@relkit/supervisor 0.0.0
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/LICENSE +21 -0
- package/README.md +5 -0
- package/dist/candidate-output.d.ts +4 -0
- package/dist/candidate-output.d.ts.map +1 -0
- package/dist/candidate-output.js +60 -0
- package/dist/candidate-output.js.map +1 -0
- package/dist/candidate-process.d.ts +19 -0
- package/dist/candidate-process.d.ts.map +1 -0
- package/dist/candidate-process.js +105 -0
- package/dist/candidate-process.js.map +1 -0
- package/dist/candidate-types.d.ts +56 -0
- package/dist/candidate-types.d.ts.map +1 -0
- package/dist/candidate-types.js +2 -0
- package/dist/candidate-types.js.map +1 -0
- package/dist/candidate.d.ts +10 -0
- package/dist/candidate.d.ts.map +1 -0
- package/dist/candidate.js +116 -0
- package/dist/candidate.js.map +1 -0
- package/dist/drain-cleanup.d.ts +8 -0
- package/dist/drain-cleanup.d.ts.map +1 -0
- package/dist/drain-cleanup.js +28 -0
- package/dist/drain-cleanup.js.map +1 -0
- package/dist/drain-state.d.ts +4 -0
- package/dist/drain-state.d.ts.map +1 -0
- package/dist/drain-state.js +26 -0
- package/dist/drain-state.js.map +1 -0
- package/dist/drain-types.d.ts +61 -0
- package/dist/drain-types.d.ts.map +1 -0
- package/dist/drain-types.js +2 -0
- package/dist/drain-types.js.map +1 -0
- package/dist/drain.d.ts +35 -0
- package/dist/drain.d.ts.map +1 -0
- package/dist/drain.js +178 -0
- package/dist/drain.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/observability-records.d.ts +9 -0
- package/dist/observability-records.d.ts.map +1 -0
- package/dist/observability-records.js +71 -0
- package/dist/observability-records.js.map +1 -0
- package/dist/observability-types.d.ts +18 -0
- package/dist/observability-types.d.ts.map +1 -0
- package/dist/observability-types.js +2 -0
- package/dist/observability-types.js.map +1 -0
- package/dist/observability.d.ts +5 -0
- package/dist/observability.d.ts.map +1 -0
- package/dist/observability.js +46 -0
- package/dist/observability.js.map +1 -0
- package/dist/proxy-forward.d.ts +5 -0
- package/dist/proxy-forward.d.ts.map +1 -0
- package/dist/proxy-forward.js +43 -0
- package/dist/proxy-forward.js.map +1 -0
- package/dist/proxy.d.ts +45 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +125 -0
- package/dist/proxy.js.map +1 -0
- package/dist/state-machine-telemetry.d.ts +14 -0
- package/dist/state-machine-telemetry.d.ts.map +1 -0
- package/dist/state-machine-telemetry.js +79 -0
- package/dist/state-machine-telemetry.js.map +1 -0
- package/dist/state-machine-types.d.ts +53 -0
- package/dist/state-machine-types.d.ts.map +1 -0
- package/dist/state-machine-types.js +30 -0
- package/dist/state-machine-types.js.map +1 -0
- package/dist/state-machine.d.ts +36 -0
- package/dist/state-machine.d.ts.map +1 -0
- package/dist/state-machine.js +144 -0
- package/dist/state-machine.js.map +1 -0
- package/dist/verification-http.d.ts +4 -0
- package/dist/verification-http.d.ts.map +1 -0
- package/dist/verification-http.js +49 -0
- package/dist/verification-http.js.map +1 -0
- package/dist/verification-probe.d.ts +12 -0
- package/dist/verification-probe.d.ts.map +1 -0
- package/dist/verification-probe.js +106 -0
- package/dist/verification-probe.js.map +1 -0
- package/dist/verification-types.d.ts +40 -0
- package/dist/verification-types.d.ts.map +1 -0
- package/dist/verification-types.js +11 -0
- package/dist/verification-types.js.map +1 -0
- package/dist/verification.d.ts +5 -0
- package/dist/verification.d.ts.map +1 -0
- package/dist/verification.js +54 -0
- package/dist/verification.js.map +1 -0
- package/dist/watcher.d.ts +48 -0
- package/dist/watcher.d.ts.map +1 -0
- package/dist/watcher.js +135 -0
- package/dist/watcher.js.map +1 -0
- package/package.json +40 -0
package/dist/drain.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { SupervisorCandidateToken } from "./state-machine-types.js";
|
|
2
|
+
import { type SupervisorDrainLease, type SupervisorDrainOptions, type SupervisorDrainReport, type SupervisorDrainWorkOptions } from "./drain-types.js";
|
|
3
|
+
export * from "./drain-types.js";
|
|
4
|
+
export { drainPreviousGeneration } from "./drain-state.js";
|
|
5
|
+
export declare const DEFAULT_SUPERVISOR_DRAIN_TIMEOUT_MS = 1000;
|
|
6
|
+
export declare class SupervisorDrainError extends Error {
|
|
7
|
+
readonly code: "RELKIT_DRAIN_STATE_INVALID" | "RELKIT_DRAIN_TOKEN_MISMATCH";
|
|
8
|
+
constructor(code: SupervisorDrainError["code"], message: string);
|
|
9
|
+
}
|
|
10
|
+
/** Owns admission and bounded cleanup for one retired generation token. */
|
|
11
|
+
export declare class SupervisorGenerationDrain {
|
|
12
|
+
readonly token: SupervisorCandidateToken;
|
|
13
|
+
readonly deadlineMs: number;
|
|
14
|
+
private readonly now;
|
|
15
|
+
private readonly candidate;
|
|
16
|
+
private readonly providers;
|
|
17
|
+
private readonly onReport;
|
|
18
|
+
private readonly work;
|
|
19
|
+
private readonly idleWaiters;
|
|
20
|
+
private nextWorkId;
|
|
21
|
+
private accepting;
|
|
22
|
+
private shutdown;
|
|
23
|
+
constructor(options: SupervisorDrainOptions);
|
|
24
|
+
get inFlight(): number;
|
|
25
|
+
get acceptingWork(): boolean;
|
|
26
|
+
/** Creates a generation-scoped cancellation signal; returns undefined after drain starts. */
|
|
27
|
+
track(token: SupervisorCandidateToken, options?: SupervisorDrainWorkOptions): SupervisorDrainLease | undefined;
|
|
28
|
+
/** Waits for work, interrupts the remainder, and releases resources at one bounded deadline. */
|
|
29
|
+
drain(): Promise<SupervisorDrainReport>;
|
|
30
|
+
private run;
|
|
31
|
+
private release;
|
|
32
|
+
private waitForIdle;
|
|
33
|
+
}
|
|
34
|
+
export declare function createSupervisorDrain(options: SupervisorDrainOptions): SupervisorGenerationDrain;
|
|
35
|
+
//# sourceMappingURL=drain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drain.d.ts","sourceRoot":"","sources":["../src/drain.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAI1B,KAAK,0BAA0B,EAChC,MAAM,kBAAkB,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,eAAO,MAAM,mCAAmC,OAAQ,CAAC;AAKzD,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,IAAI,EAAE,4BAA4B,GAAG,6BAA6B,CAAC;gBAChE,IAAI,EAAE,oBAAoB,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM;CAKhE;AACD,2EAA2E;AAC3E,qBAAa,yBAAyB;IACpC,QAAQ,CAAC,KAAK,EAAE,wBAAwB,CAAC;IACzC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsC;IAChE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqC;IAC/D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAC9D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkC;IACvD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;IACrD,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,QAAQ,CAA6C;gBACjD,OAAO,EAAE,sBAAsB;IAmB3C,IAAI,QAAQ,IAAI,MAAM,CAErB;IACD,IAAI,aAAa,IAAI,OAAO,CAE3B;IACD,6FAA6F;IAC7F,KAAK,CACH,KAAK,EAAE,wBAAwB,EAC/B,OAAO,GAAE,0BAA+B,GACvC,oBAAoB,GAAG,SAAS;IAenC,gGAAgG;IAChG,KAAK,IAAI,OAAO,CAAC,qBAAqB,CAAC;YAKzB,GAAG;IAsEjB,OAAO,CAAC,OAAO;IAOf,OAAO,CAAC,WAAW;CAepB;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,yBAAyB,CAEhG"}
|
package/dist/drain.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { closeAction, resourceAction } from "./drain-cleanup.js";
|
|
2
|
+
import { validateSupervisorToken } from "./state-machine-telemetry.js";
|
|
3
|
+
import {} from "./drain-types.js";
|
|
4
|
+
export * from "./drain-types.js";
|
|
5
|
+
export { drainPreviousGeneration } from "./drain-state.js";
|
|
6
|
+
export const DEFAULT_SUPERVISOR_DRAIN_TIMEOUT_MS = 1_000;
|
|
7
|
+
export class SupervisorDrainError extends Error {
|
|
8
|
+
code;
|
|
9
|
+
constructor(code, message) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = "SupervisorDrainError";
|
|
12
|
+
this.code = code;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** Owns admission and bounded cleanup for one retired generation token. */
|
|
16
|
+
export class SupervisorGenerationDrain {
|
|
17
|
+
token;
|
|
18
|
+
deadlineMs;
|
|
19
|
+
now;
|
|
20
|
+
candidate;
|
|
21
|
+
providers;
|
|
22
|
+
onReport;
|
|
23
|
+
work = new Map();
|
|
24
|
+
idleWaiters = new Set();
|
|
25
|
+
nextWorkId = 0;
|
|
26
|
+
accepting = true;
|
|
27
|
+
shutdown;
|
|
28
|
+
constructor(options) {
|
|
29
|
+
validateSupervisorToken(options.token);
|
|
30
|
+
if (options.candidate !== undefined && !sameToken(options.candidate.token, options.token)) {
|
|
31
|
+
throw new SupervisorDrainError("RELKIT_DRAIN_TOKEN_MISMATCH", "The candidate token does not match the retired generation.");
|
|
32
|
+
}
|
|
33
|
+
const deadlineMs = options.deadlineMs ?? DEFAULT_SUPERVISOR_DRAIN_TIMEOUT_MS;
|
|
34
|
+
if (!Number.isSafeInteger(deadlineMs) || deadlineMs < 0) {
|
|
35
|
+
throw new RangeError("Supervisor drain deadline must be a non-negative safe integer.");
|
|
36
|
+
}
|
|
37
|
+
this.token = Object.freeze({ ...options.token });
|
|
38
|
+
this.deadlineMs = deadlineMs;
|
|
39
|
+
this.now = options.now ?? Date.now;
|
|
40
|
+
this.candidate = options.candidate;
|
|
41
|
+
this.providers = Object.freeze([...(options.providers ?? [])]);
|
|
42
|
+
this.onReport = options.onReport;
|
|
43
|
+
}
|
|
44
|
+
get inFlight() {
|
|
45
|
+
return this.work.size;
|
|
46
|
+
}
|
|
47
|
+
get acceptingWork() {
|
|
48
|
+
return this.accepting;
|
|
49
|
+
}
|
|
50
|
+
/** Creates a generation-scoped cancellation signal; returns undefined after drain starts. */
|
|
51
|
+
track(token, options = {}) {
|
|
52
|
+
validateSupervisorToken(token);
|
|
53
|
+
if (!this.accepting || !sameToken(token, this.token))
|
|
54
|
+
return undefined;
|
|
55
|
+
const id = ++this.nextWorkId;
|
|
56
|
+
const tracked = {
|
|
57
|
+
controller: new AbortController(),
|
|
58
|
+
interrupt: options.interrupt,
|
|
59
|
+
};
|
|
60
|
+
this.work.set(id, tracked);
|
|
61
|
+
return Object.freeze({
|
|
62
|
+
token: this.token,
|
|
63
|
+
signal: tracked.controller.signal,
|
|
64
|
+
release: () => this.release(id),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/** Waits for work, interrupts the remainder, and releases resources at one bounded deadline. */
|
|
68
|
+
drain() {
|
|
69
|
+
this.shutdown ??= this.run();
|
|
70
|
+
return this.shutdown;
|
|
71
|
+
}
|
|
72
|
+
async run() {
|
|
73
|
+
this.accepting = false;
|
|
74
|
+
const startedAt = this.now();
|
|
75
|
+
const deadlineAt = startedAt + this.deadlineMs;
|
|
76
|
+
const initialInFlight = this.work.size;
|
|
77
|
+
let interrupted = 0;
|
|
78
|
+
let timedOut = !(await this.waitForIdle(deadlineAt));
|
|
79
|
+
if (timedOut) {
|
|
80
|
+
const pending = [...this.work.values()];
|
|
81
|
+
for (const work of pending) {
|
|
82
|
+
if (work.controller.signal.aborted)
|
|
83
|
+
continue;
|
|
84
|
+
work.controller.abort(new Error("Retired generation drain deadline expired."));
|
|
85
|
+
interrupted += 1;
|
|
86
|
+
try {
|
|
87
|
+
void Promise.resolve(work.interrupt?.("Retired generation drain deadline expired.")).catch(() => undefined);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// Interruption is best effort; the bounded report still closes resources.
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const candidate = await closeAction("candidate", this.candidate?.dispose, deadlineAt, this.now);
|
|
95
|
+
const providers = [];
|
|
96
|
+
const failures = [];
|
|
97
|
+
for (let index = this.providers.length - 1; index >= 0; index -= 1) {
|
|
98
|
+
const provider = this.providers[index];
|
|
99
|
+
if (provider === undefined)
|
|
100
|
+
continue;
|
|
101
|
+
const id = provider.id ?? `provider-${index}`;
|
|
102
|
+
const result = await closeAction(id, resourceAction(provider), deadlineAt, this.now);
|
|
103
|
+
providers.push({ id, status: result.status });
|
|
104
|
+
if (result.message !== undefined)
|
|
105
|
+
failures.push({ resource: id, message: result.message });
|
|
106
|
+
}
|
|
107
|
+
const remaining = this.work.size;
|
|
108
|
+
timedOut ||=
|
|
109
|
+
remaining > 0 ||
|
|
110
|
+
candidate.status === "timed-out" ||
|
|
111
|
+
providers.some((item) => item.status === "timed-out");
|
|
112
|
+
if (candidate.message !== undefined)
|
|
113
|
+
failures.push({ resource: "candidate", message: candidate.message });
|
|
114
|
+
const outcome = timedOut
|
|
115
|
+
? "timed-out"
|
|
116
|
+
: failures.length > 0
|
|
117
|
+
? "failed"
|
|
118
|
+
: interrupted > 0
|
|
119
|
+
? "interrupted"
|
|
120
|
+
: "drained";
|
|
121
|
+
const report = Object.freeze({
|
|
122
|
+
token: this.token,
|
|
123
|
+
deadlineMs: this.deadlineMs,
|
|
124
|
+
elapsedMs: Math.max(0, this.now() - startedAt),
|
|
125
|
+
initialInFlight,
|
|
126
|
+
completed: initialInFlight - remaining,
|
|
127
|
+
interrupted,
|
|
128
|
+
remaining,
|
|
129
|
+
timedOut,
|
|
130
|
+
outcome,
|
|
131
|
+
candidate: candidate.status,
|
|
132
|
+
providers: Object.freeze(providers.reverse()),
|
|
133
|
+
failures: Object.freeze(failures),
|
|
134
|
+
stateTransition: "not-configured",
|
|
135
|
+
});
|
|
136
|
+
try {
|
|
137
|
+
this.onReport?.(report);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// Reporting cannot change generation cleanup.
|
|
141
|
+
}
|
|
142
|
+
return report;
|
|
143
|
+
}
|
|
144
|
+
release(id) {
|
|
145
|
+
if (!this.work.delete(id) || this.work.size !== 0)
|
|
146
|
+
return;
|
|
147
|
+
const waiters = [...this.idleWaiters];
|
|
148
|
+
this.idleWaiters.clear();
|
|
149
|
+
for (const resolve of waiters)
|
|
150
|
+
resolve();
|
|
151
|
+
}
|
|
152
|
+
waitForIdle(deadlineAt) {
|
|
153
|
+
if (this.work.size === 0)
|
|
154
|
+
return Promise.resolve(true);
|
|
155
|
+
const remaining = Math.max(0, deadlineAt - this.now());
|
|
156
|
+
return new Promise((resolve) => {
|
|
157
|
+
let timer;
|
|
158
|
+
const finish = (drained) => {
|
|
159
|
+
if (timer !== undefined)
|
|
160
|
+
clearTimeout(timer);
|
|
161
|
+
this.idleWaiters.delete(onIdle);
|
|
162
|
+
resolve(drained);
|
|
163
|
+
};
|
|
164
|
+
const onIdle = () => finish(true);
|
|
165
|
+
this.idleWaiters.add(onIdle);
|
|
166
|
+
timer = setTimeout(() => finish(false), remaining);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
export function createSupervisorDrain(options) {
|
|
171
|
+
return new SupervisorGenerationDrain(options);
|
|
172
|
+
}
|
|
173
|
+
function sameToken(left, right) {
|
|
174
|
+
return (Boolean(left && right) &&
|
|
175
|
+
left?.sourceToken === right?.sourceToken &&
|
|
176
|
+
left?.generationToken === right?.generationToken);
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=drain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drain.js","sourceRoot":"","sources":["../src/drain.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,OAAO,EASN,MAAM,kBAAkB,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,MAAM,CAAC,MAAM,mCAAmC,GAAG,KAAK,CAAC;AAKzD,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,IAAI,CAA+D;IAC5E,YAAY,IAAkC,EAAE,OAAe;QAC7D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AACD,2EAA2E;AAC3E,MAAM,OAAO,yBAAyB;IAC3B,KAAK,CAA2B;IAChC,UAAU,CAAS;IACX,GAAG,CAAe;IAClB,SAAS,CAAsC;IAC/C,SAAS,CAAqC;IAC9C,QAAQ,CAAqC;IAC7C,IAAI,GAAG,IAAI,GAAG,EAAuB,CAAC;IACtC,WAAW,GAAG,IAAI,GAAG,EAAc,CAAC;IAC7C,UAAU,GAAG,CAAC,CAAC;IACf,SAAS,GAAG,IAAI,CAAC;IACjB,QAAQ,CAA6C;IAC7D,YAAY,OAA+B;QACzC,uBAAuB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1F,MAAM,IAAI,oBAAoB,CAC5B,6BAA6B,EAC7B,4DAA4D,CAC7D,CAAC;QACJ,CAAC;QACD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mCAAmC,CAAC;QAC7E,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YACxD,MAAM,IAAI,UAAU,CAAC,gEAAgE,CAAC,CAAC;QACzF,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACjD,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;QACnC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/D,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IACnC,CAAC;IACD,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACxB,CAAC;IACD,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IACD,6FAA6F;IAC7F,KAAK,CACH,KAA+B,EAC/B,UAAsC,EAAE;QAExC,uBAAuB,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QACvE,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC;QAC7B,MAAM,OAAO,GAAgB;YAC3B,UAAU,EAAE,IAAI,eAAe,EAAE;YACjC,SAAS,EAAE,OAAO,CAAC,SAAS;SAC7B,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC3B,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,MAAM;YACjC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;SAChC,CAAC,CAAC;IACL,CAAC;IACD,gGAAgG;IAChG,KAAK;QACH,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAEO,KAAK,CAAC,GAAG;QACf,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC;QAC/C,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QACvC,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,IAAI,QAAQ,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC;QACrD,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YACxC,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;gBAC3B,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO;oBAAE,SAAS;gBAC7C,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC,CAAC;gBAC/E,WAAW,IAAI,CAAC,CAAC;gBACjB,IAAI,CAAC;oBACH,KAAK,OAAO,CAAC,OAAO,CAClB,IAAI,CAAC,SAAS,EAAE,CAAC,4CAA4C,CAAC,CAC/D,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;gBAC3B,CAAC;gBAAC,MAAM,CAAC;oBACP,0EAA0E;gBAC5E,CAAC;YACH,CAAC;QACH,CAAC;QACD,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAChG,MAAM,SAAS,GAAoC,EAAE,CAAC;QACtD,MAAM,QAAQ,GAA6B,EAAE,CAAC;QAC9C,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACvC,IAAI,QAAQ,KAAK,SAAS;gBAAE,SAAS;YACrC,MAAM,EAAE,GAAG,QAAQ,CAAC,EAAE,IAAI,YAAY,KAAK,EAAE,CAAC;YAC9C,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,EAAE,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;YACrF,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;YAC9C,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS;gBAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7F,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QACjC,QAAQ;YACN,SAAS,GAAG,CAAC;gBACb,SAAS,CAAC,MAAM,KAAK,WAAW;gBAChC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;QACxD,IAAI,SAAS,CAAC,OAAO,KAAK,SAAS;YACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;QACvE,MAAM,OAAO,GAAG,QAAQ;YACtB,CAAC,CAAC,WAAW;YACb,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;gBACnB,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,WAAW,GAAG,CAAC;oBACf,CAAC,CAAC,aAAa;oBACf,CAAC,CAAC,SAAS,CAAC;QAClB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YAC3B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAC9C,eAAe;YACf,SAAS,EAAE,eAAe,GAAG,SAAS;YACtC,WAAW;YACX,SAAS;YACT,QAAQ;YACR,OAAO;YACP,SAAS,EAAE,SAAS,CAAC,MAAM;YAC3B,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;YAC7C,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;YACjC,eAAe,EAAE,gBAAkD;SACpE,CAAC,CAAC;QACH,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,8CAA8C;QAChD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,OAAO,CAAC,EAAU;QACxB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO;QAC1D,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC;QACtC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,OAAO,IAAI,OAAO;YAAE,OAAO,EAAE,CAAC;IAC3C,CAAC;IAEO,WAAW,CAAC,UAAkB;QACpC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACvD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACvD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,IAAI,KAAgD,CAAC;YACrD,MAAM,MAAM,GAAG,CAAC,OAAgB,EAAQ,EAAE;gBACxC,IAAI,KAAK,KAAK,SAAS;oBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;gBAC7C,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAChC,OAAO,CAAC,OAAO,CAAC,CAAC;YACnB,CAAC,CAAC;YACF,MAAM,MAAM,GAAG,GAAS,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACxC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC7B,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAED,MAAM,UAAU,qBAAqB,CAAC,OAA+B;IACnE,OAAO,IAAI,yBAAyB,CAAC,OAAO,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,SAAS,CAChB,IAA0C,EAC1C,KAA2C;IAE3C,OAAO,CACL,OAAO,CAAC,IAAI,IAAI,KAAK,CAAC;QACtB,IAAI,EAAE,WAAW,KAAK,KAAK,EAAE,WAAW;QACxC,IAAI,EAAE,eAAe,KAAK,KAAK,EAAE,eAAe,CACjD,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./state-machine.js";
|
|
2
|
+
export * from "./watcher.js";
|
|
3
|
+
export * from "./candidate.js";
|
|
4
|
+
export * from "./verification.js";
|
|
5
|
+
export * from "./proxy.js";
|
|
6
|
+
export * from "./drain.js";
|
|
7
|
+
export * from "./drain-state.js";
|
|
8
|
+
export * from "./observability.js";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./state-machine.js";
|
|
2
|
+
export * from "./watcher.js";
|
|
3
|
+
export * from "./candidate.js";
|
|
4
|
+
export * from "./verification.js";
|
|
5
|
+
export * from "./proxy.js";
|
|
6
|
+
export * from "./drain.js";
|
|
7
|
+
export * from "./drain-state.js";
|
|
8
|
+
export * from "./observability.js";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type DiagnosticRecord, type GenerationRecord } from "@relkit/observability";
|
|
2
|
+
import type { SupervisorCandidateToken, SupervisorTelemetry } from "./state-machine-types.js";
|
|
3
|
+
export interface SupervisorTelemetryRecord {
|
|
4
|
+
readonly record: GenerationRecord | DiagnosticRecord;
|
|
5
|
+
readonly streamType: "generation.changed" | "diagnostic.changed";
|
|
6
|
+
}
|
|
7
|
+
export declare function recordsForTelemetry(event: SupervisorTelemetry, graphHash: (token: SupervisorCandidateToken) => string, now: () => number): readonly SupervisorTelemetryRecord[];
|
|
8
|
+
export declare function generationIdFor(token: SupervisorCandidateToken): string;
|
|
9
|
+
//# sourceMappingURL=observability-records.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observability-records.d.ts","sourceRoot":"","sources":["../src/observability-records.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,gBAAgB,EAErB,KAAK,gBAAgB,EACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EACV,wBAAwB,EAExB,mBAAmB,EACpB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,CAAC;IACrD,QAAQ,CAAC,UAAU,EAAE,oBAAoB,GAAG,oBAAoB,CAAC;CAClE;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,mBAAmB,EAC1B,SAAS,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,MAAM,EACtD,GAAG,EAAE,MAAM,MAAM,GAChB,SAAS,yBAAyB,EAAE,CAkDtC;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,wBAAwB,GAAG,MAAM,CAEvE"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { OBSERVABILITY_MODEL_VERSION, } from "@relkit/observability";
|
|
2
|
+
export function recordsForTelemetry(event, graphHash, now) {
|
|
3
|
+
if (event.type !== "outcome")
|
|
4
|
+
return [];
|
|
5
|
+
const occurredAt = new Date(now()).toISOString();
|
|
6
|
+
const target = event.phase === "drain" ? event.previousGeneration : undefined;
|
|
7
|
+
const token = target ?? tokenFor(event);
|
|
8
|
+
const hash = graphHash(token);
|
|
9
|
+
const generationId = generationIdFor(token);
|
|
10
|
+
const lifecycle = lifecycleFor(event);
|
|
11
|
+
const generation = {
|
|
12
|
+
version: OBSERVABILITY_MODEL_VERSION,
|
|
13
|
+
signal: "generation",
|
|
14
|
+
generationId,
|
|
15
|
+
graphHash: hash,
|
|
16
|
+
event: lifecycle,
|
|
17
|
+
occurredAt,
|
|
18
|
+
sourceVersion: token.sourceToken,
|
|
19
|
+
...(event.error?.code === undefined ? {} : { errorCode: event.error.code }),
|
|
20
|
+
};
|
|
21
|
+
const diagnostic = {
|
|
22
|
+
version: OBSERVABILITY_MODEL_VERSION,
|
|
23
|
+
signal: "diagnostic",
|
|
24
|
+
code: event.error?.code ?? `RELKIT_SUPERVISOR_${event.outcome.toUpperCase().replaceAll("-", "_")}`,
|
|
25
|
+
severity: event.outcome === "candidate-stale" ? "warning" : lifecycle === "failed" ? "error" : "info",
|
|
26
|
+
message: event.error?.message ?? `Supervisor ${event.phase} ${event.outcome}.`,
|
|
27
|
+
occurredAt,
|
|
28
|
+
generationId,
|
|
29
|
+
graphHash: hash,
|
|
30
|
+
};
|
|
31
|
+
const result = [
|
|
32
|
+
{ record: generation, streamType: "generation.changed" },
|
|
33
|
+
{ record: diagnostic, streamType: "diagnostic.changed" },
|
|
34
|
+
];
|
|
35
|
+
if (event.outcome === "switch-succeeded" && event.previousGeneration !== undefined) {
|
|
36
|
+
const previous = event.previousGeneration;
|
|
37
|
+
result.unshift({
|
|
38
|
+
streamType: "generation.changed",
|
|
39
|
+
record: {
|
|
40
|
+
version: OBSERVABILITY_MODEL_VERSION,
|
|
41
|
+
signal: "generation",
|
|
42
|
+
generationId: generationIdFor(previous),
|
|
43
|
+
graphHash: graphHash(previous),
|
|
44
|
+
event: "draining",
|
|
45
|
+
occurredAt,
|
|
46
|
+
sourceVersion: previous.sourceToken,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return Object.freeze(result);
|
|
51
|
+
}
|
|
52
|
+
export function generationIdFor(token) {
|
|
53
|
+
return `generation-${token.generationToken}`;
|
|
54
|
+
}
|
|
55
|
+
function tokenFor(event) {
|
|
56
|
+
return { sourceToken: event.sourceToken, generationToken: event.generationToken };
|
|
57
|
+
}
|
|
58
|
+
function lifecycleFor(event) {
|
|
59
|
+
if (event.phase === "compile")
|
|
60
|
+
return event.outcome === "compile-succeeded" ? "created" : "failed";
|
|
61
|
+
if (event.phase === "start")
|
|
62
|
+
return event.outcome === "start-succeeded" ? "started" : "failed";
|
|
63
|
+
if (event.phase === "verification")
|
|
64
|
+
return event.outcome === "verification-succeeded" ? "ready" : "failed";
|
|
65
|
+
if (event.phase === "switch")
|
|
66
|
+
return event.outcome === "switch-succeeded" ? "activated" : "failed";
|
|
67
|
+
if (event.outcome === "drain-succeeded")
|
|
68
|
+
return "stopped";
|
|
69
|
+
return "failed";
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=observability-records.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observability-records.js","sourceRoot":"","sources":["../src/observability-records.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { MaybePromise } from "@relkit/contracts";
|
|
2
|
+
import type { ObservabilityCollector, ObservabilityRecord, ObservabilityStream, RedactionPolicy } from "@relkit/observability";
|
|
3
|
+
import type { SupervisorCandidateToken, SupervisorTelemetry, SupervisorTelemetryListener } from "./state-machine-types.js";
|
|
4
|
+
export type SupervisorGraphHash = string | ((token: SupervisorCandidateToken, event: SupervisorTelemetry) => string | undefined);
|
|
5
|
+
export interface SupervisorObservabilityOptions {
|
|
6
|
+
readonly graphHash: SupervisorGraphHash;
|
|
7
|
+
readonly collector?: Pick<ObservabilityCollector, "collect">;
|
|
8
|
+
readonly stream?: Pick<ObservabilityStream, "publishRecord">;
|
|
9
|
+
readonly append?: (record: ObservabilityRecord) => MaybePromise<unknown>;
|
|
10
|
+
readonly redaction?: RedactionPolicy;
|
|
11
|
+
readonly now?: () => number;
|
|
12
|
+
}
|
|
13
|
+
export interface SupervisorObservability {
|
|
14
|
+
readonly onTelemetry: SupervisorTelemetryListener;
|
|
15
|
+
readonly emit: (event: SupervisorTelemetry) => void;
|
|
16
|
+
readonly flush: () => Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=observability-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observability-types.d.ts","sourceRoot":"","sources":["../src/observability-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EACV,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EAChB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EACV,wBAAwB,EACxB,mBAAmB,EACnB,2BAA2B,EAC5B,MAAM,0BAA0B,CAAC;AAElC,MAAM,MAAM,mBAAmB,GAC7B,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,wBAAwB,EAAE,KAAK,EAAE,mBAAmB,KAAK,MAAM,GAAG,SAAS,CAAC,CAAC;AAEjG,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,SAAS,EAAE,mBAAmB,CAAC;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,sBAAsB,EAAE,SAAS,CAAC,CAAC;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,YAAY,CAAC,OAAO,CAAC,CAAC;IACzE,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,WAAW,EAAE,2BAA2B,CAAC;IAClD,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACpD,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observability-types.js","sourceRoot":"","sources":["../src/observability-types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SupervisorObservability, SupervisorObservabilityOptions } from "./observability-types.js";
|
|
2
|
+
export type { SupervisorGraphHash, SupervisorObservability, SupervisorObservabilityOptions, } from "./observability-types.js";
|
|
3
|
+
/** Bridges supervisor lifecycle outcomes into the existing redacted observability sinks. */
|
|
4
|
+
export declare function createSupervisorObservability(options: SupervisorObservabilityOptions): SupervisorObservability;
|
|
5
|
+
//# sourceMappingURL=observability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observability.d.ts","sourceRoot":"","sources":["../src/observability.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,uBAAuB,EACvB,8BAA8B,EAC/B,MAAM,0BAA0B,CAAC;AAElC,YAAY,EACV,mBAAmB,EACnB,uBAAuB,EACvB,8BAA8B,GAC/B,MAAM,0BAA0B,CAAC;AAElC,4FAA4F;AAC5F,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,8BAA8B,GACtC,uBAAuB,CAuCzB"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { admitObservabilityRecord } from "@relkit/observability";
|
|
2
|
+
import { recordsForTelemetry } from "./observability-records.js";
|
|
3
|
+
/** Bridges supervisor lifecycle outcomes into the existing redacted observability sinks. */
|
|
4
|
+
export function createSupervisorObservability(options) {
|
|
5
|
+
const now = options.now ?? Date.now;
|
|
6
|
+
let tail = Promise.resolve();
|
|
7
|
+
const resolveHash = createHashResolver(options.graphHash);
|
|
8
|
+
const emit = (event) => {
|
|
9
|
+
const records = recordsForTelemetry(event, (token) => resolveHash(token, event), now);
|
|
10
|
+
for (const item of records)
|
|
11
|
+
publish(item.record, item.streamType);
|
|
12
|
+
};
|
|
13
|
+
const publish = (record, streamType) => {
|
|
14
|
+
const safe = admitObservabilityRecord(record, options.redaction);
|
|
15
|
+
if (safe === undefined)
|
|
16
|
+
return;
|
|
17
|
+
try {
|
|
18
|
+
options.collector?.collect(safe);
|
|
19
|
+
options.stream?.publishRecord(streamType, safe);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// A closed or bounded sink cannot change supervisor lifecycle behavior.
|
|
23
|
+
}
|
|
24
|
+
if (options.append !== undefined) {
|
|
25
|
+
tail = tail
|
|
26
|
+
.then(() => options.append(safe))
|
|
27
|
+
.then(() => undefined, () => undefined);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
return Object.freeze({
|
|
31
|
+
onTelemetry: emit,
|
|
32
|
+
emit,
|
|
33
|
+
flush: async () => {
|
|
34
|
+
await tail;
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function createHashResolver(value) {
|
|
39
|
+
return (token, event) => {
|
|
40
|
+
const hash = typeof value === "string" ? value : value(token, event);
|
|
41
|
+
if (hash === undefined || hash.trim() === "")
|
|
42
|
+
throw new TypeError(`Supervisor observability requires an explicit graph hash for generation-${token.generationToken}.`);
|
|
43
|
+
return hash;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=observability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observability.js","sourceRoot":"","sources":["../src/observability.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAA4B,MAAM,uBAAuB,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAcjE,4FAA4F;AAC5F,MAAM,UAAU,6BAA6B,CAC3C,OAAuC;IAEvC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACpC,IAAI,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAC7B,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAE1D,MAAM,IAAI,GAAG,CAAC,KAA0B,EAAQ,EAAE;QAChD,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;QACtF,KAAK,MAAM,IAAI,IAAI,OAAO;YAAE,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACpE,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,CACd,MAA2B,EAC3B,UAAuD,EACjD,EAAE;QACR,MAAM,IAAI,GAAG,wBAAwB,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QACjE,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO;QAC/B,IAAI,CAAC;YACH,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;YACjC,OAAO,CAAC,MAAM,EAAE,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,wEAAwE;QAC1E,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACjC,IAAI,GAAG,IAAI;iBACR,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAO,CAAC,IAAI,CAAC,CAAC;iBACjC,IAAI,CACH,GAAG,EAAE,CAAC,SAAS,EACf,GAAG,EAAE,CAAC,SAAS,CAChB,CAAC;QACN,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,WAAW,EAAE,IAAI;QACjB,IAAI;QACJ,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,MAAM,IAAI,CAAC;QACb,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAS,kBAAkB,CACzB,KAA0B;IAE1B,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACtB,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACrE,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;YAC1C,MAAM,IAAI,SAAS,CACjB,2EAA2E,KAAK,CAAC,eAAe,GAAG,CACpG,CAAC;QACJ,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SupervisorDrainLease } from "./drain-types.js";
|
|
2
|
+
import type { ActiveSupervisorProxyTarget } from "./proxy.js";
|
|
3
|
+
export declare function forwardProxyRequest(request: Request, target: ActiveSupervisorProxyTarget, fetcher?: typeof fetch, lease?: SupervisorDrainLease): Promise<Response>;
|
|
4
|
+
export declare function drainResponse(): Response;
|
|
5
|
+
//# sourceMappingURL=proxy-forward.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-forward.d.ts","sourceRoot":"","sources":["../src/proxy-forward.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAe9D,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,2BAA2B,EACnC,OAAO,GAAE,OAAO,KAAa,EAC7B,KAAK,CAAC,EAAE,oBAAoB,GAC3B,OAAO,CAAC,QAAQ,CAAC,CAanB;AAED,wBAAgB,aAAa,IAAI,QAAQ,CAKxC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const HOP_BY_HOP_HEADERS = [
|
|
2
|
+
"connection",
|
|
3
|
+
"content-length",
|
|
4
|
+
"keep-alive",
|
|
5
|
+
"proxy-authenticate",
|
|
6
|
+
"proxy-authorization",
|
|
7
|
+
"te",
|
|
8
|
+
"trailer",
|
|
9
|
+
"transfer-encoding",
|
|
10
|
+
"upgrade",
|
|
11
|
+
"host",
|
|
12
|
+
];
|
|
13
|
+
export function forwardProxyRequest(request, target, fetcher = fetch, lease) {
|
|
14
|
+
const url = new URL(request.url);
|
|
15
|
+
url.protocol = "http:";
|
|
16
|
+
url.hostname = target.hostname;
|
|
17
|
+
url.port = String(target.port);
|
|
18
|
+
const init = {
|
|
19
|
+
method: request.method,
|
|
20
|
+
headers: forwardedHeaders(request.headers),
|
|
21
|
+
redirect: "manual",
|
|
22
|
+
signal: lease === undefined ? request.signal : AbortSignal.any([request.signal, lease.signal]),
|
|
23
|
+
};
|
|
24
|
+
if (request.method !== "GET" && request.method !== "HEAD")
|
|
25
|
+
init.body = request.body;
|
|
26
|
+
return fetcher(url, init);
|
|
27
|
+
}
|
|
28
|
+
export function drainResponse() {
|
|
29
|
+
return new Response(JSON.stringify({ error: "RelKit generation is draining." }), {
|
|
30
|
+
status: 503,
|
|
31
|
+
headers: { "cache-control": "no-store", "content-type": "application/json" },
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function forwardedHeaders(source) {
|
|
35
|
+
const headers = new Headers(source);
|
|
36
|
+
const connection = headers.get("connection");
|
|
37
|
+
for (const name of connection?.split(",") ?? [])
|
|
38
|
+
headers.delete(name.trim());
|
|
39
|
+
for (const name of HOP_BY_HOP_HEADERS)
|
|
40
|
+
headers.delete(name);
|
|
41
|
+
return headers;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=proxy-forward.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-forward.js","sourceRoot":"","sources":["../src/proxy-forward.ts"],"names":[],"mappings":"AAGA,MAAM,kBAAkB,GAAG;IACzB,YAAY;IACZ,gBAAgB;IAChB,YAAY;IACZ,oBAAoB;IACpB,qBAAqB;IACrB,IAAI;IACJ,SAAS;IACT,mBAAmB;IACnB,SAAS;IACT,MAAM;CACE,CAAC;AAEX,MAAM,UAAU,mBAAmB,CACjC,OAAgB,EAChB,MAAmC,EACnC,UAAwB,KAAK,EAC7B,KAA4B;IAE5B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACjC,GAAG,CAAC,QAAQ,GAAG,OAAO,CAAC;IACvB,GAAG,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC/B,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAgB;QACxB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,OAAO,CAAC;QAC1C,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;KAC/F,CAAC;IACF,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM;QAAE,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IACpF,OAAO,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,gCAAgC,EAAE,CAAC,EAAE;QAC/E,MAAM,EAAE,GAAG;QACX,OAAO,EAAE,EAAE,eAAe,EAAE,UAAU,EAAE,cAAc,EAAE,kBAAkB,EAAE;KAC7E,CAAC,CAAC;AACL,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAe;IACvC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC7C,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE;QAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7E,KAAK,MAAM,IAAI,IAAI,kBAAkB;QAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5D,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/proxy.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { StartedCandidate } from "./candidate-types.js";
|
|
2
|
+
import type { SupervisorDrainLease } from "./drain-types.js";
|
|
3
|
+
import type { SupervisorCandidateToken } from "./state-machine-types.js";
|
|
4
|
+
export { forwardProxyRequest } from "./proxy-forward.js";
|
|
5
|
+
export declare const DEFAULT_SUPERVISOR_HOSTNAME = "127.0.0.1";
|
|
6
|
+
export declare const DEFAULT_SUPERVISOR_PORT = 3000;
|
|
7
|
+
export type SupervisorProxyTarget = Pick<StartedCandidate, "token" | "port"> & {
|
|
8
|
+
readonly hostname?: string;
|
|
9
|
+
};
|
|
10
|
+
export interface ActiveSupervisorProxyTarget {
|
|
11
|
+
readonly token: SupervisorCandidateToken;
|
|
12
|
+
readonly hostname: string;
|
|
13
|
+
readonly port: number;
|
|
14
|
+
}
|
|
15
|
+
export interface SupervisorProxyOptions {
|
|
16
|
+
readonly hostname?: string;
|
|
17
|
+
readonly port?: number;
|
|
18
|
+
readonly targetHostname?: string;
|
|
19
|
+
readonly fetch?: typeof fetch;
|
|
20
|
+
readonly track?: (token: SupervisorCandidateToken) => SupervisorDrainLease | undefined;
|
|
21
|
+
}
|
|
22
|
+
/** Stable development listener that synchronously selects one active target per request. */
|
|
23
|
+
export declare class SupervisorProxy {
|
|
24
|
+
private readonly hostname;
|
|
25
|
+
private readonly configuredPort;
|
|
26
|
+
private readonly targetHostname;
|
|
27
|
+
private readonly fetcher;
|
|
28
|
+
private readonly track;
|
|
29
|
+
private server;
|
|
30
|
+
private stopping;
|
|
31
|
+
private target;
|
|
32
|
+
constructor(options?: SupervisorProxyOptions);
|
|
33
|
+
get port(): number;
|
|
34
|
+
get url(): URL | undefined;
|
|
35
|
+
get activeTarget(): ActiveSupervisorProxyTarget | undefined;
|
|
36
|
+
listen(): Promise<this>;
|
|
37
|
+
/** Replaces the target only when the expected active token still matches. */
|
|
38
|
+
compareAndSwitch(expected: SupervisorCandidateToken | undefined, next: SupervisorProxyTarget): boolean;
|
|
39
|
+
switchTarget(next: SupervisorProxyTarget, expected?: SupervisorCandidateToken | undefined): boolean;
|
|
40
|
+
/** Reads the active reference before awaiting, so switched traffic cannot select a retired target. */
|
|
41
|
+
handle(request: Request): Promise<Response>;
|
|
42
|
+
stop(): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
export declare function createSupervisorProxy(options?: SupervisorProxyOptions): SupervisorProxy;
|
|
45
|
+
//# sourceMappingURL=proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAG7D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,eAAO,MAAM,2BAA2B,cAAc,CAAC;AACvD,eAAO,MAAM,uBAAuB,OAAQ,CAAC;AAE7C,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,gBAAgB,EAAE,OAAO,GAAG,MAAM,CAAC,GAAG;IAC7E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,KAAK,EAAE,wBAAwB,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,oBAAoB,GAAG,SAAS,CAAC;CACxF;AAED,4FAA4F;AAC5F,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkC;IACxD,OAAO,CAAC,MAAM,CAAoC;IAClD,OAAO,CAAC,QAAQ,CAA4B;IAC5C,OAAO,CAAC,MAAM,CAA0C;gBAE5C,OAAO,GAAE,sBAA2B;IAUhD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,GAAG,IAAI,GAAG,GAAG,SAAS,CAEzB;IAED,IAAI,YAAY,IAAI,2BAA2B,GAAG,SAAS,CAE1D;IAEK,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAW7B,6EAA6E;IAC7E,gBAAgB,CACd,QAAQ,EAAE,wBAAwB,GAAG,SAAS,EAC9C,IAAI,EAAE,qBAAqB,GAC1B,OAAO;IAeV,YAAY,CAAC,IAAI,EAAE,qBAAqB,EAAE,QAAQ,uCAAqB,GAAG,OAAO;IAIjF,sGAAsG;IACtG,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IAqB3C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAUtB;AAED,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,sBAA2B,GAAG,eAAe,CAE3F"}
|