@thingd/cli 0.49.5 → 0.49.7
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.
- package/dist/mcp/cluster.d.ts +2 -1
- package/dist/mcp/cluster.d.ts.map +1 -1
- package/dist/mcp/cluster.js +2 -1
- package/dist/mcp/http.d.ts.map +1 -1
- package/dist/mcp/http.js +21 -12
- package/package.json +2 -2
package/dist/mcp/cluster.d.ts
CHANGED
|
@@ -51,6 +51,7 @@ export type ThingdClusterStatus = {
|
|
|
51
51
|
peers: string[];
|
|
52
52
|
leaderElection: boolean;
|
|
53
53
|
electionMaxFailures: number;
|
|
54
|
+
consecutiveFailures: number;
|
|
54
55
|
replication: {
|
|
55
56
|
lastReplicatedSequence: number;
|
|
56
57
|
status: string;
|
|
@@ -59,7 +60,7 @@ export type ThingdClusterStatus = {
|
|
|
59
60
|
};
|
|
60
61
|
export declare function readClusterOptionsFromEnv(env: Record<string, string | undefined>): ThingdClusterOptions;
|
|
61
62
|
export declare function resolveClusterOptions(options: ThingdClusterOptions | undefined): ResolvedThingdClusterOptions;
|
|
62
|
-
export declare function getClusterStatus(cluster: ResolvedThingdClusterOptions, db: ThingD): Promise<ThingdClusterStatus>;
|
|
63
|
+
export declare function getClusterStatus(cluster: ResolvedThingdClusterOptions, db: ThingD, consecutiveFailures?: number): Promise<ThingdClusterStatus>;
|
|
63
64
|
export declare function forwardMcpRequestToLeader(cluster: ResolvedThingdClusterOptions, mcpPath: string, request: IncomingMessage, response: ServerResponse): Promise<void>;
|
|
64
65
|
export declare function findNextLeaderCandidate(cluster: ResolvedThingdClusterOptions): {
|
|
65
66
|
url: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../../src/mcp/cluster.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1C,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;AACjE,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,QAAQ,GAAG,YAAY,CAAC;AAEtE,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,sBAAsB,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,+EAA+E;IAC/E,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,IAAI,EAAE,iBAAiB,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,sBAAsB,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,wFAAwF;IACxF,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,iBAAiB,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,sBAAsB,CAAC;IAClC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,cAAc,EAAE,OAAO,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,WAAW,EACP;QACE,sBAAsB,EAAE,MAAM,CAAC;QAC/B,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,GACD,iBAAiB,CAAC;CACvB,CAAC;AAIF,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACtC,oBAAoB,CAkBtB;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,oBAAoB,GAAG,SAAS,GACxC,4BAA4B,CA0C9B;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,4BAA4B,EACrC,EAAE,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../../src/mcp/cluster.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp/cluster.js
CHANGED
|
@@ -55,7 +55,7 @@ export function resolveClusterOptions(options) {
|
|
|
55
55
|
cachedReplicationLag: 0,
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
|
-
export async function getClusterStatus(cluster, db) {
|
|
58
|
+
export async function getClusterStatus(cluster, db, consecutiveFailures = 0) {
|
|
59
59
|
let replication = "not-implemented";
|
|
60
60
|
if (cluster.mode === "follower") {
|
|
61
61
|
try {
|
|
@@ -101,6 +101,7 @@ export async function getClusterStatus(cluster, db) {
|
|
|
101
101
|
peers: cluster.peers,
|
|
102
102
|
leaderElection: cluster.leaderElection,
|
|
103
103
|
electionMaxFailures: cluster.electionMaxFailures,
|
|
104
|
+
consecutiveFailures,
|
|
104
105
|
replication,
|
|
105
106
|
};
|
|
106
107
|
}
|
package/dist/mcp/http.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/mcp/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAC;AAGjG,OAAO,EAKL,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC/B,MAAM,aAAa,CAAC;AACrB,OAAO,EAML,KAAK,oBAAoB,EAC1B,MAAM,cAAc,CAAC;AACtB,OAAO,EAA2B,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEhF,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,KAAK,CAAC,EAAE,qBAAqB,GAAG,KAAK,CAAC;IACtC,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,yBAAyB,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/mcp/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAC;AAGjG,OAAO,EAKL,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC/B,MAAM,aAAa,CAAC;AACrB,OAAO,EAML,KAAK,oBAAoB,EAC1B,MAAM,cAAc,CAAC;AACtB,OAAO,EAA2B,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEhF,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,KAAK,CAAC,EAAE,qBAAqB,GAAG,KAAK,CAAC;IACtC,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,yBAAyB,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAmBF,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,uBAAuB,CAAC,CAqDlC"}
|
package/dist/mcp/http.js
CHANGED
|
@@ -150,7 +150,7 @@ async function handleHealth(state, request, response) {
|
|
|
150
150
|
});
|
|
151
151
|
return;
|
|
152
152
|
}
|
|
153
|
-
const status = await getClusterStatus(state.cluster, state.db);
|
|
153
|
+
const status = await getClusterStatus(state.cluster, state.db, state.consecutiveReplicationFailures);
|
|
154
154
|
writeJson(response, 200, {
|
|
155
155
|
ok: true,
|
|
156
156
|
service: "thingd-mcp",
|
|
@@ -167,7 +167,7 @@ async function handleClusterStatus(state, request, response) {
|
|
|
167
167
|
});
|
|
168
168
|
return;
|
|
169
169
|
}
|
|
170
|
-
const status = await getClusterStatus(state.cluster, state.db);
|
|
170
|
+
const status = await getClusterStatus(state.cluster, state.db, state.consecutiveReplicationFailures);
|
|
171
171
|
writeJson(response, 200, status, request.method === "HEAD");
|
|
172
172
|
}
|
|
173
173
|
function handleClusterPeers(state, request, response) {
|
|
@@ -384,9 +384,12 @@ function startReplicationRunner(state) {
|
|
|
384
384
|
if (!leaderUrl) {
|
|
385
385
|
return;
|
|
386
386
|
}
|
|
387
|
-
const pullInterval = 500;
|
|
387
|
+
const pullInterval = parseInt(process.env.THINGD_CLUSTER_REPLICATION_INTERVAL_MS ?? "500", 10);
|
|
388
|
+
const abort = new AbortController();
|
|
389
|
+
state.replicationAbort = abort;
|
|
390
|
+
const signal = abort.signal;
|
|
388
391
|
async function runSync() {
|
|
389
|
-
if (state.replicationStopped) {
|
|
392
|
+
if (signal.aborted || state.replicationStopped) {
|
|
390
393
|
return;
|
|
391
394
|
}
|
|
392
395
|
const status = await state.db.get("__thingd_meta", "replication_status");
|
|
@@ -395,7 +398,7 @@ function startReplicationRunner(state) {
|
|
|
395
398
|
: 0;
|
|
396
399
|
let fetched = false;
|
|
397
400
|
for (const url of resolveLeaderUrls(state.cluster)) {
|
|
398
|
-
if (state.replicationStopped) {
|
|
401
|
+
if (signal.aborted || state.replicationStopped) {
|
|
399
402
|
return;
|
|
400
403
|
}
|
|
401
404
|
try {
|
|
@@ -418,7 +421,7 @@ function startReplicationRunner(state) {
|
|
|
418
421
|
const resData = (await response.json());
|
|
419
422
|
if (resData.success && Array.isArray(resData.events) && resData.events.length > 0) {
|
|
420
423
|
for (const ev of resData.events) {
|
|
421
|
-
if (state.replicationStopped) {
|
|
424
|
+
if (signal.aborted || state.replicationStopped) {
|
|
422
425
|
return;
|
|
423
426
|
}
|
|
424
427
|
const type = ev.type;
|
|
@@ -458,14 +461,22 @@ function startReplicationRunner(state) {
|
|
|
458
461
|
break;
|
|
459
462
|
}
|
|
460
463
|
catch (error) {
|
|
461
|
-
|
|
464
|
+
// Log replication failures periodically (once per electionMaxFailures)
|
|
465
|
+
// to avoid flooding logs when the leader is unreachable.
|
|
466
|
+
if (state.consecutiveReplicationFailures % state.cluster.electionMaxFailures === 0) {
|
|
467
|
+
console.error(`Replication from ${url} failed:`, error instanceof Error ? error.message : String(error));
|
|
468
|
+
}
|
|
462
469
|
}
|
|
463
470
|
}
|
|
464
|
-
if (state.replicationStopped) {
|
|
471
|
+
if (signal.aborted || state.replicationStopped) {
|
|
465
472
|
return;
|
|
466
473
|
}
|
|
467
474
|
if (!fetched) {
|
|
468
475
|
state.consecutiveReplicationFailures++;
|
|
476
|
+
// Print "All leader URLs exhausted" only once per failure threshold
|
|
477
|
+
if (state.consecutiveReplicationFailures === state.cluster.electionMaxFailures) {
|
|
478
|
+
console.error("All leader URLs exhausted for replication");
|
|
479
|
+
}
|
|
469
480
|
if (state.cluster.leaderElection &&
|
|
470
481
|
state.consecutiveReplicationFailures >= state.cluster.electionMaxFailures) {
|
|
471
482
|
state.consecutiveReplicationFailures = 0;
|
|
@@ -476,14 +487,11 @@ function startReplicationRunner(state) {
|
|
|
476
487
|
}
|
|
477
488
|
// leaderUrl was updated by failover; retry immediately.
|
|
478
489
|
}
|
|
479
|
-
else {
|
|
480
|
-
console.error("All leader URLs exhausted for replication");
|
|
481
|
-
}
|
|
482
490
|
}
|
|
483
491
|
else {
|
|
484
492
|
state.consecutiveReplicationFailures = 0;
|
|
485
493
|
}
|
|
486
|
-
if (!state.replicationStopped) {
|
|
494
|
+
if (!signal.aborted && !state.replicationStopped) {
|
|
487
495
|
state.replicationTimer = setTimeout(() => {
|
|
488
496
|
void runSync();
|
|
489
497
|
}, pullInterval);
|
|
@@ -494,6 +502,7 @@ function startReplicationRunner(state) {
|
|
|
494
502
|
}, pullInterval);
|
|
495
503
|
}
|
|
496
504
|
function stopReplicationRunner(state) {
|
|
505
|
+
state.replicationAbort?.abort();
|
|
497
506
|
state.replicationStopped = true;
|
|
498
507
|
if (state.replicationTimer) {
|
|
499
508
|
clearTimeout(state.replicationTimer);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thingd/cli",
|
|
3
|
-
"version": "0.49.
|
|
3
|
+
"version": "0.49.7",
|
|
4
4
|
"description": "CLI, Interactive TUI Dashboard, and MCP server for thingd — a fast object-first data engine for applications and AI agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"homepage": "https://engine.thingd.cloud",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"cli-table3": "^0.6.5",
|
|
46
46
|
"picocolors": "^1.1.1",
|
|
47
47
|
"zod": "^4.4.3",
|
|
48
|
-
"@thingd/sdk": "0.49.
|
|
48
|
+
"@thingd/sdk": "0.49.7"
|
|
49
49
|
},
|
|
50
50
|
"engines": {
|
|
51
51
|
"node": ">=24.0.0"
|