mslxdff 0.1.15 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/mslxdff.js +43 -0
  2. package/package.json +1 -1
package/bin/mslxdff.js CHANGED
@@ -200,6 +200,19 @@ if (groupCmd && groupCmd !== "create") {
200
200
  if (names.length) {
201
201
  for (const n of names) {
202
202
  console.log(`${n} (${Object.keys(all[n].members || {}).length} members)`);
203
+ // probe every member endpoint concurrently to show reachability + latency
204
+ const probes = Object.entries(all[n].members || {}).map(([id, m]) => ({
205
+ id, url: m?.url,
206
+ }));
207
+ const joined = loadGroupsJoined().find((g) => g.name === n);
208
+ if (joined?.leaderUrl) probes.push({ id: "leader", url: joined.leaderUrl });
209
+ const results = await Promise.all(probes.map(probeHealth));
210
+ const rows = results.sort((a, b) => (a.rank ?? 9) - (b.rank ?? 9));
211
+ for (const r of rows) {
212
+ const state = r.fail ? ` fail ${r.fail}` : ` ok ${r.ms}ms`;
213
+ const via = r.alt ? " (v1/health)" : "";
214
+ console.log(` ${String(r.id || "?")} ${r.url}${state}${via}`);
215
+ }
203
216
  }
204
217
  } else {
205
218
  console.log("no groups on this node");
@@ -273,6 +286,36 @@ function markJoined(entry) {
273
286
 
274
287
  function errMsg(err) { return String(err?.message || err); }
275
288
 
289
+ // Probe a member's health endpoint concurrently (v1/health preferred,
290
+ // falling back to /health). Returns { id, url, ms, rank } or { id, url, fail }.
291
+ const HEALTH_TIMEOUT_MS = 4000;
292
+ async function probeHealth({ id, url } = {}) {
293
+ if (!url) return { id, url, fail: "no url", rank: 3 };
294
+ const forBase = async (base) => {
295
+ const target = `${base}/v1/health`;
296
+ const startedAt = Date.now();
297
+ try {
298
+ const res = await fetch(target, { signal: AbortSignal.timeout(HEALTH_TIMEOUT_MS) });
299
+ if (!res.ok) return { ok: false, alt: true };
300
+ return { ok: true, alt: false, ms: Date.now() - startedAt, rank: 0 };
301
+ } catch {
302
+ return { ok: false, alt: true };
303
+ }
304
+ };
305
+ const base = String(url).replace(/\/+$/, "");
306
+ const first = await forBase(base);
307
+ if (first.ok) return { id, url: base, ms: first.ms, rank: 0 };
308
+ // v1/health 404/refused → try plain /health (older nodes)
309
+ const startedAt = Date.now();
310
+ try {
311
+ const res = await fetch(`${base}/health`, { signal: AbortSignal.timeout(HEALTH_TIMEOUT_MS) });
312
+ if (res.ok) return { id, url: base, ms: Date.now() - startedAt, rank: 1, via: "health" };
313
+ } catch {
314
+ // fall through
315
+ }
316
+ return { id, url: base, fail: "unreachable", rank: 2 };
317
+ }
318
+
276
319
  function readModelsCache(cacheFile) {
277
320
  try {
278
321
  return JSON.parse(readFileSync(cacheFile, "utf8"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mslxdff",
3
- "version": "0.1.15",
3
+ "version": "0.1.16",
4
4
  "description": "测试项目,请勿使用。",
5
5
  "type": "module",
6
6
  "bin": {