@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/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 rel-kit
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CandidateLogger, CandidateOutput } from "./candidate-types.js";
|
|
2
|
+
import type { SupervisorCandidateToken } from "./state-machine-types.js";
|
|
3
|
+
export declare function captureOutput(child: Bun.ReadableSubprocess, logger: CandidateLogger | undefined, token: SupervisorCandidateToken, directory: string, limit: number): Promise<CandidateOutput>;
|
|
4
|
+
//# sourceMappingURL=candidate-output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"candidate-output.d.ts","sourceRoot":"","sources":["../src/candidate-output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAqB,eAAe,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAChG,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEzE,wBAAgB,aAAa,CAC3B,KAAK,EAAE,GAAG,CAAC,kBAAkB,EAC7B,MAAM,EAAE,eAAe,GAAG,SAAS,EACnC,KAAK,EAAE,wBAAwB,EAC/B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,eAAe,CAAC,CAU1B"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export function captureOutput(child, logger, token, directory, limit) {
|
|
2
|
+
const budget = { remaining: limit, truncated: false };
|
|
3
|
+
return Promise.all([
|
|
4
|
+
captureStream(child.stdout, "stdout", logger, token, directory, budget),
|
|
5
|
+
captureStream(child.stderr, "stderr", logger, token, directory, budget),
|
|
6
|
+
]).then(([stdout, stderr]) => ({
|
|
7
|
+
stdout: stdout.text,
|
|
8
|
+
stderr: stderr.text,
|
|
9
|
+
truncated: budget.truncated || stdout.truncated || stderr.truncated,
|
|
10
|
+
}));
|
|
11
|
+
}
|
|
12
|
+
async function captureStream(stream, channel, logger, token, directory, budget) {
|
|
13
|
+
const reader = stream.getReader();
|
|
14
|
+
const decoder = new TextDecoder();
|
|
15
|
+
let text = "";
|
|
16
|
+
let truncated = false;
|
|
17
|
+
try {
|
|
18
|
+
while (true) {
|
|
19
|
+
const next = await reader.read();
|
|
20
|
+
if (next.done)
|
|
21
|
+
break;
|
|
22
|
+
const part = next.value.subarray(0, Math.max(0, budget.remaining));
|
|
23
|
+
if (part.byteLength > 0) {
|
|
24
|
+
const chunk = decoder.decode(part, { stream: part.byteLength < next.value.byteLength });
|
|
25
|
+
text += chunk;
|
|
26
|
+
budget.remaining -= part.byteLength;
|
|
27
|
+
logOutput(logger, token, directory, channel, chunk);
|
|
28
|
+
}
|
|
29
|
+
if (part.byteLength < next.value.byteLength) {
|
|
30
|
+
truncated = true;
|
|
31
|
+
budget.truncated = true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
text += decoder.decode();
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
truncated = true;
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
reader.releaseLock();
|
|
41
|
+
}
|
|
42
|
+
return { text, truncated };
|
|
43
|
+
}
|
|
44
|
+
function logOutput(logger, token, directory, channel, output) {
|
|
45
|
+
const event = {
|
|
46
|
+
level: channel === "stderr" ? "warn" : "info",
|
|
47
|
+
event: "candidate.startup-output",
|
|
48
|
+
token,
|
|
49
|
+
directory,
|
|
50
|
+
stream: channel,
|
|
51
|
+
output,
|
|
52
|
+
};
|
|
53
|
+
try {
|
|
54
|
+
logger?.(event);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Logging failures must not change candidate lifecycle behavior.
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=candidate-output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"candidate-output.js","sourceRoot":"","sources":["../src/candidate-output.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CandidateLogEvent, CandidateLogger, CandidateOptions } from "./candidate-types.js";
|
|
2
|
+
import type { SupervisorCandidateToken } from "./state-machine-types.js";
|
|
3
|
+
export { captureOutput } from "./candidate-output.js";
|
|
4
|
+
export declare function candidateContext(options: CandidateOptions): {
|
|
5
|
+
readonly projectRoot: string;
|
|
6
|
+
readonly directoryRoot: string;
|
|
7
|
+
readonly directory: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function entrypointIn(directory: string, entrypoint: string): string;
|
|
10
|
+
export declare function resolvePort(options: CandidateOptions, hostname: string): Promise<number>;
|
|
11
|
+
export declare function childEnvironment(values: Readonly<Record<string, string | undefined>> | undefined, token: SupervisorCandidateToken, port: number): Record<string, string>;
|
|
12
|
+
export declare function createStopper(child: Bun.ReadableSubprocess, timeoutMs: number): () => Promise<void>;
|
|
13
|
+
export declare function terminate(child: Bun.ReadableSubprocess, timeoutMs: number): Promise<void>;
|
|
14
|
+
export declare function cleanupCandidate(directory: string, root: string): Promise<void>;
|
|
15
|
+
export declare function emitFailure(options: CandidateOptions, event: "candidate.compile.failed" | "candidate.start.failed", directory: string, error: unknown): void;
|
|
16
|
+
export declare function emit(logger: CandidateLogger | undefined, event: CandidateLogEvent): void;
|
|
17
|
+
export declare function throwIfAborted(signal: AbortSignal | undefined): void;
|
|
18
|
+
export declare function validateBound(value: number, name: string, allowZero: boolean): void;
|
|
19
|
+
//# sourceMappingURL=candidate-process.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"candidate-process.d.ts","sourceRoot":"","sources":["../src/candidate-process.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAEjG,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG;IAC3D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,CAMA;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAO1E;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ9F;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,SAAS,EAChE,KAAK,EAAE,wBAAwB,EAC/B,IAAI,EAAE,MAAM,GACX,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAiBxB;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,GAAG,CAAC,kBAAkB,EAC7B,SAAS,EAAE,MAAM,GAChB,MAAM,OAAO,CAAC,IAAI,CAAC,CAMrB;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,kBAAkB,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAU/F;AAED,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIrF;AAED,wBAAgB,WAAW,CACzB,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAE,0BAA0B,GAAG,wBAAwB,EAC5D,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,GACb,IAAI,CAQN;AAED,wBAAgB,IAAI,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,EAAE,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAMxF;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,IAAI,CAEpE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,CAGnF"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { rm } from "node:fs/promises";
|
|
2
|
+
import { isAbsolute, join, relative, resolve } from "node:path";
|
|
3
|
+
import { validateSupervisorToken } from "./state-machine-telemetry.js";
|
|
4
|
+
export { captureOutput } from "./candidate-output.js";
|
|
5
|
+
export function candidateContext(options) {
|
|
6
|
+
validateSupervisorToken(options.token);
|
|
7
|
+
const projectRoot = resolve(options.projectRoot);
|
|
8
|
+
const directoryRoot = resolve(projectRoot, options.generatedDirectory ?? ".relkit/generated");
|
|
9
|
+
const directory = join(directoryRoot, `generation-${options.token.generationToken}`);
|
|
10
|
+
return { projectRoot, directoryRoot, directory };
|
|
11
|
+
}
|
|
12
|
+
export function entrypointIn(directory, entrypoint) {
|
|
13
|
+
if (typeof entrypoint !== "string" || entrypoint.trim() === "")
|
|
14
|
+
throw new TypeError("Candidate compilation must return an entrypoint.");
|
|
15
|
+
const resolved = resolve(directory, entrypoint);
|
|
16
|
+
if (!isWithin(directory, resolved) || resolved === directory)
|
|
17
|
+
throw new Error("Candidate entrypoint must remain inside its generation directory.");
|
|
18
|
+
return resolved;
|
|
19
|
+
}
|
|
20
|
+
export async function resolvePort(options, hostname) {
|
|
21
|
+
const port = options.port === undefined || options.port === 0
|
|
22
|
+
? await (options.allocatePort ?? allocatePort)(hostname)
|
|
23
|
+
: options.port;
|
|
24
|
+
if (!Number.isSafeInteger(port) || port < 1 || port > 65_535)
|
|
25
|
+
throw new RangeError("Candidate backend port must be between 1 and 65535.");
|
|
26
|
+
return port;
|
|
27
|
+
}
|
|
28
|
+
export function childEnvironment(values, token, port) {
|
|
29
|
+
const inherited = Object.fromEntries(Object.entries(process.env).filter((entry) => entry[1] !== undefined));
|
|
30
|
+
return {
|
|
31
|
+
...inherited,
|
|
32
|
+
...Object.fromEntries(Object.entries(values ?? {}).filter((entry) => entry[1] !== undefined)),
|
|
33
|
+
PORT: String(port),
|
|
34
|
+
RELKIT_SOURCE_TOKEN: String(token.sourceToken),
|
|
35
|
+
RELKIT_GENERATION_TOKEN: String(token.generationToken),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function createStopper(child, timeoutMs) {
|
|
39
|
+
let stopping;
|
|
40
|
+
return () => {
|
|
41
|
+
stopping ??= terminate(child, timeoutMs);
|
|
42
|
+
return stopping;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export async function terminate(child, timeoutMs) {
|
|
46
|
+
if (child.exitCode === null)
|
|
47
|
+
child.kill("SIGTERM");
|
|
48
|
+
const exited = await Promise.race([
|
|
49
|
+
child.exited.then(() => true),
|
|
50
|
+
delay(timeoutMs).then(() => false),
|
|
51
|
+
]);
|
|
52
|
+
if (!exited && child.exitCode === null) {
|
|
53
|
+
child.kill("SIGKILL");
|
|
54
|
+
await child.exited;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export async function cleanupCandidate(directory, root) {
|
|
58
|
+
if (!isWithin(root, directory) || directory === root)
|
|
59
|
+
throw new Error("Candidate cleanup path must remain below its generated directory.");
|
|
60
|
+
await rm(directory, { recursive: true, force: true });
|
|
61
|
+
}
|
|
62
|
+
export function emitFailure(options, event, directory, error) {
|
|
63
|
+
emit(options.logger, {
|
|
64
|
+
level: "error",
|
|
65
|
+
event,
|
|
66
|
+
token: options.token,
|
|
67
|
+
directory,
|
|
68
|
+
fields: { message: errorMessage(error).slice(0, 512) },
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
export function emit(logger, event) {
|
|
72
|
+
try {
|
|
73
|
+
logger?.(Object.freeze({ ...event, token: Object.freeze({ ...event.token }) }));
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// Logging failures must not change candidate lifecycle behavior.
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export function throwIfAborted(signal) {
|
|
80
|
+
if (signal?.aborted)
|
|
81
|
+
throw signal.reason ?? new Error("Candidate operation was aborted.");
|
|
82
|
+
}
|
|
83
|
+
export function validateBound(value, name, allowZero) {
|
|
84
|
+
if (!Number.isSafeInteger(value) || value < (allowZero ? 0 : 1))
|
|
85
|
+
throw new RangeError(`${name} must be ${allowZero ? "non-negative" : "positive"}.`);
|
|
86
|
+
}
|
|
87
|
+
function isWithin(root, candidate) {
|
|
88
|
+
const path = relative(root, candidate);
|
|
89
|
+
return path === "" || (!path.startsWith("..") && !isAbsolute(path));
|
|
90
|
+
}
|
|
91
|
+
async function allocatePort(hostname) {
|
|
92
|
+
const server = Bun.serve({ hostname, port: 0, fetch: () => new Response() });
|
|
93
|
+
const port = server.port;
|
|
94
|
+
await server.stop(true);
|
|
95
|
+
if (port === undefined)
|
|
96
|
+
throw new Error("Bun did not allocate a candidate backend port.");
|
|
97
|
+
return port;
|
|
98
|
+
}
|
|
99
|
+
function errorMessage(error) {
|
|
100
|
+
return error instanceof Error ? error.message : String(error);
|
|
101
|
+
}
|
|
102
|
+
function delay(milliseconds) {
|
|
103
|
+
return new Promise((resolveDelay) => setTimeout(resolveDelay, milliseconds));
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=candidate-process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"candidate-process.js","sourceRoot":"","sources":["../src/candidate-process.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { SupervisorCandidateToken } from "./state-machine-types.js";
|
|
2
|
+
export interface CandidateCompileRequest {
|
|
3
|
+
readonly token: SupervisorCandidateToken;
|
|
4
|
+
readonly projectRoot: string;
|
|
5
|
+
readonly outputDirectory: string;
|
|
6
|
+
readonly signal: AbortSignal;
|
|
7
|
+
}
|
|
8
|
+
export interface CandidateCompileResult {
|
|
9
|
+
readonly entrypoint: string;
|
|
10
|
+
}
|
|
11
|
+
export type CandidateCompile = (request: CandidateCompileRequest) => CandidateCompileResult | PromiseLike<CandidateCompileResult>;
|
|
12
|
+
export interface CandidateLogEvent {
|
|
13
|
+
readonly level: "info" | "warn" | "error";
|
|
14
|
+
readonly event: "candidate.compile.started" | "candidate.compile.succeeded" | "candidate.compile.failed" | "candidate.start.started" | "candidate.start.succeeded" | "candidate.start.failed" | "candidate.startup-output" | "candidate.process-exited";
|
|
15
|
+
readonly token: SupervisorCandidateToken;
|
|
16
|
+
readonly directory: string;
|
|
17
|
+
readonly stream?: "stdout" | "stderr";
|
|
18
|
+
readonly output?: string;
|
|
19
|
+
readonly fields?: Readonly<Record<string, string | number | boolean>>;
|
|
20
|
+
}
|
|
21
|
+
export type CandidateLogger = (event: CandidateLogEvent) => void;
|
|
22
|
+
export interface CandidateOptions {
|
|
23
|
+
readonly projectRoot: string;
|
|
24
|
+
readonly token: SupervisorCandidateToken;
|
|
25
|
+
readonly compile: CandidateCompile;
|
|
26
|
+
readonly generatedDirectory?: string;
|
|
27
|
+
readonly hostname?: string;
|
|
28
|
+
readonly port?: number;
|
|
29
|
+
readonly environment?: Readonly<Record<string, string | undefined>>;
|
|
30
|
+
readonly maxStartupOutputBytes?: number;
|
|
31
|
+
readonly stopTimeoutMs?: number;
|
|
32
|
+
readonly signal?: AbortSignal;
|
|
33
|
+
readonly allocatePort?: (hostname: string) => Promise<number>;
|
|
34
|
+
readonly logger?: CandidateLogger;
|
|
35
|
+
}
|
|
36
|
+
export interface CompiledCandidate {
|
|
37
|
+
readonly token: SupervisorCandidateToken;
|
|
38
|
+
readonly directory: string;
|
|
39
|
+
readonly entrypoint: string;
|
|
40
|
+
readonly cleanup: () => Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
export interface CandidateOutput {
|
|
43
|
+
readonly stdout: string;
|
|
44
|
+
readonly stderr: string;
|
|
45
|
+
readonly truncated: boolean;
|
|
46
|
+
}
|
|
47
|
+
export interface StartedCandidate extends CompiledCandidate {
|
|
48
|
+
readonly port: number;
|
|
49
|
+
readonly pid: number;
|
|
50
|
+
readonly process: Bun.ReadableSubprocess;
|
|
51
|
+
readonly exited: Promise<number>;
|
|
52
|
+
readonly output: Promise<CandidateOutput>;
|
|
53
|
+
readonly stop: () => Promise<void>;
|
|
54
|
+
readonly dispose: () => Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=candidate-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"candidate-types.d.ts","sourceRoot":"","sources":["../src/candidate-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"candidate-types.js","sourceRoot":"","sources":["../src/candidate-types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CandidateOptions, CompiledCandidate, StartedCandidate } from "./candidate-types.js";
|
|
2
|
+
export type { CandidateCompile, CandidateCompileRequest, CandidateCompileResult, CandidateLogEvent, CandidateLogger, CandidateOptions, CandidateOutput, CompiledCandidate, StartedCandidate, } from "./candidate-types.js";
|
|
3
|
+
export declare const DEFAULT_CANDIDATE_GENERATED_DIRECTORY = ".relkit/generated";
|
|
4
|
+
export declare const DEFAULT_CANDIDATE_OUTPUT_BYTES: number;
|
|
5
|
+
export declare const DEFAULT_CANDIDATE_STOP_TIMEOUT_MS = 1000;
|
|
6
|
+
/** Compiles one token into an exclusive generation directory. */
|
|
7
|
+
export declare function compileCandidate(options: CandidateOptions): Promise<CompiledCandidate>;
|
|
8
|
+
/** Compiles and starts one Bun backend without changing any active generation. */
|
|
9
|
+
export declare function startCandidate(options: CandidateOptions): Promise<StartedCandidate>;
|
|
10
|
+
//# sourceMappingURL=candidate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"candidate.d.ts","sourceRoot":"","sources":["../src/candidate.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAElG,YAAY,EACV,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,sBAAsB,CAAC;AAE9B,eAAO,MAAM,qCAAqC,sBAAsB,CAAC;AACzE,eAAO,MAAM,8BAA8B,QAAW,CAAC;AACvD,eAAO,MAAM,iCAAiC,OAAQ,CAAC;AAEvD,iEAAiE;AACjE,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAuC5F;AAED,kFAAkF;AAClF,wBAAsB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA2EzF"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { access, mkdir } from "node:fs/promises";
|
|
2
|
+
import { candidateContext, captureOutput, childEnvironment, cleanupCandidate, createStopper, emit, emitFailure, entrypointIn, resolvePort, terminate, throwIfAborted, validateBound, } from "./candidate-process.js";
|
|
3
|
+
export const DEFAULT_CANDIDATE_GENERATED_DIRECTORY = ".relkit/generated";
|
|
4
|
+
export const DEFAULT_CANDIDATE_OUTPUT_BYTES = 8 * 1024;
|
|
5
|
+
export const DEFAULT_CANDIDATE_STOP_TIMEOUT_MS = 1_000;
|
|
6
|
+
/** Compiles one token into an exclusive generation directory. */
|
|
7
|
+
export async function compileCandidate(options) {
|
|
8
|
+
const context = candidateContext(options);
|
|
9
|
+
await mkdir(context.directoryRoot, { recursive: true });
|
|
10
|
+
await mkdir(context.directory);
|
|
11
|
+
emit(options.logger, {
|
|
12
|
+
level: "info",
|
|
13
|
+
event: "candidate.compile.started",
|
|
14
|
+
token: options.token,
|
|
15
|
+
directory: context.directory,
|
|
16
|
+
});
|
|
17
|
+
try {
|
|
18
|
+
throwIfAborted(options.signal);
|
|
19
|
+
const result = await options.compile({
|
|
20
|
+
token: options.token,
|
|
21
|
+
projectRoot: context.projectRoot,
|
|
22
|
+
outputDirectory: context.directory,
|
|
23
|
+
signal: options.signal ?? new AbortController().signal,
|
|
24
|
+
});
|
|
25
|
+
throwIfAborted(options.signal);
|
|
26
|
+
const entrypoint = entrypointIn(context.directory, result.entrypoint);
|
|
27
|
+
await access(entrypoint);
|
|
28
|
+
emit(options.logger, {
|
|
29
|
+
level: "info",
|
|
30
|
+
event: "candidate.compile.succeeded",
|
|
31
|
+
token: options.token,
|
|
32
|
+
directory: context.directory,
|
|
33
|
+
fields: { entrypoint },
|
|
34
|
+
});
|
|
35
|
+
return Object.freeze({
|
|
36
|
+
token: options.token,
|
|
37
|
+
directory: context.directory,
|
|
38
|
+
entrypoint,
|
|
39
|
+
cleanup: () => cleanupCandidate(context.directory, context.directoryRoot),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
emitFailure(options, "candidate.compile.failed", context.directory, error);
|
|
44
|
+
await cleanupCandidate(context.directory, context.directoryRoot).catch(() => undefined);
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** Compiles and starts one Bun backend without changing any active generation. */
|
|
49
|
+
export async function startCandidate(options) {
|
|
50
|
+
const maxOutputBytes = options.maxStartupOutputBytes ?? DEFAULT_CANDIDATE_OUTPUT_BYTES;
|
|
51
|
+
const stopTimeoutMs = options.stopTimeoutMs ?? DEFAULT_CANDIDATE_STOP_TIMEOUT_MS;
|
|
52
|
+
validateBound(maxOutputBytes, "maxStartupOutputBytes", false);
|
|
53
|
+
validateBound(stopTimeoutMs, "stopTimeoutMs", true);
|
|
54
|
+
const compiled = await compileCandidate(options);
|
|
55
|
+
const hostname = options.hostname ?? "127.0.0.1";
|
|
56
|
+
let child;
|
|
57
|
+
try {
|
|
58
|
+
throwIfAborted(options.signal);
|
|
59
|
+
const port = await resolvePort(options, hostname);
|
|
60
|
+
const environment = childEnvironment(options.environment, options.token, port);
|
|
61
|
+
emit(options.logger, {
|
|
62
|
+
level: "info",
|
|
63
|
+
event: "candidate.start.started",
|
|
64
|
+
token: options.token,
|
|
65
|
+
directory: compiled.directory,
|
|
66
|
+
fields: { port },
|
|
67
|
+
});
|
|
68
|
+
child = Bun.spawn([process.execPath, "run", "--no-env-file", "--no-install", "--silent", compiled.entrypoint], {
|
|
69
|
+
cwd: options.projectRoot,
|
|
70
|
+
env: environment,
|
|
71
|
+
stdin: "ignore",
|
|
72
|
+
stdout: "pipe",
|
|
73
|
+
stderr: "pipe",
|
|
74
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
75
|
+
});
|
|
76
|
+
const output = captureOutput(child, options.logger, options.token, compiled.directory, maxOutputBytes);
|
|
77
|
+
const exited = child.exited;
|
|
78
|
+
void exited.then((exitCode) => emit(options.logger, {
|
|
79
|
+
level: exitCode === 0 ? "info" : "error",
|
|
80
|
+
event: "candidate.process-exited",
|
|
81
|
+
token: options.token,
|
|
82
|
+
directory: compiled.directory,
|
|
83
|
+
fields: { exitCode },
|
|
84
|
+
}));
|
|
85
|
+
const stop = createStopper(child, stopTimeoutMs);
|
|
86
|
+
const dispose = async () => {
|
|
87
|
+
await stop();
|
|
88
|
+
await compiled.cleanup();
|
|
89
|
+
};
|
|
90
|
+
emit(options.logger, {
|
|
91
|
+
level: "info",
|
|
92
|
+
event: "candidate.start.succeeded",
|
|
93
|
+
token: options.token,
|
|
94
|
+
directory: compiled.directory,
|
|
95
|
+
fields: { port, pid: child.pid },
|
|
96
|
+
});
|
|
97
|
+
return Object.freeze({
|
|
98
|
+
...compiled,
|
|
99
|
+
port,
|
|
100
|
+
pid: child.pid,
|
|
101
|
+
process: child,
|
|
102
|
+
exited,
|
|
103
|
+
output,
|
|
104
|
+
stop,
|
|
105
|
+
dispose,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
if (child !== undefined)
|
|
110
|
+
await terminate(child, stopTimeoutMs);
|
|
111
|
+
emitFailure(options, "candidate.start.failed", compiled.directory, error);
|
|
112
|
+
await compiled.cleanup().catch(() => undefined);
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=candidate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"candidate.js","sourceRoot":"","sources":["../src/candidate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SupervisorDrainAction, SupervisorDrainCleanupStatus, SupervisorDrainResource } from "./drain-types.js";
|
|
2
|
+
export interface SupervisorDrainCleanupResult {
|
|
3
|
+
readonly status: SupervisorDrainCleanupStatus;
|
|
4
|
+
readonly message?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function closeAction(id: string, action: SupervisorDrainAction | undefined, deadlineAt: number, now: () => number): Promise<SupervisorDrainCleanupResult>;
|
|
7
|
+
export declare function resourceAction(resource: SupervisorDrainResource): SupervisorDrainAction | undefined;
|
|
8
|
+
//# sourceMappingURL=drain-cleanup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drain-cleanup.d.ts","sourceRoot":"","sources":["../src/drain-cleanup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,4BAA4B,EAC5B,uBAAuB,EACxB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,MAAM,EAAE,4BAA4B,CAAC;IAC9C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAsB,WAAW,CAC/B,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,qBAAqB,GAAG,SAAS,EACzC,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,MAAM,GAChB,OAAO,CAAC,4BAA4B,CAAC,CAqBvC;AAED,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,uBAAuB,GAChC,qBAAqB,GAAG,SAAS,CAEnC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export async function closeAction(id, action, deadlineAt, now) {
|
|
2
|
+
if (action === undefined)
|
|
3
|
+
return { status: "not-configured" };
|
|
4
|
+
let operation;
|
|
5
|
+
try {
|
|
6
|
+
operation = action();
|
|
7
|
+
}
|
|
8
|
+
catch (error) {
|
|
9
|
+
return { status: "failed", message: `${id}: ${errorMessage(error)}`.slice(0, 256) };
|
|
10
|
+
}
|
|
11
|
+
return new Promise((resolve) => {
|
|
12
|
+
let timer;
|
|
13
|
+
const finish = (result) => {
|
|
14
|
+
if (timer !== undefined)
|
|
15
|
+
clearTimeout(timer);
|
|
16
|
+
resolve(result);
|
|
17
|
+
};
|
|
18
|
+
timer = setTimeout(() => finish({ status: "timed-out" }), Math.max(0, deadlineAt - now()));
|
|
19
|
+
Promise.resolve(operation).then(() => finish({ status: "closed" }), (error) => finish({ status: "failed", message: `${id}: ${errorMessage(error)}`.slice(0, 256) }));
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
export function resourceAction(resource) {
|
|
23
|
+
return resource.close ?? resource.release ?? resource.dispose;
|
|
24
|
+
}
|
|
25
|
+
function errorMessage(error) {
|
|
26
|
+
return error instanceof Error ? error.message : "Resource cleanup failed.";
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=drain-cleanup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drain-cleanup.js","sourceRoot":"","sources":["../src/drain-cleanup.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,EAAU,EACV,MAAyC,EACzC,UAAkB,EAClB,GAAiB;IAEjB,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC9D,IAAI,SAAmC,CAAC;IACxC,IAAI,CAAC;QACH,SAAS,GAAG,MAAM,EAAE,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;IACtF,CAAC;IACD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,KAAgD,CAAC;QACrD,MAAM,MAAM,GAAG,CAAC,MAAoC,EAAQ,EAAE;YAC5D,IAAI,KAAK,KAAK,SAAS;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YAC7C,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC,CAAC;QACF,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;QAC3F,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CAC7B,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAClC,CAAC,KAAK,EAAE,EAAE,CACR,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CACvF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,QAAiC;IAEjC,OAAO,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC;AAChE,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC;AAC7E,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DrainPreviousGenerationOptions, SupervisorDrainReport } from "./drain-types.js";
|
|
2
|
+
/** Drains the token recorded by the 13.2 state machine and completes its drain transition. */
|
|
3
|
+
export declare function drainPreviousGeneration(options: DrainPreviousGenerationOptions): Promise<SupervisorDrainReport>;
|
|
4
|
+
//# sourceMappingURL=drain-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drain-state.d.ts","sourceRoot":"","sources":["../src/drain-state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,8BAA8B,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE9F,8FAA8F;AAC9F,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,qBAAqB,CAAC,CAqBhC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createSupervisorDrain, SupervisorDrainError } from "./drain.js";
|
|
2
|
+
import { validateSupervisorToken } from "./state-machine-telemetry.js";
|
|
3
|
+
/** Drains the token recorded by the 13.2 state machine and completes its drain transition. */
|
|
4
|
+
export async function drainPreviousGeneration(options) {
|
|
5
|
+
validateSupervisorToken(options.activeToken);
|
|
6
|
+
const snapshot = options.stateMachine.snapshot();
|
|
7
|
+
if (snapshot.state !== "draining-previous" ||
|
|
8
|
+
!sameToken(snapshot.previousGeneration, options.token) ||
|
|
9
|
+
!sameToken(snapshot.activeGeneration, options.activeToken)) {
|
|
10
|
+
throw new SupervisorDrainError(snapshot.state === "draining-previous"
|
|
11
|
+
? "RELKIT_DRAIN_TOKEN_MISMATCH"
|
|
12
|
+
: "RELKIT_DRAIN_STATE_INVALID", "The state machine no longer owns the retired generation.");
|
|
13
|
+
}
|
|
14
|
+
const report = await createSupervisorDrain(options).drain();
|
|
15
|
+
const completed = report.outcome === "drained"
|
|
16
|
+
? options.stateMachine.drainSucceeded(options.activeToken)
|
|
17
|
+
: options.stateMachine.drainFailed(options.activeToken, report.outcome);
|
|
18
|
+
return Object.freeze({ ...report, stateTransition: completed ? "completed" : "stale" });
|
|
19
|
+
}
|
|
20
|
+
function sameToken(left, right) {
|
|
21
|
+
return (left !== undefined &&
|
|
22
|
+
right !== undefined &&
|
|
23
|
+
left.sourceToken === right.sourceToken &&
|
|
24
|
+
left.generationToken === right.generationToken);
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=drain-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drain-state.js","sourceRoot":"","sources":["../src/drain-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAIvE,8FAA8F;AAC9F,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,OAAuC;IAEvC,uBAAuB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;IACjD,IACE,QAAQ,CAAC,KAAK,KAAK,mBAAmB;QACtC,CAAC,SAAS,CAAC,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC,KAAK,CAAC;QACtD,CAAC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC,WAAW,CAAC,EAC1D,CAAC;QACD,MAAM,IAAI,oBAAoB,CAC5B,QAAQ,CAAC,KAAK,KAAK,mBAAmB;YACpC,CAAC,CAAC,6BAA6B;YAC/B,CAAC,CAAC,4BAA4B,EAChC,0DAA0D,CAC3D,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC;IAC5D,MAAM,SAAS,GACb,MAAM,CAAC,OAAO,KAAK,SAAS;QAC1B,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC;QAC1D,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5E,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,EAAE,eAAe,EAAE,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AAC1F,CAAC;AAED,SAAS,SAAS,CAChB,IAA0C,EAC1C,KAA2C;IAE3C,OAAO,CACL,IAAI,KAAK,SAAS;QAClB,KAAK,KAAK,SAAS;QACnB,IAAI,CAAC,WAAW,KAAK,KAAK,CAAC,WAAW;QACtC,IAAI,CAAC,eAAe,KAAK,KAAK,CAAC,eAAe,CAC/C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { StartedCandidate } from "./candidate-types.js";
|
|
2
|
+
import type { SupervisorCandidateToken, SupervisorStateSnapshot } from "./state-machine-types.js";
|
|
3
|
+
export type SupervisorDrainAction = () => void | PromiseLike<void>;
|
|
4
|
+
export interface SupervisorDrainResource {
|
|
5
|
+
readonly id?: string;
|
|
6
|
+
readonly close?: SupervisorDrainAction;
|
|
7
|
+
readonly release?: SupervisorDrainAction;
|
|
8
|
+
readonly dispose?: SupervisorDrainAction;
|
|
9
|
+
}
|
|
10
|
+
export interface SupervisorDrainWorkOptions {
|
|
11
|
+
readonly interrupt?: (reason: unknown) => void | PromiseLike<void>;
|
|
12
|
+
}
|
|
13
|
+
export interface SupervisorDrainLease {
|
|
14
|
+
readonly token: SupervisorCandidateToken;
|
|
15
|
+
readonly signal: AbortSignal;
|
|
16
|
+
readonly release: () => void;
|
|
17
|
+
}
|
|
18
|
+
export type SupervisorDrainCleanupStatus = "not-configured" | "closed" | "failed" | "timed-out";
|
|
19
|
+
export interface SupervisorDrainResourceResult {
|
|
20
|
+
readonly id: string;
|
|
21
|
+
readonly status: SupervisorDrainCleanupStatus;
|
|
22
|
+
}
|
|
23
|
+
export type SupervisorDrainOutcome = "drained" | "interrupted" | "timed-out" | "failed";
|
|
24
|
+
export type SupervisorDrainStateTransition = "not-configured" | "completed" | "stale";
|
|
25
|
+
export interface SupervisorDrainFailure {
|
|
26
|
+
readonly resource: string;
|
|
27
|
+
readonly message: string;
|
|
28
|
+
}
|
|
29
|
+
export interface SupervisorDrainReport {
|
|
30
|
+
readonly token: SupervisorCandidateToken;
|
|
31
|
+
readonly deadlineMs: number;
|
|
32
|
+
readonly elapsedMs: number;
|
|
33
|
+
readonly initialInFlight: number;
|
|
34
|
+
readonly completed: number;
|
|
35
|
+
readonly interrupted: number;
|
|
36
|
+
readonly remaining: number;
|
|
37
|
+
readonly timedOut: boolean;
|
|
38
|
+
readonly outcome: SupervisorDrainOutcome;
|
|
39
|
+
readonly candidate: SupervisorDrainCleanupStatus;
|
|
40
|
+
readonly providers: readonly SupervisorDrainResourceResult[];
|
|
41
|
+
readonly failures: readonly SupervisorDrainFailure[];
|
|
42
|
+
readonly stateTransition: SupervisorDrainStateTransition;
|
|
43
|
+
}
|
|
44
|
+
export interface SupervisorDrainOptions {
|
|
45
|
+
readonly token: SupervisorCandidateToken;
|
|
46
|
+
readonly deadlineMs?: number;
|
|
47
|
+
readonly now?: () => number;
|
|
48
|
+
readonly candidate?: Pick<StartedCandidate, "token" | "dispose">;
|
|
49
|
+
readonly providers?: readonly SupervisorDrainResource[];
|
|
50
|
+
readonly onReport?: (report: SupervisorDrainReport) => void;
|
|
51
|
+
}
|
|
52
|
+
export interface SupervisorDrainStateMachine {
|
|
53
|
+
readonly snapshot: () => SupervisorStateSnapshot;
|
|
54
|
+
readonly drainSucceeded: (token: SupervisorCandidateToken) => boolean;
|
|
55
|
+
readonly drainFailed: (token: SupervisorCandidateToken, reason: unknown) => boolean;
|
|
56
|
+
}
|
|
57
|
+
export interface DrainPreviousGenerationOptions extends SupervisorDrainOptions {
|
|
58
|
+
readonly activeToken: SupervisorCandidateToken;
|
|
59
|
+
readonly stateMachine: SupervisorDrainStateMachine;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=drain-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drain-types.d.ts","sourceRoot":"","sources":["../src/drain-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drain-types.js","sourceRoot":"","sources":["../src/drain-types.ts"],"names":[],"mappings":""}
|