@sift-wiki/conductor 0.2.0-beta.1 → 0.2.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/dist/adapters/claudeAgent.js +1 -0
- package/dist/adapters/claudeAgent.js.map +1 -1
- package/dist/adapters/codexAgent.js +1 -0
- package/dist/adapters/codexAgent.js.map +1 -1
- package/dist/adapters/fakeAgent.js +1 -0
- package/dist/adapters/fakeAgent.js.map +1 -1
- package/dist/adapters/httpAgent.js +1 -0
- package/dist/adapters/httpAgent.js.map +1 -1
- package/dist/adapters/processAgent.js +4 -0
- package/dist/adapters/processAgent.js.map +1 -1
- package/dist/adapters/provider/runProvider.js +4 -0
- package/dist/adapters/provider/runProvider.js.map +1 -1
- package/dist/adapters/provider/store.js +3 -4
- package/dist/adapters/provider/store.js.map +1 -1
- package/dist/adapters/types.d.ts +9 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +16 -4
- package/dist/cli.js.map +1 -1
- package/dist/conductorClient.d.ts +56 -19
- package/dist/conductorClient.js +91 -40
- package/dist/conductorClient.js.map +1 -1
- package/dist/config.js +4 -5
- package/dist/config.js.map +1 -1
- package/dist/daemon.d.ts +19 -6
- package/dist/daemon.js +199 -121
- package/dist/daemon.js.map +1 -1
- package/dist/desktop/app/controller.d.ts +1 -1
- package/dist/desktop/app/runtimeController.d.ts +7 -0
- package/dist/desktop/app/runtimeController.js +12 -1
- package/dist/desktop/app/runtimeController.js.map +1 -1
- package/dist/localApi/contracts.d.ts +15 -4
- package/dist/localApi/contracts.js +19 -1
- package/dist/localApi/contracts.js.map +1 -1
- package/dist/localApi/recovery.d.ts +66 -0
- package/dist/localApi/recovery.js +118 -0
- package/dist/localApi/recovery.js.map +1 -0
- package/dist/localApi/server.js +3 -1
- package/dist/localApi/server.js.map +1 -1
- package/dist/localApp/service.js +16 -4
- package/dist/localApp/service.js.map +1 -1
- package/dist/protocol/fenced.d.ts +135 -0
- package/dist/protocol/fenced.js +142 -0
- package/dist/protocol/fenced.js.map +1 -0
- package/dist/redaction.js +2 -0
- package/dist/redaction.js.map +1 -1
- package/dist/runtime/atomicFile.d.ts +6 -0
- package/dist/runtime/atomicFile.js +78 -0
- package/dist/runtime/atomicFile.js.map +1 -0
- package/dist/runtime/daemonCapabilities.d.ts +7 -0
- package/dist/runtime/daemonCapabilities.js +24 -0
- package/dist/runtime/daemonCapabilities.js.map +1 -0
- package/dist/runtime/eventOutbox.d.ts +100 -0
- package/dist/runtime/eventOutbox.js +206 -0
- package/dist/runtime/eventOutbox.js.map +1 -0
- package/dist/runtime/executionJournal.d.ts +102 -0
- package/dist/runtime/executionJournal.js +209 -0
- package/dist/runtime/executionJournal.js.map +1 -0
- package/dist/runtime/executionSafety.d.ts +76 -0
- package/dist/runtime/executionSafety.js +207 -0
- package/dist/runtime/executionSafety.js.map +1 -0
- package/dist/runtime/fencedExecutionState.d.ts +43 -0
- package/dist/runtime/fencedExecutionState.js +158 -0
- package/dist/runtime/fencedExecutionState.js.map +1 -0
- package/dist/runtime/leaseManager.d.ts +38 -0
- package/dist/runtime/leaseManager.js +102 -0
- package/dist/runtime/leaseManager.js.map +1 -0
- package/dist/runtime/localRunQueue.d.ts +1 -1
- package/dist/runtime/localRunQueue.js +8 -0
- package/dist/runtime/localRunQueue.js.map +1 -1
- package/dist/runtime/localSessionCache.d.ts +1 -1
- package/dist/runtime/localSessionCache.js.map +1 -1
- package/dist/runtime/process.d.ts +13 -1
- package/dist/runtime/process.js +39 -9
- package/dist/runtime/process.js.map +1 -1
- package/dist/runtime/recoveryCoordinator.d.ts +19 -0
- package/dist/runtime/recoveryCoordinator.js +183 -0
- package/dist/runtime/recoveryCoordinator.js.map +1 -0
- package/dist/runtime/runtimeLock.d.ts +33 -0
- package/dist/runtime/runtimeLock.js +140 -0
- package/dist/runtime/runtimeLock.js.map +1 -0
- package/dist/runtime/runtimeService.d.ts +6 -1
- package/dist/runtime/runtimeService.js +54 -20
- package/dist/runtime/runtimeService.js.map +1 -1
- package/dist/runtime/taskExecution.d.ts +4 -0
- package/dist/runtime/taskExecution.js +32 -12
- package/dist/runtime/taskExecution.js.map +1 -1
- package/dist/types.d.ts +28 -13
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/workTypes.d.ts +5 -5
- package/dist-web/assets/index-SwT063kc.js +72 -0
- package/dist-web/index.html +2 -2
- package/package.json +1 -1
- package/dist-web/assets/index-D5X9InfE.js +0 -72
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ChildProcess, type SpawnOptions } from "node:child_process";
|
|
2
|
+
import type { SafeProcessIdentity } from "./executionJournal.js";
|
|
2
3
|
export type ProcessLogStream = "stdout" | "stderr";
|
|
3
4
|
export type RunProcessInput = {
|
|
4
5
|
command: string;
|
|
@@ -11,6 +12,7 @@ export type RunProcessInput = {
|
|
|
11
12
|
outputLimitBytes: number;
|
|
12
13
|
signal: AbortSignal;
|
|
13
14
|
onLog(stream: ProcessLogStream, chunk: string): Promise<void>;
|
|
15
|
+
onStarted?: ((identity: SafeProcessIdentity) => Promise<void>) | undefined;
|
|
14
16
|
};
|
|
15
17
|
export type RunProcessResult = {
|
|
16
18
|
exitCode: number | null;
|
|
@@ -23,5 +25,15 @@ export type RunProcessResult = {
|
|
|
23
25
|
};
|
|
24
26
|
export type RunProcess = (input: RunProcessInput) => Promise<RunProcessResult>;
|
|
25
27
|
export type SpawnLike = (command: string, args: string[], options: SpawnOptions) => ChildProcess;
|
|
26
|
-
export
|
|
28
|
+
export type ProcessTreeTerminator = (input: {
|
|
29
|
+
child: ChildProcess;
|
|
30
|
+
processGroupId: number | null;
|
|
31
|
+
signal: NodeJS.Signals;
|
|
32
|
+
}) => void;
|
|
33
|
+
export declare function createProcessRunner(spawn?: SpawnLike, terminate?: ProcessTreeTerminator, readStartMarker?: (pid: number) => Promise<string | undefined>): RunProcess;
|
|
27
34
|
export declare const runChildProcess: RunProcess;
|
|
35
|
+
export declare function processTreeTerminationCapability(platform?: NodeJS.Platform): {
|
|
36
|
+
supported: boolean;
|
|
37
|
+
mechanism: "process-group" | "taskkill-tree";
|
|
38
|
+
};
|
|
39
|
+
export declare function windowsTaskkillArgs(pid: number, signal: NodeJS.Signals): string[];
|
package/dist/runtime/process.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { spawn as nodeSpawn } from "node:child_process";
|
|
1
|
+
import { execFile, spawn as nodeSpawn, } from "node:child_process";
|
|
2
2
|
import { Buffer } from "node:buffer";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { readProcessStartMarker } from "./runtimeLock.js";
|
|
4
|
+
export function createProcessRunner(spawn = nodeSpawn, terminate = terminateProcessTree, readStartMarker = readProcessStartMarker) {
|
|
5
|
+
return (input) => runChildProcessWithSpawn(input, spawn, terminate, readStartMarker);
|
|
5
6
|
}
|
|
6
7
|
export const runChildProcess = createProcessRunner();
|
|
7
|
-
async function runChildProcessWithSpawn(input, spawn) {
|
|
8
|
+
async function runChildProcessWithSpawn(input, spawn, terminate, readStartMarker) {
|
|
8
9
|
return new Promise((resolve, reject) => {
|
|
9
10
|
const child = spawn(input.command, input.args, {
|
|
10
11
|
cwd: input.cwd,
|
|
@@ -25,6 +26,7 @@ async function runChildProcessWithSpawn(input, spawn) {
|
|
|
25
26
|
let logChain = Promise.resolve();
|
|
26
27
|
let timeout;
|
|
27
28
|
let killTimeout;
|
|
29
|
+
const startPromise = recordProcessIdentity(child, input, readStartMarker);
|
|
28
30
|
const requestStop = (reason) => {
|
|
29
31
|
if (closed) {
|
|
30
32
|
return;
|
|
@@ -32,12 +34,13 @@ async function runChildProcessWithSpawn(input, spawn) {
|
|
|
32
34
|
if (reason === "timeout") {
|
|
33
35
|
timedOut = true;
|
|
34
36
|
}
|
|
35
|
-
|
|
37
|
+
terminate({ child, processGroupId, signal: "SIGTERM" });
|
|
36
38
|
killTimeout ??= setTimeout(() => {
|
|
37
|
-
|
|
39
|
+
terminate({ child, processGroupId, signal: "SIGKILL" });
|
|
38
40
|
}, Math.max(1, input.graceMs));
|
|
39
41
|
};
|
|
40
42
|
const onAbort = () => requestStop("abort");
|
|
43
|
+
void startPromise.catch(() => requestStop("abort"));
|
|
41
44
|
input.signal.addEventListener("abort", onAbort, { once: true });
|
|
42
45
|
if (input.signal.aborted) {
|
|
43
46
|
requestStop("abort");
|
|
@@ -69,7 +72,7 @@ async function runChildProcessWithSpawn(input, spawn) {
|
|
|
69
72
|
child.on("close", (code, closeSignal) => {
|
|
70
73
|
closed = true;
|
|
71
74
|
cleanup();
|
|
72
|
-
void logChain.
|
|
75
|
+
void Promise.all([logChain, startPromise]).then(() => {
|
|
73
76
|
resolve({
|
|
74
77
|
exitCode: code,
|
|
75
78
|
signal: closeSignal,
|
|
@@ -79,7 +82,7 @@ async function runChildProcessWithSpawn(input, spawn) {
|
|
|
79
82
|
pid: child.pid ?? null,
|
|
80
83
|
startedAt,
|
|
81
84
|
});
|
|
82
|
-
});
|
|
85
|
+
}).catch(reject);
|
|
83
86
|
});
|
|
84
87
|
function cleanup() {
|
|
85
88
|
input.signal.removeEventListener("abort", onAbort);
|
|
@@ -92,13 +95,22 @@ async function runChildProcessWithSpawn(input, spawn) {
|
|
|
92
95
|
}
|
|
93
96
|
});
|
|
94
97
|
}
|
|
98
|
+
async function recordProcessIdentity(child, input, readStartMarker) {
|
|
99
|
+
if (input.onStarted === undefined || child.pid === undefined || child.pid <= 0)
|
|
100
|
+
return;
|
|
101
|
+
const startMarker = await readStartMarker(child.pid);
|
|
102
|
+
if (startMarker === undefined)
|
|
103
|
+
return;
|
|
104
|
+
await input.onStarted({ pid: child.pid, startMarker });
|
|
105
|
+
}
|
|
95
106
|
function resolveProcessGroupId(child) {
|
|
96
107
|
if (process.platform === "win32") {
|
|
97
108
|
return null;
|
|
98
109
|
}
|
|
99
110
|
return typeof child.pid === "number" && child.pid > 0 ? child.pid : null;
|
|
100
111
|
}
|
|
101
|
-
function
|
|
112
|
+
function terminateProcessTree(input) {
|
|
113
|
+
const { child, processGroupId, signal } = input;
|
|
102
114
|
if (process.platform !== "win32" && processGroupId !== null) {
|
|
103
115
|
try {
|
|
104
116
|
process.kill(-processGroupId, signal);
|
|
@@ -108,10 +120,28 @@ function signalRunningProcess(child, processGroupId, signal) {
|
|
|
108
120
|
// Fall through to direct child signaling.
|
|
109
121
|
}
|
|
110
122
|
}
|
|
123
|
+
if (process.platform === "win32" && typeof child.pid === "number" && child.pid > 0) {
|
|
124
|
+
execFile("taskkill.exe", windowsTaskkillArgs(child.pid, signal), { windowsHide: true }, (error) => {
|
|
125
|
+
if (error !== null)
|
|
126
|
+
signalDirectChild(child, signal);
|
|
127
|
+
});
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
signalDirectChild(child, signal);
|
|
131
|
+
}
|
|
132
|
+
function signalDirectChild(child, signal) {
|
|
111
133
|
if (!child.killed) {
|
|
112
134
|
child.kill(signal);
|
|
113
135
|
}
|
|
114
136
|
}
|
|
137
|
+
export function processTreeTerminationCapability(platform = process.platform) {
|
|
138
|
+
return platform === "win32"
|
|
139
|
+
? { supported: true, mechanism: "taskkill-tree" }
|
|
140
|
+
: { supported: true, mechanism: "process-group" };
|
|
141
|
+
}
|
|
142
|
+
export function windowsTaskkillArgs(pid, signal) {
|
|
143
|
+
return ["/PID", String(pid), "/T", ...(signal === "SIGKILL" ? ["/F"] : [])];
|
|
144
|
+
}
|
|
115
145
|
function chunkToString(chunk) {
|
|
116
146
|
return Buffer.isBuffer(chunk) ? chunk.toString("utf8") : String(chunk);
|
|
117
147
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/runtime/process.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/runtime/process.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { LocalAgentAdapter } from "../adapters/types.js";
|
|
2
|
+
import type { ConductorClient, ConductorWorkClient } from "../types.js";
|
|
3
|
+
import type { DurableEventOutbox } from "./eventOutbox.js";
|
|
4
|
+
import type { ExecutionJournalStore } from "./executionJournal.js";
|
|
5
|
+
export type RecoverySummary = {
|
|
6
|
+
reconciledAttempts: number;
|
|
7
|
+
resumedAttempts: number;
|
|
8
|
+
closedAttempts: number;
|
|
9
|
+
canClaim: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare function reconcileUnfinishedAttempts(input: {
|
|
12
|
+
credential: string;
|
|
13
|
+
client: Pick<ConductorClient, "reconcileAttempt" | "appendRunEvent"> & Partial<Pick<ConductorClient, "acknowledgeCancellation">>;
|
|
14
|
+
workClient?: Pick<ConductorWorkClient, "setTaskDisposition"> | undefined;
|
|
15
|
+
journalStore: ExecutionJournalStore;
|
|
16
|
+
outbox: DurableEventOutbox;
|
|
17
|
+
adapters: LocalAgentAdapter[];
|
|
18
|
+
now?: (() => Date) | undefined;
|
|
19
|
+
}): Promise<RecoverySummary>;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { ConductorApiError } from "../conductorClient.js";
|
|
2
|
+
export async function reconcileUnfinishedAttempts(input) {
|
|
3
|
+
const unfinished = await input.journalStore.listUnfinished();
|
|
4
|
+
if (unfinished.length === 0) {
|
|
5
|
+
return { reconciledAttempts: 0, resumedAttempts: 0, closedAttempts: 0, canClaim: true };
|
|
6
|
+
}
|
|
7
|
+
if (input.client.reconcileAttempt === undefined) {
|
|
8
|
+
throw new Error("Sift reconciliation is unavailable while unfinished fenced attempts exist.");
|
|
9
|
+
}
|
|
10
|
+
let resumedAttempts = 0;
|
|
11
|
+
let closedAttempts = 0;
|
|
12
|
+
let canClaim = true;
|
|
13
|
+
for (const entry of unfinished) {
|
|
14
|
+
const journal = await updateJournal(input, entry.journal, { phase: "recovering" });
|
|
15
|
+
const adapter = input.adapters.find((candidate) => candidate.localKey === journal.localKey);
|
|
16
|
+
const providerResumeSupported = adapter?.resumeSupport === "session";
|
|
17
|
+
const decision = await input.client.reconcileAttempt(input.credential, {
|
|
18
|
+
attemptId: journal.authority.attemptId,
|
|
19
|
+
leaseGeneration: journal.authority.leaseGeneration,
|
|
20
|
+
lastAcknowledgedClientSequence: journal.lastAcknowledgedClientSequence,
|
|
21
|
+
providerResumeSupported,
|
|
22
|
+
supervisedProcessRunning: false,
|
|
23
|
+
...(journal.terminalResult === undefined
|
|
24
|
+
? {}
|
|
25
|
+
: {
|
|
26
|
+
terminalResult: {
|
|
27
|
+
disposition: journal.terminalResult.status === "overtime"
|
|
28
|
+
? "failed"
|
|
29
|
+
: journal.terminalResult.status,
|
|
30
|
+
summary: { summary: journal.terminalResult.summary },
|
|
31
|
+
},
|
|
32
|
+
}),
|
|
33
|
+
});
|
|
34
|
+
if (decision.decision === "resume") {
|
|
35
|
+
resumedAttempts += 1;
|
|
36
|
+
if (!providerResumeSupported && journal.terminalResult === undefined) {
|
|
37
|
+
await updateJournal(input, journal, {
|
|
38
|
+
phase: "interrupted",
|
|
39
|
+
interruptionReason: "Sift returned resume for a provider without verified safe resume support.",
|
|
40
|
+
});
|
|
41
|
+
canClaim = false;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const resumed = await applyResume(input, journal, { ...decision, decision: "resume" });
|
|
45
|
+
if (resumed.terminalResult === undefined)
|
|
46
|
+
canClaim = false;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (decision.decision === "stop" && !isTerminalCanonicalStatus(decision.canonicalStatus)) {
|
|
50
|
+
if (decision.cancellationRequested) {
|
|
51
|
+
try {
|
|
52
|
+
const settled = await settleCancellation(input, journal);
|
|
53
|
+
await updateJournal(input, journal, {
|
|
54
|
+
phase: "terminal",
|
|
55
|
+
terminalResult: journal.terminalResult ?? {
|
|
56
|
+
status: "cancelled",
|
|
57
|
+
summary: settled.summary,
|
|
58
|
+
},
|
|
59
|
+
interruptionReason: "Canonical cancellation confirmed during recovery.",
|
|
60
|
+
});
|
|
61
|
+
await input.outbox.discardAttempt(journal.attemptId);
|
|
62
|
+
closedAttempts += 1;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
canClaim = false;
|
|
67
|
+
await updateJournal(input, journal, {
|
|
68
|
+
phase: "recovering",
|
|
69
|
+
interruptionReason: `Cancellation settlement remains pending: ${errorMessage(error)}`,
|
|
70
|
+
});
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
canClaim = false;
|
|
75
|
+
await updateJournal(input, journal, {
|
|
76
|
+
phase: "recovering",
|
|
77
|
+
interruptionReason: decision.reason ?? "Sift returned stop while canonical work remains nonterminal.",
|
|
78
|
+
});
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
await updateJournal(input, journal, decisionJournalUpdate(decision));
|
|
82
|
+
await input.outbox.discardAttempt(journal.attemptId);
|
|
83
|
+
closedAttempts += 1;
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
reconciledAttempts: unfinished.length,
|
|
87
|
+
resumedAttempts,
|
|
88
|
+
closedAttempts,
|
|
89
|
+
canClaim,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
async function settleCancellation(input, journal) {
|
|
93
|
+
const summary = journal.terminalResult?.status === "cancelled"
|
|
94
|
+
? journal.terminalResult.summary
|
|
95
|
+
: "Stopped local execution after Sift cancellation during recovery.";
|
|
96
|
+
const options = {
|
|
97
|
+
authority: journal.authority,
|
|
98
|
+
idempotencyKey: journal.settlementIdempotencyKey ?? `recovery-cancel:${journal.attemptId}`,
|
|
99
|
+
};
|
|
100
|
+
if (journal.taskRecordId !== undefined) {
|
|
101
|
+
if (input.workClient === undefined) {
|
|
102
|
+
throw new Error("Task cancellation settlement client is unavailable.");
|
|
103
|
+
}
|
|
104
|
+
await input.workClient.setTaskDisposition(input.credential, journal.runId, journal.taskRecordId, "cancelled", { summary }, options);
|
|
105
|
+
return { summary };
|
|
106
|
+
}
|
|
107
|
+
if (input.client.acknowledgeCancellation === undefined) {
|
|
108
|
+
throw new Error("Run cancellation settlement client is unavailable.");
|
|
109
|
+
}
|
|
110
|
+
await input.client.acknowledgeCancellation(input.credential, journal.runId, { summary }, options);
|
|
111
|
+
return { summary };
|
|
112
|
+
}
|
|
113
|
+
function isTerminalCanonicalStatus(status) {
|
|
114
|
+
return status === "completed" || status === "failed" || status === "cancelled";
|
|
115
|
+
}
|
|
116
|
+
function errorMessage(error) {
|
|
117
|
+
return error instanceof Error ? error.message : "Unknown cancellation settlement failure.";
|
|
118
|
+
}
|
|
119
|
+
async function applyResume(input, journal, decision) {
|
|
120
|
+
if (decision.authority === undefined) {
|
|
121
|
+
throw new Error("Resume reconciliation omitted refreshed authority.");
|
|
122
|
+
}
|
|
123
|
+
let next = await updateJournal(input, journal, {
|
|
124
|
+
authority: decision.authority,
|
|
125
|
+
lastAcknowledgedClientSequence: Math.max(journal.lastAcknowledgedClientSequence, decision.lastAcknowledgedClientSequence),
|
|
126
|
+
phase: "recovering",
|
|
127
|
+
});
|
|
128
|
+
await input.outbox.acknowledge(next.attemptId, next.lastAcknowledgedClientSequence);
|
|
129
|
+
for (const entry of await input.outbox.listAttempt(next.attemptId)) {
|
|
130
|
+
let response;
|
|
131
|
+
try {
|
|
132
|
+
response = await input.client.appendRunEvent(input.credential, next.runId, {
|
|
133
|
+
eventType: entry.event.eventType,
|
|
134
|
+
...(entry.event.payload === undefined ? {} : { payload: entry.event.payload }),
|
|
135
|
+
...(entry.event.occurredAt === undefined ? {} : { occurredAt: entry.event.occurredAt }),
|
|
136
|
+
clientEventId: entry.clientEventId,
|
|
137
|
+
clientSequence: entry.clientSequence,
|
|
138
|
+
authority: next.authority,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
if (error instanceof ConductorApiError && error.disposition === "retryable")
|
|
143
|
+
throw error;
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
const acknowledged = acknowledgementSequence(response);
|
|
147
|
+
if (acknowledged === undefined) {
|
|
148
|
+
throw new Error("Fenced event delivery response omitted acknowledgedClientSequence.");
|
|
149
|
+
}
|
|
150
|
+
await input.outbox.acknowledge(next.attemptId, acknowledged);
|
|
151
|
+
next = await updateJournal(input, next, {
|
|
152
|
+
lastAcknowledgedClientSequence: Math.max(next.lastAcknowledgedClientSequence, acknowledged),
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return next;
|
|
156
|
+
}
|
|
157
|
+
function decisionJournalUpdate(decision) {
|
|
158
|
+
switch (decision.decision) {
|
|
159
|
+
case "already_terminal":
|
|
160
|
+
return { phase: "terminal", interruptionReason: decision.reason ?? "Canonical run is already terminal." };
|
|
161
|
+
case "superseded":
|
|
162
|
+
return { phase: "superseded", interruptionReason: decision.reason ?? "Another attempt owns this work." };
|
|
163
|
+
case "stop":
|
|
164
|
+
return { phase: "interrupted", interruptionReason: decision.reason ?? "Sift instructed local execution to stop." };
|
|
165
|
+
case "retry_as_new_attempt":
|
|
166
|
+
return { phase: "interrupted", interruptionReason: decision.reason ?? "Retry requires a new fenced attempt." };
|
|
167
|
+
case "resume":
|
|
168
|
+
throw new Error("Resume decisions require refreshed authority handling.");
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
async function updateJournal(input, journal, update) {
|
|
172
|
+
const next = {
|
|
173
|
+
...journal,
|
|
174
|
+
...update,
|
|
175
|
+
updatedAt: (input.now ?? (() => new Date()))().toISOString(),
|
|
176
|
+
};
|
|
177
|
+
await input.journalStore.write(next);
|
|
178
|
+
return next;
|
|
179
|
+
}
|
|
180
|
+
function acknowledgementSequence(response) {
|
|
181
|
+
return response.acknowledgedClientSequence;
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=recoveryCoordinator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recoveryCoordinator.js","sourceRoot":"","sources":["../../src/runtime/recoveryCoordinator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAqB1D,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,KASjD;IACC,MAAM,UAAU,GAAG,MAAM,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,CAAC;IAC7D,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,kBAAkB,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1F,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,4EAA4E,CAAC,CAAC;IAChG,CAAC;IAED,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,IAAI,QAAQ,GAAG,IAAI,CAAC;IACpB,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;QACnF,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC5F,MAAM,uBAAuB,GAAG,OAAO,EAAE,aAAa,KAAK,SAAS,CAAC;QACrE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,UAAU,EAAE;YACrE,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,SAAS;YACtC,eAAe,EAAE,OAAO,CAAC,SAAS,CAAC,eAAe;YAClD,8BAA8B,EAAE,OAAO,CAAC,8BAA8B;YACtE,uBAAuB;YACvB,wBAAwB,EAAE,KAAK;YAC/B,GAAG,CAAC,OAAO,CAAC,cAAc,KAAK,SAAS;gBACtC,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC;oBACE,cAAc,EAAE;wBACd,WAAW,EAAE,OAAO,CAAC,cAAc,CAAC,MAAM,KAAK,UAAU;4BACvD,CAAC,CAAC,QAAQ;4BACV,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM;wBACjC,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE;qBACrD;iBACF,CAAC;SACP,CAAC,CAAC;QACH,IAAI,QAAQ,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACnC,eAAe,IAAI,CAAC,CAAC;YACrB,IAAI,CAAC,uBAAuB,IAAI,OAAO,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;gBACrE,MAAM,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE;oBAClC,KAAK,EAAE,aAAa;oBACpB,kBAAkB,EAAE,2EAA2E;iBAChG,CAAC,CAAC;gBACH,QAAQ,GAAG,KAAK,CAAC;gBACjB,SAAS;YACX,CAAC;YACD,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,GAAG,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;YACvF,IAAI,OAAO,CAAC,cAAc,KAAK,SAAS;gBAAE,QAAQ,GAAG,KAAK,CAAC;YAC3D,SAAS;QACX,CAAC;QACD,IAAI,QAAQ,CAAC,QAAQ,KAAK,MAAM,IAAI,CAAC,yBAAyB,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;YACzF,IAAI,QAAQ,CAAC,qBAAqB,EAAE,CAAC;gBACnC,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;oBACzD,MAAM,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE;wBAClC,KAAK,EAAE,UAAU;wBACjB,cAAc,EAAE,OAAO,CAAC,cAAc,IAAI;4BACxC,MAAM,EAAE,WAAW;4BACnB,OAAO,EAAE,OAAO,CAAC,OAAO;yBACzB;wBACD,kBAAkB,EAAE,mDAAmD;qBACxE,CAAC,CAAC;oBACH,MAAM,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;oBACrD,cAAc,IAAI,CAAC,CAAC;oBACpB,SAAS;gBACX,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,QAAQ,GAAG,KAAK,CAAC;oBACjB,MAAM,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE;wBAClC,KAAK,EAAE,YAAY;wBACnB,kBAAkB,EAAE,4CAA4C,YAAY,CAAC,KAAK,CAAC,EAAE;qBACtF,CAAC,CAAC;oBACH,SAAS;gBACX,CAAC;YACH,CAAC;YACD,QAAQ,GAAG,KAAK,CAAC;YACjB,MAAM,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE;gBAClC,KAAK,EAAE,YAAY;gBACnB,kBAAkB,EAAE,QAAQ,CAAC,MAAM,IAAI,8DAA8D;aACtG,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,MAAM,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC,CAAC;QACrE,MAAM,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACrD,cAAc,IAAI,CAAC,CAAC;IACtB,CAAC;IACD,OAAO;QACL,kBAAkB,EAAE,UAAU,CAAC,MAAM;QACrC,eAAe;QACf,cAAc;QACd,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,KAAwD,EACxD,OAAyB;IAEzB,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,MAAM,KAAK,WAAW;QAC5D,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO;QAChC,CAAC,CAAC,kEAAkE,CAAC;IACvE,MAAM,OAAO,GAAG;QACd,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,cAAc,EACZ,OAAO,CAAC,wBAAwB,IAAI,mBAAmB,OAAO,CAAC,SAAS,EAAE;KAC7E,CAAC;IACF,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QACvC,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,KAAK,CAAC,UAAU,CAAC,kBAAkB,CACvC,KAAK,CAAC,UAAU,EAChB,OAAO,CAAC,KAAK,EACb,OAAO,CAAC,YAAY,EACpB,WAAW,EACX,EAAE,OAAO,EAAE,EACX,OAAO,CACR,CAAC;QACF,OAAO,EAAE,OAAO,EAAE,CAAC;IACrB,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,CAAC,uBAAuB,KAAK,SAAS,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IACD,MAAM,KAAK,CAAC,MAAM,CAAC,uBAAuB,CACxC,KAAK,CAAC,UAAU,EAChB,OAAO,CAAC,KAAK,EACb,EAAE,OAAO,EAAE,EACX,OAAO,CACR,CAAC;IACF,OAAO,EAAE,OAAO,EAAE,CAAC;AACrB,CAAC;AAED,SAAS,yBAAyB,CAAC,MAAc;IAC/C,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,WAAW,CAAC;AACjF,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,0CAA0C,CAAC;AAC7F,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,KAAwD,EACxD,OAAyB,EACzB,QAA2D;IAE3D,IAAI,QAAQ,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,IAAI,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE;QAC7C,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,8BAA8B,EAAE,IAAI,CAAC,GAAG,CACtC,OAAO,CAAC,8BAA8B,EACtC,QAAQ,CAAC,8BAA8B,CACxC;QACD,KAAK,EAAE,YAAY;KACpB,CAAC,CAAC;IACH,MAAM,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,8BAA8B,CAAC,CAAC;IACpF,KAAK,MAAM,KAAK,IAAI,MAAM,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACnE,IAAI,QAA8B,CAAC;QACnC,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,EAAE;gBACzE,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS;gBAChC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC9E,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;gBACvF,aAAa,EAAE,KAAK,CAAC,aAAa;gBAClC,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,SAAS,EAAE,IAAI,CAAC,SAAS;aAC1B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,iBAAiB,IAAI,KAAK,CAAC,WAAW,KAAK,WAAW;gBAAE,MAAM,KAAK,CAAC;YACzF,MAAM,KAAK,CAAC;QACd,CAAC;QACD,MAAM,YAAY,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;QACvD,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;QACxF,CAAC;QACD,MAAM,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAC7D,IAAI,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE;YACtC,8BAA8B,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,8BAA8B,EAAE,YAAY,CAAC;SAC5F,CAAC,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,qBAAqB,CAC5B,QAAkC;IAElC,QAAQ,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAC1B,KAAK,kBAAkB;YACrB,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,QAAQ,CAAC,MAAM,IAAI,oCAAoC,EAAE,CAAC;QAC5G,KAAK,YAAY;YACf,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,QAAQ,CAAC,MAAM,IAAI,iCAAiC,EAAE,CAAC;QAC3G,KAAK,MAAM;YACT,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,QAAQ,CAAC,MAAM,IAAI,0CAA0C,EAAE,CAAC;QACrH,KAAK,sBAAsB;YACzB,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,QAAQ,CAAC,MAAM,IAAI,sCAAsC,EAAE,CAAC;QACjH,KAAK,QAAQ;YACX,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,KAAsF,EACtF,OAAyB,EACzB,MAAiC;IAEjC,MAAM,IAAI,GAAG;QACX,GAAG,OAAO;QACV,GAAG,MAAM;QACT,SAAS,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,WAAW,EAAE;KAC7D,CAAC;IACF,MAAM,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,uBAAuB,CAAC,QAA8B;IAC7D,OAAO,QAAQ,CAAC,0BAA0B,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
declare const lockSchema: z.ZodObject<{
|
|
3
|
+
schemaVersion: z.ZodLiteral<1>;
|
|
4
|
+
identityKey: z.ZodString;
|
|
5
|
+
pid: z.ZodNumber;
|
|
6
|
+
processStartMarker: z.ZodString;
|
|
7
|
+
nonce: z.ZodString;
|
|
8
|
+
acquiredAt: z.ZodISODateTime;
|
|
9
|
+
}, z.core.$strict>;
|
|
10
|
+
export type RuntimeLockRecord = z.infer<typeof lockSchema>;
|
|
11
|
+
export type RuntimeLockHandle = {
|
|
12
|
+
record: RuntimeLockRecord;
|
|
13
|
+
release(): Promise<void>;
|
|
14
|
+
};
|
|
15
|
+
export type RuntimeLockOptions = {
|
|
16
|
+
pid?: number | undefined;
|
|
17
|
+
now?: (() => Date) | undefined;
|
|
18
|
+
createNonce?: (() => string) | undefined;
|
|
19
|
+
readProcessStartMarker?: ((pid: number) => Promise<string | undefined>) | undefined;
|
|
20
|
+
};
|
|
21
|
+
export declare class RuntimeIdentityLock {
|
|
22
|
+
readonly path: string;
|
|
23
|
+
private readonly options;
|
|
24
|
+
constructor(path?: string, options?: RuntimeLockOptions);
|
|
25
|
+
acquire(identityKey: string): Promise<RuntimeLockHandle>;
|
|
26
|
+
private tryCreate;
|
|
27
|
+
private readExisting;
|
|
28
|
+
private recoverStaleLock;
|
|
29
|
+
private handle;
|
|
30
|
+
}
|
|
31
|
+
export declare function defaultRuntimeLockPath(env?: NodeJS.ProcessEnv): string;
|
|
32
|
+
export declare function readProcessStartMarker(pid: number): Promise<string | undefined>;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
3
|
+
import { chmod, mkdir, open, readFile, rename, rm } from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { defaultConfigPath } from "../config.js";
|
|
8
|
+
import { isNodeError } from "./atomicFile.js";
|
|
9
|
+
const execFileAsync = promisify(execFile);
|
|
10
|
+
const lockSchema = z.object({
|
|
11
|
+
schemaVersion: z.literal(1),
|
|
12
|
+
identityKey: z.string().min(1).max(500),
|
|
13
|
+
pid: z.number().int().positive(),
|
|
14
|
+
processStartMarker: z.string().min(1).max(500),
|
|
15
|
+
nonce: z.string().min(1),
|
|
16
|
+
acquiredAt: z.iso.datetime(),
|
|
17
|
+
}).strict();
|
|
18
|
+
export class RuntimeIdentityLock {
|
|
19
|
+
path;
|
|
20
|
+
options;
|
|
21
|
+
constructor(path = defaultRuntimeLockPath(), options = {}) {
|
|
22
|
+
this.path = path;
|
|
23
|
+
this.options = options;
|
|
24
|
+
}
|
|
25
|
+
async acquire(identityKey) {
|
|
26
|
+
await mkdir(path.dirname(this.path), { recursive: true, mode: 0o700 });
|
|
27
|
+
await chmod(path.dirname(this.path), 0o700);
|
|
28
|
+
const pid = this.options.pid ?? process.pid;
|
|
29
|
+
const markerReader = this.options.readProcessStartMarker ?? readProcessStartMarker;
|
|
30
|
+
const processStartMarker = await markerReader(pid);
|
|
31
|
+
if (processStartMarker === undefined) {
|
|
32
|
+
throw new Error("Cannot establish a PID-reuse-safe runtime identity.");
|
|
33
|
+
}
|
|
34
|
+
const record = lockSchema.parse({
|
|
35
|
+
schemaVersion: 1,
|
|
36
|
+
identityKey,
|
|
37
|
+
pid,
|
|
38
|
+
processStartMarker,
|
|
39
|
+
nonce: (this.options.createNonce ?? randomUUID)(),
|
|
40
|
+
acquiredAt: (this.options.now ?? (() => new Date()))().toISOString(),
|
|
41
|
+
});
|
|
42
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
43
|
+
if (await this.tryCreate(record))
|
|
44
|
+
return this.handle(record);
|
|
45
|
+
const existing = await this.readExisting();
|
|
46
|
+
if (existing !== undefined && await sameLiveProcess(existing, markerReader)) {
|
|
47
|
+
throw new Error("Another Conductor runtime already owns this paired identity and state directory.");
|
|
48
|
+
}
|
|
49
|
+
await this.recoverStaleLock(existing);
|
|
50
|
+
}
|
|
51
|
+
throw new Error("Could not acquire the Conductor runtime identity lock.");
|
|
52
|
+
}
|
|
53
|
+
async tryCreate(record) {
|
|
54
|
+
try {
|
|
55
|
+
const handle = await open(this.path, "wx", 0o600);
|
|
56
|
+
try {
|
|
57
|
+
await handle.writeFile(`${JSON.stringify(record, null, 2)}\n`, "utf8");
|
|
58
|
+
await handle.sync();
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
await handle.close();
|
|
62
|
+
}
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
if (isNodeError(error) && error.code === "EEXIST")
|
|
67
|
+
return false;
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async readExisting() {
|
|
72
|
+
try {
|
|
73
|
+
return lockSchema.parse(JSON.parse(await readFile(this.path, "utf8")));
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (isNodeError(error) && error.code === "ENOENT")
|
|
77
|
+
return undefined;
|
|
78
|
+
if (error instanceof SyntaxError || error instanceof z.ZodError)
|
|
79
|
+
return undefined;
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async recoverStaleLock(existing) {
|
|
84
|
+
try {
|
|
85
|
+
await rename(this.path, `${this.path}.stale-${existing?.nonce ?? randomUUID()}`);
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
if (!isNodeError(error) || error.code !== "ENOENT")
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
handle(record) {
|
|
93
|
+
return {
|
|
94
|
+
record,
|
|
95
|
+
release: async () => {
|
|
96
|
+
const existing = await this.readExisting();
|
|
97
|
+
if (existing?.nonce === record.nonce)
|
|
98
|
+
await rm(this.path, { force: true });
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
export function defaultRuntimeLockPath(env = process.env) {
|
|
104
|
+
return path.join(path.dirname(defaultConfigPath(env)), "runtime", "conductor.lock");
|
|
105
|
+
}
|
|
106
|
+
async function sameLiveProcess(record, markerReader) {
|
|
107
|
+
try {
|
|
108
|
+
process.kill(record.pid, 0);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
if (isNodeError(error) && error.code === "EPERM")
|
|
112
|
+
return true;
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
return await markerReader(record.pid) === record.processStartMarker;
|
|
116
|
+
}
|
|
117
|
+
export async function readProcessStartMarker(pid) {
|
|
118
|
+
if (process.platform === "linux") {
|
|
119
|
+
try {
|
|
120
|
+
const stat = await readFile(`/proc/${String(pid)}/stat`, "utf8");
|
|
121
|
+
return stat.trim().split(/\s+/u)[21];
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const command = process.platform === "win32" ? "powershell.exe" : "ps";
|
|
128
|
+
const args = process.platform === "win32"
|
|
129
|
+
? ["-NoProfile", "-Command", `(Get-Process -Id ${String(pid)}).StartTime.ToUniversalTime().Ticks`]
|
|
130
|
+
: ["-o", "lstart=", "-p", String(pid)];
|
|
131
|
+
try {
|
|
132
|
+
const { stdout } = await execFileAsync(command, args, { timeout: 2_000 });
|
|
133
|
+
const marker = stdout.trim();
|
|
134
|
+
return marker.length === 0 ? undefined : marker;
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=runtimeLock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtimeLock.js","sourceRoot":"","sources":["../../src/runtime/runtimeLock.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { DaemonOnceResult, RunDaemonOnceInput } from "../daemon.js";
|
|
2
|
+
import type { RuntimeIdentityLock } from "./runtimeLock.js";
|
|
2
3
|
export type RuntimeServiceState = "stopped" | "starting" | "running" | "stopping" | "failed";
|
|
3
4
|
export type RuntimeServiceStatus = {
|
|
4
5
|
state: RuntimeServiceState;
|
|
@@ -9,6 +10,7 @@ export type RuntimeServiceStatus = {
|
|
|
9
10
|
};
|
|
10
11
|
export declare class HeadlessRuntimeService {
|
|
11
12
|
private readonly input;
|
|
13
|
+
private readonly runtimeLock?;
|
|
12
14
|
private state;
|
|
13
15
|
private startedAt;
|
|
14
16
|
private stoppedAt;
|
|
@@ -16,7 +18,8 @@ export declare class HeadlessRuntimeService {
|
|
|
16
18
|
private lastErrorMessage;
|
|
17
19
|
private controller;
|
|
18
20
|
private runPromise;
|
|
19
|
-
|
|
21
|
+
private lockHandle;
|
|
22
|
+
constructor(input: Omit<RunDaemonOnceInput, "signal">, runtimeLock?: RuntimeIdentityLock | undefined);
|
|
20
23
|
status(): RuntimeServiceStatus;
|
|
21
24
|
runOnce(): Promise<DaemonOnceResult>;
|
|
22
25
|
start(): Promise<RuntimeServiceStatus>;
|
|
@@ -24,4 +27,6 @@ export declare class HeadlessRuntimeService {
|
|
|
24
27
|
restart(): Promise<RuntimeServiceStatus>;
|
|
25
28
|
waitUntilStopped(): Promise<RuntimeServiceStatus>;
|
|
26
29
|
private runUntilStopped;
|
|
30
|
+
private acquireOwnership;
|
|
31
|
+
private releaseOwnership;
|
|
27
32
|
}
|