mslxdff 0.1.24 → 0.1.25

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 +50 -13
  2. package/package.json +1 -1
package/bin/mslxdff.js CHANGED
@@ -253,24 +253,60 @@ if (groupCmd && groupCmd !== "create") {
253
253
  continue;
254
254
  }
255
255
  }
256
- console.log(`${g.name} (${Object.keys(members).length} members)`);
257
- // probe every member endpoint concurrently for reachability + latency
258
- const probes = Object.entries(members).map(([id, m]) => ({ id, url: m?.url || id }));
259
- if (!isLeader && g.leaderUrl && !probes.some((p) => p.url === g.leaderUrl)) {
260
- probes.push({ id: "leader", url: g.leaderUrl });
261
- }
262
- const results = await Promise.all(probes.map(probeHealth));
263
- const rows = results.sort((a, b) => (a.rank ?? 9) - (b.rank ?? 9));
264
- for (const r of rows) {
256
+ const entries = Object.entries(members).filter(([id]) => id !== "leader");
257
+ console.log(`${g.name} (${entries.length} member${entries.length === 1 ? "" : "s"})`);
258
+ // probe every member endpoint concurrently for reachability + latency;
259
+ // display order = state order so the sequence numbers stay stable for -group remove
260
+ const probes = await Promise.all(
261
+ entries.map(([id, m]) => probeHealth({ id, url: m?.url || id }))
262
+ );
263
+ const leaderEntry = members.leader ? Object.entries(members).find(([id]) => id === "leader") : null;
264
+ const leaderProbe = leaderEntry ? await probeHealth({ id: "leader", url: leaderEntry[1].url }) : null;
265
+ const display = leaderProbe ? [...probes, leaderProbe] : probes;
266
+ let seq = 0;
267
+ for (const r of display) {
265
268
  const state = r.fail ? `fail ${r.fail}` : `ok ${r.ms}ms`;
266
- const label = r.id && r.id !== r.url ? r.id + " " : "";
267
- console.log(` ${label}${r.url} ${state}`);
269
+ if (r.id === "leader") {
270
+ console.log(` leader ${r.url} ${state}`);
271
+ continue;
272
+ }
273
+ seq += 1;
274
+ const label = r.id && r.id !== r.url ? ` [${r.id}]` : "";
275
+ console.log(` ${seq}. ${r.url}${label} ${state}`);
268
276
  }
269
277
  }
270
278
  console.log(`\njoined groups (${joinedList.length}):`);
271
279
  for (const g of joinedList) console.log(` ${g.name} ${g.leaderUrl || "(this node is the leader)"}`);
280
+ } else if (action === "remove" && a) {
281
+ // leader-only: kick a member by its list sequence number (1-based, leader excluded)
282
+ const seq = Number(a);
283
+ if (!Number.isInteger(seq) || seq < 1) {
284
+ console.error(`usage: mslxdff -group remove <seq>`);
285
+ process.exit(1);
286
+ }
287
+ const joined = loadGroupsJoined().find((g) => !g.leaderUrl);
288
+ if (!joined) {
289
+ console.error("group remove requires being the leader — this node leads no group");
290
+ process.exit(1);
291
+ }
292
+ const members = groups.list()[joined.name]?.members || {};
293
+ const entries = Object.entries(members).filter(([id]) => id !== "leader");
294
+ const target = entries[seq - 1];
295
+ if (!target) {
296
+ console.error(`member #${seq} not found — group "${joined.name}" has ${entries.length} member(s)`);
297
+ process.exit(1);
298
+ }
299
+ const [id, m] = target;
300
+ try {
301
+ const removed = groups.removeMember(joined.name, { url: m.url });
302
+ if (removed) console.log(`removed ${m.url} from "${joined.name}"`);
303
+ else console.log(`member ${m.url} already gone from "${joined.name}"`);
304
+ } catch (err) {
305
+ console.error(`remove failed: ${errMsg(err)}`);
306
+ process.exit(1);
307
+ }
272
308
  } else {
273
- console.error("usage: mslxdff -creategroup <name> | -group sync | -group leave <name> | -group list");
309
+ console.error("usage: mslxdff -group sync | -group leave <name> | -group list | -group remove <seq> | -creategroup <name>");
274
310
  }
275
311
  process.exit(0);
276
312
  }
@@ -714,7 +750,8 @@ Usage:
714
750
  mslxdff -addtogroup <leader-host> <name> join a group via its leader host (default port 8989)
715
751
  mslxdff -group sync pull the freshest member list for all joined groups
716
752
  mslxdff -group leave <name> leave a group (removes its members from this node)
717
- mslxdff -group list list groups on this node
753
+ mslxdff -group list list groups on this node (numbered members)
754
+ mslxdff -group remove <seq> leader only: kick a member by its list sequence number
718
755
  mslxdff -leavegroup leave every joined group as a member (leaders: use -delgroup)
719
756
  mslxdff -delgroup <name> disband a group this node leads (deletes it and its members)
720
757
  mslxdff -resetban [ip] clear join-failure bans (all, or one ip)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mslxdff",
3
- "version": "0.1.24",
3
+ "version": "0.1.25",
4
4
  "description": "测试项目,请勿使用。",
5
5
  "type": "module",
6
6
  "bin": {