taskflow-core 0.2.0 → 0.2.1
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/README.md +247 -862
- package/dist/agents.d.ts +12 -0
- package/dist/agents.d.ts.map +1 -1
- package/dist/agents.js +29 -1
- package/dist/agents.js.map +1 -1
- package/dist/cwd-bridge.d.ts +61 -0
- package/dist/cwd-bridge.d.ts.map +1 -0
- package/dist/cwd-bridge.js +136 -0
- package/dist/cwd-bridge.js.map +1 -0
- package/dist/detached-runner.js +31 -5
- package/dist/detached-runner.js.map +1 -1
- package/dist/exec/driver.d.ts +1 -0
- package/dist/exec/driver.d.ts.map +1 -1
- package/dist/exec/driver.js +15 -2
- package/dist/exec/driver.js.map +1 -1
- package/dist/exec/step-kinds.d.ts.map +1 -1
- package/dist/exec/step-kinds.js +28 -3
- package/dist/exec/step-kinds.js.map +1 -1
- package/dist/exec/step.d.ts +1 -0
- package/dist/exec/step.d.ts.map +1 -1
- package/dist/exec/step.js +18 -0
- package/dist/exec/step.js.map +1 -1
- package/dist/flowir/compile.d.ts.map +1 -1
- package/dist/flowir/compile.js +13 -0
- package/dist/flowir/compile.js.map +1 -1
- package/dist/host/runner-types.d.ts +16 -0
- package/dist/host/runner-types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/interpolate.d.ts +4 -0
- package/dist/interpolate.d.ts.map +1 -1
- package/dist/interpolate.js +14 -0
- package/dist/interpolate.js.map +1 -1
- package/dist/resources/authority.d.ts +35 -0
- package/dist/resources/authority.d.ts.map +1 -0
- package/dist/resources/authority.js +67 -0
- package/dist/resources/authority.js.map +1 -0
- package/dist/resources/backend.d.ts +302 -0
- package/dist/resources/backend.d.ts.map +1 -0
- package/dist/resources/backend.js +16 -0
- package/dist/resources/backend.js.map +1 -0
- package/dist/resources/baseline.d.ts +116 -0
- package/dist/resources/baseline.d.ts.map +1 -0
- package/dist/resources/baseline.js +447 -0
- package/dist/resources/baseline.js.map +1 -0
- package/dist/resources/canonical-json.d.ts +7 -0
- package/dist/resources/canonical-json.d.ts.map +1 -0
- package/dist/resources/canonical-json.js +75 -0
- package/dist/resources/canonical-json.js.map +1 -0
- package/dist/resources/errors.d.ts +23 -0
- package/dist/resources/errors.d.ts.map +1 -0
- package/dist/resources/errors.js +89 -0
- package/dist/resources/errors.js.map +1 -0
- package/dist/resources/execution.d.ts +90 -0
- package/dist/resources/execution.d.ts.map +1 -0
- package/dist/resources/execution.js +581 -0
- package/dist/resources/execution.js.map +1 -0
- package/dist/resources/index.d.ts +15 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +15 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/journal.d.ts +138 -0
- package/dist/resources/journal.d.ts.map +1 -0
- package/dist/resources/journal.js +438 -0
- package/dist/resources/journal.js.map +1 -0
- package/dist/resources/leases.d.ts +51 -0
- package/dist/resources/leases.d.ts.map +1 -0
- package/dist/resources/leases.js +354 -0
- package/dist/resources/leases.js.map +1 -0
- package/dist/resources/permits.d.ts +52 -0
- package/dist/resources/permits.d.ts.map +1 -0
- package/dist/resources/permits.js +240 -0
- package/dist/resources/permits.js.map +1 -0
- package/dist/resources/persistence.d.ts +63 -0
- package/dist/resources/persistence.d.ts.map +1 -0
- package/dist/resources/persistence.js +522 -0
- package/dist/resources/persistence.js.map +1 -0
- package/dist/resources/registry.d.ts +56 -0
- package/dist/resources/registry.d.ts.map +1 -0
- package/dist/resources/registry.js +139 -0
- package/dist/resources/registry.js.map +1 -0
- package/dist/resources/resolve.d.ts +49 -0
- package/dist/resources/resolve.d.ts.map +1 -0
- package/dist/resources/resolve.js +309 -0
- package/dist/resources/resolve.js.map +1 -0
- package/dist/resources/sandbox.d.ts +72 -0
- package/dist/resources/sandbox.d.ts.map +1 -0
- package/dist/resources/sandbox.js +952 -0
- package/dist/resources/sandbox.js.map +1 -0
- package/dist/resources/schema.d.ts +195 -0
- package/dist/resources/schema.d.ts.map +1 -0
- package/dist/resources/schema.js +231 -0
- package/dist/resources/schema.js.map +1 -0
- package/dist/resources/types.d.ts +36 -0
- package/dist/resources/types.d.ts.map +1 -0
- package/dist/resources/types.js +75 -0
- package/dist/resources/types.js.map +1 -0
- package/dist/runner-core.d.ts +29 -0
- package/dist/runner-core.d.ts.map +1 -1
- package/dist/runner-core.js +311 -36
- package/dist/runner-core.js.map +1 -1
- package/dist/runtime/phases/script.d.ts.map +1 -1
- package/dist/runtime/phases/script.js +47 -9
- package/dist/runtime/phases/script.js.map +1 -1
- package/dist/runtime.d.ts +39 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +542 -50
- package/dist/runtime.js.map +1 -1
- package/dist/schema.d.ts +68 -5
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +163 -22
- package/dist/schema.js.map +1 -1
- package/dist/store.d.ts +7 -0
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js.map +1 -1
- package/dist/trace.d.ts +3 -0
- package/dist/trace.d.ts.map +1 -1
- package/dist/trace.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
import * as crypto from "node:crypto";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { execFileSync } from "node:child_process";
|
|
5
|
+
/** Exact, platform-native process-birth identity when the platform exposes one.
|
|
6
|
+
* Never return an uptime estimate or a lower-precision timestamp: incomparable
|
|
7
|
+
* identities could falsely reclaim a live owner's lock. */
|
|
8
|
+
export function readProcessBirthToken(pid) {
|
|
9
|
+
if (!Number.isSafeInteger(pid) || pid < 1)
|
|
10
|
+
return undefined;
|
|
11
|
+
try {
|
|
12
|
+
if (process.platform === "linux") {
|
|
13
|
+
const bootId = fs.readFileSync("/proc/sys/kernel/random/boot_id", "utf8").trim();
|
|
14
|
+
const stat = fs.readFileSync(`/proc/${pid}/stat`, "utf8").trim();
|
|
15
|
+
const commandEnd = stat.lastIndexOf(")");
|
|
16
|
+
if (!bootId || commandEnd < 0)
|
|
17
|
+
return undefined;
|
|
18
|
+
// Fields after the command start at proc(5) field 3; starttime is field 22.
|
|
19
|
+
const startTicks = stat.slice(commandEnd + 1).trim().split(/\s+/)[19];
|
|
20
|
+
if (!/^\d+$/.test(startTicks ?? ""))
|
|
21
|
+
return undefined;
|
|
22
|
+
return `linux:${bootId}:${startTicks}`;
|
|
23
|
+
}
|
|
24
|
+
if (process.platform === "win32") {
|
|
25
|
+
const output = execFileSync("powershell.exe", [
|
|
26
|
+
"-NoLogo",
|
|
27
|
+
"-NoProfile",
|
|
28
|
+
"-NonInteractive",
|
|
29
|
+
"-Command",
|
|
30
|
+
`(Get-Process -Id ${pid} -ErrorAction Stop).StartTime.ToUniversalTime().ToFileTimeUtc()`,
|
|
31
|
+
], {
|
|
32
|
+
encoding: "utf8",
|
|
33
|
+
timeout: 1_000,
|
|
34
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
35
|
+
}).trim();
|
|
36
|
+
return /^\d+$/.test(output) ? `windows:filetime:${output}` : undefined;
|
|
37
|
+
}
|
|
38
|
+
// macOS `ps lstart` is only second precision and can alias PID reuse. Until
|
|
39
|
+
// a native high-resolution token is available, liveness is fail-closed.
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const NATIVE_PROCESS_BIRTH_TOKEN = readProcessBirthToken(process.pid);
|
|
47
|
+
const PROCESS_BIRTH_TOKEN = NATIVE_PROCESS_BIRTH_TOKEN ?? `opaque:${crypto.randomUUID()}`;
|
|
48
|
+
const PROCESS_BIRTH_TOKEN_KIND = NATIVE_PROCESS_BIRTH_TOKEN === undefined ? "opaque" : "native";
|
|
49
|
+
export class CoordinatorTimeoutError extends Error {
|
|
50
|
+
code = "TFWS_LEASE_TIMEOUT";
|
|
51
|
+
constructor(message) {
|
|
52
|
+
super(message);
|
|
53
|
+
this.name = "CoordinatorTimeoutError";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export class CoordinatorAbortError extends Error {
|
|
57
|
+
code = "ABORT_ERR";
|
|
58
|
+
constructor(message = "Coordinator operation aborted") {
|
|
59
|
+
super(message);
|
|
60
|
+
this.name = "AbortError";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export function defaultProcessIdentity() {
|
|
64
|
+
return { pid: process.pid, birthToken: PROCESS_BIRTH_TOKEN, birthTokenKind: PROCESS_BIRTH_TOKEN_KIND };
|
|
65
|
+
}
|
|
66
|
+
export function defaultProcessInspector(pid) {
|
|
67
|
+
if (pid === process.pid) {
|
|
68
|
+
return { alive: true, birthToken: PROCESS_BIRTH_TOKEN, birthTokenKind: PROCESS_BIRTH_TOKEN_KIND };
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
process.kill(pid, 0);
|
|
72
|
+
const birthToken = readProcessBirthToken(pid);
|
|
73
|
+
return birthToken === undefined
|
|
74
|
+
? { alive: true }
|
|
75
|
+
: { alive: true, birthToken, birthTokenKind: "native" };
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
const code = error.code;
|
|
79
|
+
if (code !== "EPERM")
|
|
80
|
+
return { alive: false };
|
|
81
|
+
const birthToken = readProcessBirthToken(pid);
|
|
82
|
+
return birthToken === undefined
|
|
83
|
+
? { alive: true }
|
|
84
|
+
: { alive: true, birthToken, birthTokenKind: "native" };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export function namespaceToken(namespace) {
|
|
88
|
+
return crypto.createHash("sha256").update(namespace).digest("hex").slice(0, 24);
|
|
89
|
+
}
|
|
90
|
+
export function ensureDirectory(directory) {
|
|
91
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
92
|
+
}
|
|
93
|
+
export function fsyncDirectory(directory) {
|
|
94
|
+
try {
|
|
95
|
+
const fd = fs.openSync(directory, "r");
|
|
96
|
+
try {
|
|
97
|
+
fs.fsyncSync(fd);
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
fs.closeSync(fd);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// Some filesystems/platforms do not permit fsync on directories. The WAL or
|
|
105
|
+
// data file itself is still fsynced; directory sync remains best-effort.
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
export function writeJsonAtomicDurable(filePath, value) {
|
|
109
|
+
ensureDirectory(path.dirname(filePath));
|
|
110
|
+
const temp = `${filePath}.tmp.${process.pid}.${crypto.randomBytes(6).toString("hex")}`;
|
|
111
|
+
const fd = fs.openSync(temp, "wx", 0o600);
|
|
112
|
+
try {
|
|
113
|
+
fs.writeFileSync(fd, JSON.stringify(value));
|
|
114
|
+
fs.fsyncSync(fd);
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
fs.closeSync(fd);
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
fs.renameSync(temp, filePath);
|
|
121
|
+
fsyncDirectory(path.dirname(filePath));
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
try {
|
|
125
|
+
fs.unlinkSync(temp);
|
|
126
|
+
}
|
|
127
|
+
catch { /* best effort */ }
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
export function readJsonFile(filePath, fallback) {
|
|
132
|
+
try {
|
|
133
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
if (error.code === "ENOENT")
|
|
137
|
+
return fallback;
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
export function appendJsonLinesDurable(filePath, records) {
|
|
142
|
+
if (records.length === 0)
|
|
143
|
+
return;
|
|
144
|
+
ensureDirectory(path.dirname(filePath));
|
|
145
|
+
const existed = fs.existsSync(filePath);
|
|
146
|
+
// A crash can leave a partial final JSON record. Because callers serialize WAL
|
|
147
|
+
// access with PersistentFileMutex, it is safe to truncate only that unterminated
|
|
148
|
+
// tail before appending the next durable group.
|
|
149
|
+
if (existed) {
|
|
150
|
+
const raw = fs.readFileSync(filePath);
|
|
151
|
+
if (raw.length > 0 && raw[raw.length - 1] !== 0x0a) {
|
|
152
|
+
const lastNewline = raw.lastIndexOf(0x0a);
|
|
153
|
+
const repairFd = fs.openSync(filePath, "r+");
|
|
154
|
+
try {
|
|
155
|
+
fs.ftruncateSync(repairFd, lastNewline + 1);
|
|
156
|
+
fs.fsyncSync(repairFd);
|
|
157
|
+
}
|
|
158
|
+
finally {
|
|
159
|
+
fs.closeSync(repairFd);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const fd = fs.openSync(filePath, "a", 0o600);
|
|
164
|
+
try {
|
|
165
|
+
for (const record of records) {
|
|
166
|
+
const data = Buffer.from(`${JSON.stringify(record)}\n`);
|
|
167
|
+
let offset = 0;
|
|
168
|
+
while (offset < data.length)
|
|
169
|
+
offset += fs.writeSync(fd, data, offset, data.length - offset);
|
|
170
|
+
}
|
|
171
|
+
fs.fsyncSync(fd);
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
fs.closeSync(fd);
|
|
175
|
+
}
|
|
176
|
+
if (!existed)
|
|
177
|
+
fsyncDirectory(path.dirname(filePath));
|
|
178
|
+
}
|
|
179
|
+
export function readJsonLines(filePath) {
|
|
180
|
+
let raw;
|
|
181
|
+
try {
|
|
182
|
+
raw = fs.readFileSync(filePath, "utf8");
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
if (error.code === "ENOENT")
|
|
186
|
+
return [];
|
|
187
|
+
throw error;
|
|
188
|
+
}
|
|
189
|
+
const lines = raw.split("\n");
|
|
190
|
+
const hasTerminatingNewline = raw.endsWith("\n");
|
|
191
|
+
const records = [];
|
|
192
|
+
for (let index = 0; index < lines.length; index++) {
|
|
193
|
+
const line = lines[index];
|
|
194
|
+
if (!line)
|
|
195
|
+
continue;
|
|
196
|
+
try {
|
|
197
|
+
records.push(JSON.parse(line));
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
if (!hasTerminatingNewline && index === lines.length - 1)
|
|
201
|
+
break;
|
|
202
|
+
throw new Error(`Corrupt durable JSONL record ${index + 1} in ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return records;
|
|
206
|
+
}
|
|
207
|
+
function ownerIsStale(record, identity, inspect) {
|
|
208
|
+
if (record.pid === identity.pid) {
|
|
209
|
+
// Opaque tokens identify one JS module/isolate, not an OS process. Worker
|
|
210
|
+
// threads share a PID but evaluate modules independently, so comparing two
|
|
211
|
+
// opaque UUIDs would let one live worker reclaim another's ticket. Only native
|
|
212
|
+
// kernel birth tokens are comparable; otherwise liveness fails closed.
|
|
213
|
+
return record.birthTokenKind === "native" && identity.birthTokenKind === "native" &&
|
|
214
|
+
record.birthToken !== identity.birthToken;
|
|
215
|
+
}
|
|
216
|
+
const observed = inspect(record.pid);
|
|
217
|
+
if (!observed.alive)
|
|
218
|
+
return true;
|
|
219
|
+
return record.birthTokenKind === "native" && observed.birthTokenKind === "native" &&
|
|
220
|
+
observed.birthToken !== undefined && observed.birthToken !== record.birthToken;
|
|
221
|
+
}
|
|
222
|
+
// A mutex instance can disappear after returning a completed critical-section
|
|
223
|
+
// result. Keep deferred exact-ticket cleanup shared by duplicate module instances
|
|
224
|
+
// in this JS realm, keyed by the immutable ticket path. The fsynced `done` state
|
|
225
|
+
// on the ticket itself carries the same fact across worker isolates/processes.
|
|
226
|
+
const persistenceGlobal = globalThis;
|
|
227
|
+
const PROCESS_PENDING_TICKET_RELEASES = persistenceGlobal.__taskflowPendingMutexTicketReleasesV1 ??= new Map();
|
|
228
|
+
function delay(ms, signal) {
|
|
229
|
+
if (signal?.aborted)
|
|
230
|
+
return Promise.reject(new CoordinatorAbortError());
|
|
231
|
+
return new Promise((resolve, reject) => {
|
|
232
|
+
const finish = () => signal?.removeEventListener("abort", onAbort);
|
|
233
|
+
const timer = setTimeout(() => {
|
|
234
|
+
finish();
|
|
235
|
+
resolve();
|
|
236
|
+
}, ms);
|
|
237
|
+
const onAbort = () => {
|
|
238
|
+
clearTimeout(timer);
|
|
239
|
+
finish();
|
|
240
|
+
reject(new CoordinatorAbortError());
|
|
241
|
+
};
|
|
242
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
export class PersistentFileMutex {
|
|
246
|
+
lockPath;
|
|
247
|
+
identity;
|
|
248
|
+
inspectProcess;
|
|
249
|
+
pollMs;
|
|
250
|
+
corruptLockStaleMs;
|
|
251
|
+
now;
|
|
252
|
+
constructor(lockPath, options = {}) {
|
|
253
|
+
this.lockPath = lockPath;
|
|
254
|
+
this.identity = options.processIdentity ?? defaultProcessIdentity();
|
|
255
|
+
this.inspectProcess = options.inspectProcess ?? defaultProcessInspector;
|
|
256
|
+
this.pollMs = options.pollMs ?? 20;
|
|
257
|
+
this.corruptLockStaleMs = options.corruptLockStaleMs ?? 30_000;
|
|
258
|
+
this.now = options.now ?? Date.now;
|
|
259
|
+
}
|
|
260
|
+
#queueDirectory() {
|
|
261
|
+
return `${this.lockPath}.queue`;
|
|
262
|
+
}
|
|
263
|
+
#removeTicketBestEffort(ticketPath, queueDirectory) {
|
|
264
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
265
|
+
try {
|
|
266
|
+
fs.unlinkSync(ticketPath);
|
|
267
|
+
fsyncDirectory(queueDirectory);
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
if (error.code === "ENOENT")
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
#markQueueRecordDone(recordPath, expected) {
|
|
278
|
+
const noFollow = typeof fs.constants.O_NOFOLLOW === "number" ? fs.constants.O_NOFOLLOW : 0;
|
|
279
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
280
|
+
let fd;
|
|
281
|
+
try {
|
|
282
|
+
fd = fs.openSync(recordPath, fs.constants.O_RDWR | noFollow);
|
|
283
|
+
const raw = fs.readFileSync(fd, "utf8");
|
|
284
|
+
const current = JSON.parse(raw);
|
|
285
|
+
if (current.kind !== expected.kind || current.token !== expected.token ||
|
|
286
|
+
(current.kind === "ticket" && expected.kind === "ticket" && current.ticket !== expected.ticket) ||
|
|
287
|
+
current.pid !== expected.pid ||
|
|
288
|
+
current.birthToken !== expected.birthToken || current.birthTokenKind !== expected.birthTokenKind) {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
if (current.state === "done")
|
|
292
|
+
return true;
|
|
293
|
+
if (current.state !== "held")
|
|
294
|
+
return false;
|
|
295
|
+
const terminal = Buffer.from(JSON.stringify({ ...current, state: "done" }));
|
|
296
|
+
if (terminal.byteLength !== Buffer.byteLength(raw))
|
|
297
|
+
return false;
|
|
298
|
+
let offset = 0;
|
|
299
|
+
while (offset < terminal.byteLength) {
|
|
300
|
+
offset += fs.writeSync(fd, terminal, offset, terminal.byteLength - offset, offset);
|
|
301
|
+
}
|
|
302
|
+
fs.fsyncSync(fd);
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
if (error.code === "ENOENT")
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
finally {
|
|
310
|
+
if (fd !== undefined)
|
|
311
|
+
fs.closeSync(fd);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
#drainPendingTicketReleases() {
|
|
317
|
+
const ownQueueDirectory = this.#queueDirectory();
|
|
318
|
+
for (const [ticketPath, queueDirectory] of PROCESS_PENDING_TICKET_RELEASES) {
|
|
319
|
+
if (queueDirectory !== ownQueueDirectory)
|
|
320
|
+
continue;
|
|
321
|
+
if (this.#removeTicketBestEffort(ticketPath, queueDirectory)) {
|
|
322
|
+
PROCESS_PENDING_TICKET_RELEASES.delete(ticketPath);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if ([...PROCESS_PENDING_TICKET_RELEASES.values()].some((queueDirectory) => queueDirectory === ownQueueDirectory)) {
|
|
326
|
+
throw new Error("TFWS_CONTROL_PLANE_CLEANUP: a prior mutex ticket could not be released");
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
#readQueueRecord(filePath) {
|
|
330
|
+
try {
|
|
331
|
+
const record = readJsonFile(filePath, undefined);
|
|
332
|
+
if (!record || (record.kind !== "choosing" && record.kind !== "ticket") ||
|
|
333
|
+
typeof record.token !== "string" || !Number.isSafeInteger(record.pid) ||
|
|
334
|
+
typeof record.birthToken !== "string" || record.birthToken.length === 0 ||
|
|
335
|
+
(record.birthTokenKind !== "native" && record.birthTokenKind !== "opaque") ||
|
|
336
|
+
(record.state !== "held" && record.state !== "done")) {
|
|
337
|
+
throw new Error("invalid mutex queue record");
|
|
338
|
+
}
|
|
339
|
+
if (record.kind === "ticket" &&
|
|
340
|
+
(!Number.isSafeInteger(record.ticket) || record.ticket < 1)) {
|
|
341
|
+
throw new Error("invalid mutex ticket");
|
|
342
|
+
}
|
|
343
|
+
return record;
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
if (error.code === "ENOENT")
|
|
347
|
+
return undefined;
|
|
348
|
+
try {
|
|
349
|
+
const stat = fs.statSync(filePath);
|
|
350
|
+
if (this.now() - stat.mtimeMs >= this.corruptLockStaleMs) {
|
|
351
|
+
// Queue filenames contain a never-reused UUID. Removing this exact
|
|
352
|
+
// corrupt path cannot delete a newer owner's ticket (unlike renaming
|
|
353
|
+
// one shared lockPath after a stale read).
|
|
354
|
+
fs.unlinkSync(filePath);
|
|
355
|
+
return undefined;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
catch (statError) {
|
|
359
|
+
if (statError.code === "ENOENT")
|
|
360
|
+
return undefined;
|
|
361
|
+
}
|
|
362
|
+
throw error;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
#queueSnapshot(queueDirectory) {
|
|
366
|
+
const choosing = [];
|
|
367
|
+
const tickets = [];
|
|
368
|
+
let names;
|
|
369
|
+
try {
|
|
370
|
+
names = fs.readdirSync(queueDirectory);
|
|
371
|
+
}
|
|
372
|
+
catch (error) {
|
|
373
|
+
if (error.code === "ENOENT")
|
|
374
|
+
return { choosing, tickets };
|
|
375
|
+
throw error;
|
|
376
|
+
}
|
|
377
|
+
for (const name of names) {
|
|
378
|
+
const choosingName = /^choosing-([0-9a-f-]+)\.json$/.exec(name);
|
|
379
|
+
const ticketName = /^ticket-([0-9a-f-]+)\.json$/.exec(name);
|
|
380
|
+
if (!choosingName && !ticketName)
|
|
381
|
+
continue;
|
|
382
|
+
const filePath = path.join(queueDirectory, name);
|
|
383
|
+
const record = this.#readQueueRecord(filePath);
|
|
384
|
+
if (!record)
|
|
385
|
+
continue;
|
|
386
|
+
if (record.token !== (choosingName?.[1] ?? ticketName?.[1])) {
|
|
387
|
+
throw new Error("mutex queue token does not match its immutable filename");
|
|
388
|
+
}
|
|
389
|
+
if (record.state === "done") {
|
|
390
|
+
// The owner durably ended its critical section before cleanup failed.
|
|
391
|
+
// Any process/worker may remove this exact immutable terminal ticket;
|
|
392
|
+
// no birth-token inference is involved.
|
|
393
|
+
try {
|
|
394
|
+
fs.unlinkSync(filePath);
|
|
395
|
+
}
|
|
396
|
+
catch (error) {
|
|
397
|
+
if (error.code !== "ENOENT")
|
|
398
|
+
throw error;
|
|
399
|
+
}
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
if (ownerIsStale(record, this.identity, this.inspectProcess)) {
|
|
403
|
+
// Every contender owns a unique immutable file, so stale recovery is
|
|
404
|
+
// exact-path deletion with no shared-name ABA window.
|
|
405
|
+
try {
|
|
406
|
+
fs.unlinkSync(filePath);
|
|
407
|
+
}
|
|
408
|
+
catch (error) {
|
|
409
|
+
if (error.code !== "ENOENT")
|
|
410
|
+
throw error;
|
|
411
|
+
}
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
if (record.kind === "choosing" && choosingName)
|
|
415
|
+
choosing.push({ path: filePath, record });
|
|
416
|
+
if (record.kind === "ticket" && ticketName)
|
|
417
|
+
tickets.push({ path: filePath, record });
|
|
418
|
+
}
|
|
419
|
+
return { choosing, tickets };
|
|
420
|
+
}
|
|
421
|
+
async acquire(options = {}) {
|
|
422
|
+
// A completed critical section must keep its result even if immutable-ticket
|
|
423
|
+
// cleanup was temporarily unavailable. This exact mutex fails closed on its
|
|
424
|
+
// next acquisition until the deferred cleanup succeeds.
|
|
425
|
+
this.#drainPendingTicketReleases();
|
|
426
|
+
const timeoutMs = options.timeoutMs ?? 10_000;
|
|
427
|
+
const deadline = this.now() + timeoutMs;
|
|
428
|
+
const queueDirectory = this.#queueDirectory();
|
|
429
|
+
ensureDirectory(queueDirectory);
|
|
430
|
+
const token = crypto.randomUUID();
|
|
431
|
+
const choosingPath = path.join(queueDirectory, `choosing-${token}.json`);
|
|
432
|
+
const ticketPath = path.join(queueDirectory, `ticket-${token}.json`);
|
|
433
|
+
const choosing = {
|
|
434
|
+
kind: "choosing",
|
|
435
|
+
...this.identity,
|
|
436
|
+
token,
|
|
437
|
+
createdAt: this.now(),
|
|
438
|
+
state: "held",
|
|
439
|
+
};
|
|
440
|
+
let publishedTicket = false;
|
|
441
|
+
let own;
|
|
442
|
+
try {
|
|
443
|
+
writeJsonAtomicDurable(choosingPath, choosing);
|
|
444
|
+
if (options.signal?.aborted)
|
|
445
|
+
throw new CoordinatorAbortError();
|
|
446
|
+
const initial = this.#queueSnapshot(queueDirectory);
|
|
447
|
+
const maxTicket = initial.tickets.reduce((max, item) => Math.max(max, item.record.ticket), 0);
|
|
448
|
+
if (maxTicket >= Number.MAX_SAFE_INTEGER)
|
|
449
|
+
throw new Error("mutex ticket space exhausted");
|
|
450
|
+
const ticketRecord = {
|
|
451
|
+
kind: "ticket",
|
|
452
|
+
...this.identity,
|
|
453
|
+
token,
|
|
454
|
+
ticket: maxTicket + 1,
|
|
455
|
+
createdAt: this.now(),
|
|
456
|
+
state: "held",
|
|
457
|
+
};
|
|
458
|
+
own = ticketRecord;
|
|
459
|
+
writeJsonAtomicDurable(ticketPath, ticketRecord);
|
|
460
|
+
publishedTicket = true;
|
|
461
|
+
fs.unlinkSync(choosingPath);
|
|
462
|
+
fsyncDirectory(queueDirectory);
|
|
463
|
+
while (true) {
|
|
464
|
+
if (options.signal?.aborted)
|
|
465
|
+
throw new CoordinatorAbortError();
|
|
466
|
+
const snapshot = this.#queueSnapshot(queueDirectory);
|
|
467
|
+
const otherChoosing = snapshot.choosing.some((item) => item.record.token !== token);
|
|
468
|
+
const earlier = snapshot.tickets.some((item) => item.record.token !== token &&
|
|
469
|
+
(item.record.ticket < ticketRecord.ticket ||
|
|
470
|
+
(item.record.ticket === ticketRecord.ticket && item.record.token < token)));
|
|
471
|
+
if (!otherChoosing && !earlier) {
|
|
472
|
+
let released = false;
|
|
473
|
+
return () => {
|
|
474
|
+
if (released)
|
|
475
|
+
return;
|
|
476
|
+
const terminal = this.#markQueueRecordDone(ticketPath, ticketRecord);
|
|
477
|
+
if (this.#removeTicketBestEffort(ticketPath, queueDirectory)) {
|
|
478
|
+
released = true;
|
|
479
|
+
PROCESS_PENDING_TICKET_RELEASES.delete(ticketPath);
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
PROCESS_PENDING_TICKET_RELEASES.set(ticketPath, queueDirectory);
|
|
483
|
+
console.warn(`[taskflow] mutex ticket cleanup deferred for ${path.basename(ticketPath)}` +
|
|
484
|
+
(terminal ? " (critical section durably released)" : " (release marker unavailable; fail-closed)"));
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
if (this.now() >= deadline) {
|
|
488
|
+
throw new CoordinatorTimeoutError(`Coordinator lock timeout after ${timeoutMs}ms`);
|
|
489
|
+
}
|
|
490
|
+
await delay(Math.min(this.pollMs, Math.max(1, deadline - this.now())), options.signal);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
catch (error) {
|
|
494
|
+
const candidates = [
|
|
495
|
+
[choosingPath, choosing],
|
|
496
|
+
...(publishedTicket && own ? [[ticketPath, own]] : []),
|
|
497
|
+
];
|
|
498
|
+
for (const [candidate, record] of candidates) {
|
|
499
|
+
// A cancelled/timed-out contender is no longer live. Persist that fact in
|
|
500
|
+
// the immutable queue record before unlink so permission failures cannot
|
|
501
|
+
// leave a same-process ticket that blocks the queue forever.
|
|
502
|
+
this.#markQueueRecordDone(candidate, record);
|
|
503
|
+
this.#removeTicketBestEffort(candidate, queueDirectory);
|
|
504
|
+
}
|
|
505
|
+
fsyncDirectory(queueDirectory);
|
|
506
|
+
throw error;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
async runExclusive(fn, options = {}) {
|
|
510
|
+
const release = await this.acquire(options);
|
|
511
|
+
try {
|
|
512
|
+
return await fn();
|
|
513
|
+
}
|
|
514
|
+
finally {
|
|
515
|
+
release();
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
export function isPersistedOwnerStale(record, identity, inspect) {
|
|
520
|
+
return ownerIsStale(record, identity, inspect);
|
|
521
|
+
}
|
|
522
|
+
//# sourceMappingURL=persistence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence.js","sourceRoot":"","sources":["../../src/resources/persistence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type InvocationAuthority } from "./authority.ts";
|
|
2
|
+
import { type WorkspacePolicyError } from "./errors.ts";
|
|
3
|
+
import { type ResourceVersion, type WorkspaceAccess } from "./schema.ts";
|
|
4
|
+
declare const ROOT_GRANT: unique symbol;
|
|
5
|
+
export declare const ROOT_ENFORCEMENT_MODES: readonly ["native-single-root", "native-multi-root", "resolve-only"];
|
|
6
|
+
export type RootEnforcement = (typeof ROOT_ENFORCEMENT_MODES)[number];
|
|
7
|
+
export interface RootGrant {
|
|
8
|
+
readonly [ROOT_GRANT]: true;
|
|
9
|
+
readonly grantId: string;
|
|
10
|
+
readonly bindingId: string;
|
|
11
|
+
readonly resourceDomainId: string;
|
|
12
|
+
/** Canonical physical path; runtime-only and never persisted in portable records. */
|
|
13
|
+
readonly physicalRoot: string;
|
|
14
|
+
readonly maxAccess: WorkspaceAccess;
|
|
15
|
+
readonly version?: Readonly<ResourceVersion>;
|
|
16
|
+
readonly allowedPrincipals: ReadonlySet<string>;
|
|
17
|
+
readonly enforcement: RootEnforcement;
|
|
18
|
+
}
|
|
19
|
+
export interface HostRootGrantInput {
|
|
20
|
+
grantId: string;
|
|
21
|
+
bindingId: string;
|
|
22
|
+
resourceDomainId: string;
|
|
23
|
+
physicalRoot: string;
|
|
24
|
+
maxAccess: WorkspaceAccess;
|
|
25
|
+
version?: ResourceVersion;
|
|
26
|
+
allowedPrincipals: Iterable<string>;
|
|
27
|
+
enforcement: RootEnforcement;
|
|
28
|
+
}
|
|
29
|
+
export interface RootRegistry {
|
|
30
|
+
readonly registryId: string;
|
|
31
|
+
authorize(grantId: string, principal: InvocationAuthority, requested: WorkspaceAccess): RootGrant | WorkspacePolicyError;
|
|
32
|
+
}
|
|
33
|
+
export interface RootRegistryInput {
|
|
34
|
+
registryId: string;
|
|
35
|
+
grants: readonly RootGrant[];
|
|
36
|
+
}
|
|
37
|
+
/** Invalid trusted host policy; detected before an invocation can start. */
|
|
38
|
+
export declare class RootRegistryConfigurationError extends Error {
|
|
39
|
+
constructor(message: string);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Host-only RootGrant constructor.
|
|
43
|
+
*
|
|
44
|
+
* The private symbol plus WeakSet identity make grants non-forgeable by JSON,
|
|
45
|
+
* object spread, structural casts, or structured cloning. Trusted delivery
|
|
46
|
+
* code calls this while loading its local root policy.
|
|
47
|
+
*/
|
|
48
|
+
export declare function createHostRootGrant(input: HostRootGrantInput): RootGrant;
|
|
49
|
+
export declare function isRootGrant(value: unknown): value is RootGrant;
|
|
50
|
+
/**
|
|
51
|
+
* Build a registry and reject alias configurations that could split locking,
|
|
52
|
+
* journaling, version, or cache identity for one writable physical resource.
|
|
53
|
+
*/
|
|
54
|
+
export declare function createRootRegistry(input: RootRegistryInput): RootRegistry;
|
|
55
|
+
export {};
|
|
56
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/resources/registry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAwC,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAChG,OAAO,EAAwB,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAgB,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAEvF,QAAA,MAAM,UAAU,EAAE,OAAO,MAAsC,CAAC;AAGhE,eAAO,MAAM,sBAAsB,YAAI,oBAAoB,EAAE,mBAAmB,EAAE,cAAc,CAAU,CAAC;AAC3G,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,qFAAqF;IACrF,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC;IAC7C,QAAQ,CAAC,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChD,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;CACtC;AAED,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,eAAe,CAAC;IAC3B,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACpC,WAAW,EAAE,eAAe,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,SAAS,CACR,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,mBAAmB,EAC9B,SAAS,EAAE,eAAe,GACxB,SAAS,GAAG,oBAAoB,CAAC;CACpC;AAED,MAAM,WAAW,iBAAiB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;CAC7B;AAED,4EAA4E;AAC5E,qBAAa,8BAA+B,SAAQ,KAAK;IACxD,YAAY,OAAO,EAAE,MAAM,EAG1B;CACD;AA4BD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,kBAAkB,GAAG,SAAS,CA6BxE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAE9D;AAmCD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,YAAY,CA+BzE"}
|