instar 0.28.66 → 0.28.67
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/cli.js +53 -0
- package/dist/cli.js.map +1 -1
- package/dist/lifeline/LifelineHealthWatchdog.d.ts +81 -0
- package/dist/lifeline/LifelineHealthWatchdog.d.ts.map +1 -0
- package/dist/lifeline/LifelineHealthWatchdog.js +122 -0
- package/dist/lifeline/LifelineHealthWatchdog.js.map +1 -0
- package/dist/lifeline/RestartOrchestrator.d.ts +73 -0
- package/dist/lifeline/RestartOrchestrator.d.ts.map +1 -0
- package/dist/lifeline/RestartOrchestrator.js +124 -0
- package/dist/lifeline/RestartOrchestrator.js.map +1 -0
- package/dist/lifeline/TelegramLifeline.d.ts +46 -0
- package/dist/lifeline/TelegramLifeline.d.ts.map +1 -1
- package/dist/lifeline/TelegramLifeline.js +319 -42
- package/dist/lifeline/TelegramLifeline.js.map +1 -1
- package/dist/lifeline/forwardErrors.d.ts +38 -0
- package/dist/lifeline/forwardErrors.d.ts.map +1 -0
- package/dist/lifeline/forwardErrors.js +53 -0
- package/dist/lifeline/forwardErrors.js.map +1 -0
- package/dist/lifeline/rateLimitState.d.ts +63 -0
- package/dist/lifeline/rateLimitState.d.ts.map +1 -0
- package/dist/lifeline/rateLimitState.js +110 -0
- package/dist/lifeline/rateLimitState.js.map +1 -0
- package/dist/lifeline/retryWithBackoff.d.ts +6 -0
- package/dist/lifeline/retryWithBackoff.d.ts.map +1 -1
- package/dist/lifeline/retryWithBackoff.js +2 -0
- package/dist/lifeline/retryWithBackoff.js.map +1 -1
- package/dist/lifeline/startupMarker.d.ts +20 -0
- package/dist/lifeline/startupMarker.d.ts.map +1 -0
- package/dist/lifeline/startupMarker.js +52 -0
- package/dist/lifeline/startupMarker.js.map +1 -0
- package/dist/lifeline/versionHandshake.d.ts +40 -0
- package/dist/lifeline/versionHandshake.d.ts.map +1 -0
- package/dist/lifeline/versionHandshake.js +45 -0
- package/dist/lifeline/versionHandshake.js.map +1 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +58 -1
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +76 -76
- package/upgrades/0.28.67.md +58 -0
- package/upgrades/side-effects/0.28.65.md +59 -0
- package/upgrades/side-effects/lifeline-self-restart-stage-b.md +129 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RestartOrchestrator — single-owner state machine for lifeline self-restart.
|
|
3
|
+
*
|
|
4
|
+
* Multiple initiators may fire concurrently:
|
|
5
|
+
* - LifelineHealthWatchdog (tick-based)
|
|
6
|
+
* - ForwardVersionSkewError handler (event-based)
|
|
7
|
+
* - SIGTERM handler (external, e.g., `instar lifeline restart`)
|
|
8
|
+
*
|
|
9
|
+
* All three route through `requestRestart()`. The orchestrator serializes
|
|
10
|
+
* them: only the first transition from `idle` proceeds; subsequent requests
|
|
11
|
+
* are logged and suppressed.
|
|
12
|
+
*
|
|
13
|
+
* State machine: idle → quiescing → persisting → exiting (terminal)
|
|
14
|
+
*
|
|
15
|
+
* Step 1 (quiesce) halts Telegram polling, replay loops, and the watchdog
|
|
16
|
+
* BEFORE any persist, so the queue snapshot is causally consistent.
|
|
17
|
+
*
|
|
18
|
+
* The `exitFn` is injected so tests can assert the sequence without
|
|
19
|
+
* terminating the test runner. Production injects `process.exit`.
|
|
20
|
+
*/
|
|
21
|
+
import { DegradationReporter } from '../monitoring/DegradationReporter.js';
|
|
22
|
+
export type RestartState = 'idle' | 'quiescing' | 'persisting' | 'exiting';
|
|
23
|
+
export interface RestartRequest {
|
|
24
|
+
reason: string;
|
|
25
|
+
bucket: 'watchdog' | 'versionSkew';
|
|
26
|
+
context?: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
export interface OrchestratorDeps {
|
|
29
|
+
/** Halt polling, replay interval, watchdog timer; abort in-flight forwards. Returns when drained. */
|
|
30
|
+
quiesce: () => Promise<void>;
|
|
31
|
+
/** Persist all state files atomically. Returns when all writes complete. */
|
|
32
|
+
persistAll: () => Promise<void>;
|
|
33
|
+
/** Called to exit the process. Production: process.exit. Tests: spy. */
|
|
34
|
+
exitFn: (code: number) => void;
|
|
35
|
+
/** Whether this process runs under launchd (true) or dev (false). */
|
|
36
|
+
isSupervised: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Returns true if a shadow-install update is in progress. The orchestrator
|
|
39
|
+
* will defer the restart by one tick if so, per spec §Shadow-install coordination.
|
|
40
|
+
* Tests can return a fixed value.
|
|
41
|
+
*/
|
|
42
|
+
isShadowInstallUpdating?: () => boolean;
|
|
43
|
+
/** Optional DegradationReporter override for tests. */
|
|
44
|
+
reporter?: DegradationReporter;
|
|
45
|
+
/** Maximum ms to wait for persistAll before hard-killing. */
|
|
46
|
+
persistBudgetMs?: number;
|
|
47
|
+
/** Hard-kill timeout — if persist hangs this long, call exitFn(1). */
|
|
48
|
+
hardKillMs?: number;
|
|
49
|
+
/** Defer duration if shadow-install lockfile is present. Default 30000 (one watchdog tick). */
|
|
50
|
+
shadowInstallDeferMs?: number;
|
|
51
|
+
}
|
|
52
|
+
export declare class RestartOrchestrator {
|
|
53
|
+
private readonly deps;
|
|
54
|
+
private _state;
|
|
55
|
+
private readonly reporter;
|
|
56
|
+
private readonly persistBudgetMs;
|
|
57
|
+
private readonly hardKillMs;
|
|
58
|
+
lastSuppressed: {
|
|
59
|
+
reason: string;
|
|
60
|
+
currentState: RestartState;
|
|
61
|
+
} | null;
|
|
62
|
+
constructor(deps: OrchestratorDeps);
|
|
63
|
+
get state(): RestartState;
|
|
64
|
+
/**
|
|
65
|
+
* Attempt to initiate a restart. Only proceeds if currently idle.
|
|
66
|
+
* Returns a promise that resolves only if the request was suppressed
|
|
67
|
+
* (process didn't exit); otherwise the process exits before resolve.
|
|
68
|
+
*/
|
|
69
|
+
requestRestart(req: RestartRequest): Promise<'suppressed' | 'proceeded'>;
|
|
70
|
+
/** Test helper: reset state to idle without exiting. Only safe in tests. */
|
|
71
|
+
_resetForTesting(): void;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=RestartOrchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RestartOrchestrator.d.ts","sourceRoot":"","sources":["../../src/lifeline/RestartOrchestrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAE3E,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,WAAW,GAAG,YAAY,GAAG,SAAS,CAAC;AAE3E,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,UAAU,GAAG,aAAa,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,gBAAgB;IAC/B,qGAAqG;IACrG,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,4EAA4E;IAC5E,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,wEAAwE;IACxE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,qEAAqE;IACrE,YAAY,EAAE,OAAO,CAAC;IACtB;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,MAAM,OAAO,CAAC;IACxC,uDAAuD;IACvD,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,6DAA6D;IAC7D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+FAA+F;IAC/F,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,qBAAa,mBAAmB;IAOlB,OAAO,CAAC,QAAQ,CAAC,IAAI;IANjC,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;IAC/C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAC7B,cAAc,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,YAAY,CAAA;KAAE,GAAG,IAAI,CAAQ;gBAEvD,IAAI,EAAE,gBAAgB;IAMnD,IAAI,KAAK,IAAI,YAAY,CAExB;IAED;;;;OAIG;IACG,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,GAAG,WAAW,CAAC;IAuF9E,4EAA4E;IAC5E,gBAAgB,IAAI,IAAI;CAIzB"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RestartOrchestrator — single-owner state machine for lifeline self-restart.
|
|
3
|
+
*
|
|
4
|
+
* Multiple initiators may fire concurrently:
|
|
5
|
+
* - LifelineHealthWatchdog (tick-based)
|
|
6
|
+
* - ForwardVersionSkewError handler (event-based)
|
|
7
|
+
* - SIGTERM handler (external, e.g., `instar lifeline restart`)
|
|
8
|
+
*
|
|
9
|
+
* All three route through `requestRestart()`. The orchestrator serializes
|
|
10
|
+
* them: only the first transition from `idle` proceeds; subsequent requests
|
|
11
|
+
* are logged and suppressed.
|
|
12
|
+
*
|
|
13
|
+
* State machine: idle → quiescing → persisting → exiting (terminal)
|
|
14
|
+
*
|
|
15
|
+
* Step 1 (quiesce) halts Telegram polling, replay loops, and the watchdog
|
|
16
|
+
* BEFORE any persist, so the queue snapshot is causally consistent.
|
|
17
|
+
*
|
|
18
|
+
* The `exitFn` is injected so tests can assert the sequence without
|
|
19
|
+
* terminating the test runner. Production injects `process.exit`.
|
|
20
|
+
*/
|
|
21
|
+
import { DegradationReporter } from '../monitoring/DegradationReporter.js';
|
|
22
|
+
export class RestartOrchestrator {
|
|
23
|
+
deps;
|
|
24
|
+
_state = 'idle';
|
|
25
|
+
reporter;
|
|
26
|
+
persistBudgetMs;
|
|
27
|
+
hardKillMs;
|
|
28
|
+
lastSuppressed = null;
|
|
29
|
+
constructor(deps) {
|
|
30
|
+
this.deps = deps;
|
|
31
|
+
this.reporter = deps.reporter ?? DegradationReporter.getInstance();
|
|
32
|
+
this.persistBudgetMs = deps.persistBudgetMs ?? 2000;
|
|
33
|
+
this.hardKillMs = deps.hardKillMs ?? 5000;
|
|
34
|
+
}
|
|
35
|
+
get state() {
|
|
36
|
+
return this._state;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Attempt to initiate a restart. Only proceeds if currently idle.
|
|
40
|
+
* Returns a promise that resolves only if the request was suppressed
|
|
41
|
+
* (process didn't exit); otherwise the process exits before resolve.
|
|
42
|
+
*/
|
|
43
|
+
async requestRestart(req) {
|
|
44
|
+
// Synchronous guard — set BEFORE any await to prevent re-entry.
|
|
45
|
+
if (this._state !== 'idle') {
|
|
46
|
+
this.lastSuppressed = { reason: req.reason, currentState: this._state };
|
|
47
|
+
console.log(`[RestartOrchestrator] restart-request-suppressed ` +
|
|
48
|
+
`reason=${req.reason} currentState=${this._state}`);
|
|
49
|
+
return 'suppressed';
|
|
50
|
+
}
|
|
51
|
+
this._state = 'quiescing';
|
|
52
|
+
// Fire-and-forget degradation event (best-effort, budget 500ms).
|
|
53
|
+
try {
|
|
54
|
+
await Promise.race([
|
|
55
|
+
Promise.resolve(this.reporter.report({
|
|
56
|
+
feature: 'TelegramLifeline.selfRestart',
|
|
57
|
+
primary: `exit-for-restart (${req.reason})`,
|
|
58
|
+
fallback: 'launchd will respawn',
|
|
59
|
+
reason: req.reason,
|
|
60
|
+
impact: 'Lifeline process exits; message queue persisted; respawned by launchd.',
|
|
61
|
+
})),
|
|
62
|
+
new Promise(resolve => setTimeout(resolve, 500)),
|
|
63
|
+
]);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// best-effort; never block restart on telemetry failure
|
|
67
|
+
}
|
|
68
|
+
// Shadow-install coordination: if the updater is mid-`npm i`, defer by
|
|
69
|
+
// one tick rather than respawn against a half-written tree. Spec §Shadow-
|
|
70
|
+
// install coordination. A deferred restart re-enters idle and can be
|
|
71
|
+
// re-requested on the next tick.
|
|
72
|
+
if (this.deps.isShadowInstallUpdating?.()) {
|
|
73
|
+
console.warn(`[RestartOrchestrator] restart-deferred-shadow-updating ` +
|
|
74
|
+
`reason=${req.reason} — retry after tick`);
|
|
75
|
+
this._state = 'idle';
|
|
76
|
+
return 'suppressed';
|
|
77
|
+
}
|
|
78
|
+
// Unsupervised mode: log loud + stop here. Never call exitFn in dev/test.
|
|
79
|
+
if (!this.deps.isSupervised) {
|
|
80
|
+
console.warn(`[RestartOrchestrator] would restart (trigger=${req.reason}) but unsupervised; ` +
|
|
81
|
+
`skipping exit. set INSTAR_SUPERVISED=1 to enable.`);
|
|
82
|
+
this._state = 'idle';
|
|
83
|
+
return 'suppressed';
|
|
84
|
+
}
|
|
85
|
+
// Step 1: quiesce — halt mutations before persist.
|
|
86
|
+
try {
|
|
87
|
+
await Promise.race([
|
|
88
|
+
this.deps.quiesce(),
|
|
89
|
+
new Promise(resolve => setTimeout(resolve, 1000)),
|
|
90
|
+
]);
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
console.error(`[RestartOrchestrator] quiesce error (continuing): ${err}`);
|
|
94
|
+
}
|
|
95
|
+
// Step 2: persist. Budget 2s. Hard-kill fallback 5s from now.
|
|
96
|
+
this._state = 'persisting';
|
|
97
|
+
const hardKill = setTimeout(() => {
|
|
98
|
+
console.error('[RestartOrchestrator] hard-kill: persist exceeded budget');
|
|
99
|
+
this.deps.exitFn(1);
|
|
100
|
+
}, this.hardKillMs);
|
|
101
|
+
if (typeof hardKill.unref === 'function')
|
|
102
|
+
hardKill.unref();
|
|
103
|
+
try {
|
|
104
|
+
await Promise.race([
|
|
105
|
+
this.deps.persistAll(),
|
|
106
|
+
new Promise(resolve => setTimeout(resolve, this.persistBudgetMs)),
|
|
107
|
+
]);
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
console.error(`[RestartOrchestrator] persistAll error (continuing to exit): ${err}`);
|
|
111
|
+
}
|
|
112
|
+
// Step 3: exit.
|
|
113
|
+
this._state = 'exiting';
|
|
114
|
+
clearTimeout(hardKill);
|
|
115
|
+
this.deps.exitFn(0);
|
|
116
|
+
return 'proceeded';
|
|
117
|
+
}
|
|
118
|
+
/** Test helper: reset state to idle without exiting. Only safe in tests. */
|
|
119
|
+
_resetForTesting() {
|
|
120
|
+
this._state = 'idle';
|
|
121
|
+
this.lastSuppressed = null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=RestartOrchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RestartOrchestrator.js","sourceRoot":"","sources":["../../src/lifeline/RestartOrchestrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAmC3E,MAAM,OAAO,mBAAmB;IAOD;IANrB,MAAM,GAAiB,MAAM,CAAC;IACrB,QAAQ,CAAsB;IAC9B,eAAe,CAAS;IACxB,UAAU,CAAS;IAC7B,cAAc,GAA0D,IAAI,CAAC;IAEpF,YAA6B,IAAsB;QAAtB,SAAI,GAAJ,IAAI,CAAkB;QACjD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,mBAAmB,CAAC,WAAW,EAAE,CAAC;QACnE,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC;QACpD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC;IAC5C,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,cAAc,CAAC,GAAmB;QACtC,gEAAgE;QAChE,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC,cAAc,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;YACxE,OAAO,CAAC,GAAG,CACT,mDAAmD;gBACnD,UAAU,GAAG,CAAC,MAAM,iBAAiB,IAAI,CAAC,MAAM,EAAE,CACnD,CAAC;YACF,OAAO,YAAY,CAAC;QACtB,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC;QAE1B,iEAAiE;QACjE,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,IAAI,CAAC;gBACjB,OAAO,CAAC,OAAO,CACb,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;oBACnB,OAAO,EAAE,8BAA8B;oBACvC,OAAO,EAAE,qBAAqB,GAAG,CAAC,MAAM,GAAG;oBAC3C,QAAQ,EAAE,sBAAsB;oBAChC,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,MAAM,EAAE,wEAAwE;iBACjF,CAAC,CACH;gBACD,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;aACvD,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,wDAAwD;QAC1D,CAAC;QAED,uEAAuE;QACvE,0EAA0E;QAC1E,qEAAqE;QACrE,iCAAiC;QACjC,IAAI,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,EAAE,EAAE,CAAC;YAC1C,OAAO,CAAC,IAAI,CACV,yDAAyD;gBACzD,UAAU,GAAG,CAAC,MAAM,qBAAqB,CAC1C,CAAC;YACF,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;YACrB,OAAO,YAAY,CAAC;QACtB,CAAC;QAED,0EAA0E;QAC1E,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YAC5B,OAAO,CAAC,IAAI,CACV,gDAAgD,GAAG,CAAC,MAAM,sBAAsB;gBAChF,mDAAmD,CACpD,CAAC;YACF,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;YACrB,OAAO,YAAY,CAAC;QACtB,CAAC;QAED,mDAAmD;QACnD,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,IAAI,CAAC;gBACjB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;gBACnB,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;aACxD,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,qDAAqD,GAAG,EAAE,CAAC,CAAC;QAC5E,CAAC;QAED,8DAA8D;QAC9D,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC;QAC3B,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE;YAC/B,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;YAC1E,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACtB,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACpB,IAAI,OAAO,QAAQ,CAAC,KAAK,KAAK,UAAU;YAAE,QAAQ,CAAC,KAAK,EAAE,CAAC;QAE3D,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,IAAI,CAAC;gBACjB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;gBACtB,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;aACxE,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,gEAAgE,GAAG,EAAE,CAAC,CAAC;QACvF,CAAC;QAED,gBAAgB;QAChB,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACxB,YAAY,CAAC,QAAQ,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACpB,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,4EAA4E;IAC5E,gBAAgB;QACd,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;IAC7B,CAAC;CACF"}
|
|
@@ -42,6 +42,31 @@ export declare class TelegramLifeline {
|
|
|
42
42
|
* Start the lifeline — begins Telegram polling and server supervision.
|
|
43
43
|
*/
|
|
44
44
|
start(): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Stop all in-flight / scheduled mutation sources so the queue snapshot
|
|
47
|
+
* is consistent when persisted.
|
|
48
|
+
*/
|
|
49
|
+
private quiesceEverything;
|
|
50
|
+
/**
|
|
51
|
+
* Install the restart orchestrator and watchdog. Called from start().
|
|
52
|
+
*
|
|
53
|
+
* The orchestrator owns the process.exit call. The watchdog requests
|
|
54
|
+
* restarts via the orchestrator on threshold crossings, subject to
|
|
55
|
+
* rate-limit state on disk.
|
|
56
|
+
*/
|
|
57
|
+
private installOrchestratorAndWatchdog;
|
|
58
|
+
/** Extract oldest queue item's enqueue timestamp as ms, if any. */
|
|
59
|
+
private oldestQueueItemEnqueuedAt;
|
|
60
|
+
/** Read config overrides for watchdog thresholds. */
|
|
61
|
+
private loadThresholdOverrides;
|
|
62
|
+
/** Persist rate-limit state. Safe to call during orchestrator persist. */
|
|
63
|
+
private persistRateLimitSafe;
|
|
64
|
+
/**
|
|
65
|
+
* Unified restart initiator: checks rate limit, writes history, then
|
|
66
|
+
* calls the orchestrator. Used by both the watchdog tick (bucket=watchdog)
|
|
67
|
+
* and the version-skew handler (bucket=versionSkew).
|
|
68
|
+
*/
|
|
69
|
+
private initiateRestart;
|
|
45
70
|
/**
|
|
46
71
|
* Flush stale Telegram connections on startup.
|
|
47
72
|
* After a hard kill or sleep/wake, a previous long-poll getUpdates call may
|
|
@@ -86,7 +111,28 @@ export declare class TelegramLifeline {
|
|
|
86
111
|
*/
|
|
87
112
|
private static readonly FORWARD_ATTEMPTS;
|
|
88
113
|
private static readonly FORWARD_BACKOFF_BASE_MS;
|
|
114
|
+
/**
|
|
115
|
+
* `legacyStrict` — if a pre-Stage-B server strictly validates JSON and
|
|
116
|
+
* rejects the unknown `lifelineVersion` field with 400, the lifeline
|
|
117
|
+
* falls back to omitting it and pins this flag for the session.
|
|
118
|
+
*/
|
|
119
|
+
private legacyStrictServer;
|
|
120
|
+
/** Full semver of this lifeline, read once at construction. */
|
|
121
|
+
private readonly lifelineVersion;
|
|
89
122
|
private forwardToServer;
|
|
123
|
+
/**
|
|
124
|
+
* Handle a 426 response from the server. Validates the response body's
|
|
125
|
+
* `serverVersion` differs from this lifeline's, then requests restart
|
|
126
|
+
* through the orchestrator. If the body is malformed or the versions
|
|
127
|
+
* match (loopback impostor), treat as transient.
|
|
128
|
+
*/
|
|
129
|
+
private handleVersionSkew;
|
|
130
|
+
/** Watchdog-tracked counters/state. */
|
|
131
|
+
private consecutiveForwardFailures;
|
|
132
|
+
private lastForwardSuccessAt;
|
|
133
|
+
private conflict409StartedAt;
|
|
134
|
+
private orchestrator;
|
|
135
|
+
private watchdog;
|
|
90
136
|
private handleLifelineCommand;
|
|
91
137
|
/** Max times a message can fail replay before being dropped. */
|
|
92
138
|
private static readonly MAX_REPLAY_FAILURES;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TelegramLifeline.d.ts","sourceRoot":"","sources":["../../src/lifeline/TelegramLifeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;
|
|
1
|
+
{"version":3,"file":"TelegramLifeline.d.ts","sourceRoot":"","sources":["../../src/lifeline/TelegramLifeline.ts"],"names":[],"mappings":"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"}
|