@ricsam/r5d-worker 0.0.123 → 0.0.125
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 +1 -1
- package/dist/cjs/command-launcher.cjs +6 -2
- package/dist/cjs/main.cjs +496 -238
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/project-checkout-garbage.cjs +32 -3
- package/dist/cjs/project-workspace-state.cjs +51 -35
- package/dist/cjs/project-worktrees.cjs +79 -34
- package/dist/cjs/recovery-journal-protocol.cjs +56 -0
- package/dist/cjs/recovery-journal-runtime.cjs +133 -0
- package/dist/cjs/recovery-journal-thread.cjs +9 -0
- package/dist/cjs/recovery-journal.cjs +735 -0
- package/dist/cjs/recovery-store.cjs +8 -0
- package/dist/cjs/session-file-mutations.cjs +61 -0
- package/dist/cjs/working-tree-mirror.cjs +1 -0
- package/dist/cjs/workspace-command-sync-policy.cjs +37 -8
- package/dist/cjs/workspace-filesystem-executor-thread.cjs +36 -0
- package/dist/cjs/workspace-filesystem-executor.cjs +327 -0
- package/dist/cjs/workspace-filesystem-job-types.cjs +134 -0
- package/dist/cjs/workspace-filesystem-jobs.cjs +57 -0
- package/dist/cjs/workspace-git-sync.cjs +275 -201
- package/dist/cjs/workspace-mount-hold-fence.cjs +120 -0
- package/dist/mjs/command-launcher.mjs +6 -2
- package/dist/mjs/main.mjs +499 -244
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/project-checkout-garbage.mjs +30 -2
- package/dist/mjs/project-workspace-state.mjs +51 -35
- package/dist/mjs/project-worktrees.mjs +74 -34
- package/dist/mjs/recovery-journal-protocol.mjs +30 -0
- package/dist/mjs/recovery-journal-runtime.mjs +112 -0
- package/dist/mjs/recovery-journal-thread.mjs +8 -0
- package/dist/mjs/recovery-journal.mjs +687 -0
- package/dist/mjs/recovery-store.mjs +8 -0
- package/dist/mjs/session-file-mutations.mjs +37 -0
- package/dist/mjs/working-tree-mirror.mjs +1 -0
- package/dist/mjs/workspace-command-sync-policy.mjs +37 -8
- package/dist/mjs/workspace-filesystem-executor-thread.mjs +38 -0
- package/dist/mjs/workspace-filesystem-executor.mjs +287 -0
- package/dist/mjs/workspace-filesystem-job-types.mjs +106 -0
- package/dist/mjs/workspace-filesystem-jobs.mjs +51 -0
- package/dist/mjs/workspace-git-sync.mjs +264 -202
- package/dist/mjs/workspace-mount-hold-fence.mjs +95 -0
- package/dist/types/command-launcher.d.ts +2 -1
- package/dist/types/main.d.ts +30 -19
- package/dist/types/project-checkout-garbage.d.ts +19 -2
- package/dist/types/project-workspace-state.d.ts +9 -9
- package/dist/types/project-worktrees.d.ts +49 -5
- package/dist/types/recovery-journal-protocol.d.ts +35 -0
- package/dist/types/recovery-journal-runtime.d.ts +12 -0
- package/dist/types/recovery-journal-stall-fixture.d.ts +1 -0
- package/dist/types/recovery-journal-thread.d.ts +1 -0
- package/dist/types/recovery-journal.d.ts +246 -0
- package/dist/types/recovery-store.d.ts +6 -0
- package/dist/types/session-file-mutations.d.ts +22 -0
- package/dist/types/workspace-command-sync-policy.d.ts +22 -7
- package/dist/types/workspace-filesystem-executor-thread.d.ts +1 -0
- package/dist/types/workspace-filesystem-executor.d.ts +123 -0
- package/dist/types/workspace-filesystem-job-types.d.ts +246 -0
- package/dist/types/workspace-filesystem-jobs.d.ts +7 -0
- package/dist/types/workspace-git-sync.d.ts +113 -7
- package/dist/types/workspace-mount-hold-fence.d.ts +42 -0
- package/package.json +1 -1
- package/dist/cjs/project-snapshot-recovery-runner.cjs +0 -171
- package/dist/mjs/project-snapshot-recovery-runner.mjs +0 -135
- package/dist/types/project-snapshot-recovery-runner.d.ts +0 -10
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var workspace_mount_hold_fence_exports = {};
|
|
20
|
+
__export(workspace_mount_hold_fence_exports, {
|
|
21
|
+
WorkspaceMountHoldAbortedError: () => WorkspaceMountHoldAbortedError,
|
|
22
|
+
WorkspaceMountHoldFence: () => WorkspaceMountHoldFence
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(workspace_mount_hold_fence_exports);
|
|
25
|
+
class WorkspaceMountHoldAbortedError extends Error {
|
|
26
|
+
constructor(reason) {
|
|
27
|
+
super(reason);
|
|
28
|
+
this.name = "WorkspaceMountHoldAbortedError";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
class WorkspaceMountHoldFence {
|
|
32
|
+
holds = /* @__PURE__ */ new Map();
|
|
33
|
+
waiters = /* @__PURE__ */ new Set();
|
|
34
|
+
now;
|
|
35
|
+
constructor(options = {}) {
|
|
36
|
+
this.now = options.now ?? (() => Date.now());
|
|
37
|
+
}
|
|
38
|
+
/** Take one hold on every listed mount; the returned release is idempotent. */
|
|
39
|
+
hold(mountIds, description) {
|
|
40
|
+
const ids = [...new Set(mountIds)];
|
|
41
|
+
for (const id of ids) {
|
|
42
|
+
const existing = this.holds.get(id);
|
|
43
|
+
if (existing) {
|
|
44
|
+
existing.count += 1;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
this.holds.set(id, { count: 1, description, sinceMs: this.now() });
|
|
48
|
+
}
|
|
49
|
+
let released = false;
|
|
50
|
+
return () => {
|
|
51
|
+
if (released) return;
|
|
52
|
+
released = true;
|
|
53
|
+
for (const id of ids) {
|
|
54
|
+
const existing = this.holds.get(id);
|
|
55
|
+
if (!existing) continue;
|
|
56
|
+
existing.count -= 1;
|
|
57
|
+
if (existing.count === 0) this.holds.delete(id);
|
|
58
|
+
}
|
|
59
|
+
this.wake();
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
isHeld(mountIds) {
|
|
63
|
+
return mountIds.some((id) => this.holds.has(id));
|
|
64
|
+
}
|
|
65
|
+
/** Human-readable holder of the first held mount among `mountIds`, for diagnostics. */
|
|
66
|
+
describeHold(mountIds) {
|
|
67
|
+
for (const id of mountIds) {
|
|
68
|
+
const hold = this.holds.get(id);
|
|
69
|
+
if (hold) return `${hold.description} (held for ${Math.round((this.now() - hold.sinceMs) / 1e3)}s)`;
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
/** Every held mount id, sorted, for status reporting. */
|
|
74
|
+
heldMountIds() {
|
|
75
|
+
return [...this.holds.keys()].sort();
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Resolves in the same turn as the release that leaves none of `mountIds`
|
|
79
|
+
* held, so the caller can re-check and reserve without an interleaving
|
|
80
|
+
* hold. Resolves immediately when nothing is held. Rejects with
|
|
81
|
+
* WorkspaceMountHoldAbortedError when `signal` aborts first.
|
|
82
|
+
*/
|
|
83
|
+
waitForRelease(mountIds, options = {}) {
|
|
84
|
+
if (options.signal?.aborted) {
|
|
85
|
+
return Promise.reject(new WorkspaceMountHoldAbortedError(abortReason(options.signal)));
|
|
86
|
+
}
|
|
87
|
+
if (!this.isHeld(mountIds)) return Promise.resolve();
|
|
88
|
+
return new Promise((resolve, reject) => {
|
|
89
|
+
const waiter = { mountIds, resolve, reject, signal: options.signal };
|
|
90
|
+
if (options.signal) {
|
|
91
|
+
const signal = options.signal;
|
|
92
|
+
waiter.onAbort = () => {
|
|
93
|
+
this.waiters.delete(waiter);
|
|
94
|
+
reject(new WorkspaceMountHoldAbortedError(abortReason(signal)));
|
|
95
|
+
};
|
|
96
|
+
signal.addEventListener("abort", waiter.onAbort, { once: true });
|
|
97
|
+
}
|
|
98
|
+
this.waiters.add(waiter);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
wake() {
|
|
102
|
+
for (const waiter of [...this.waiters]) {
|
|
103
|
+
if (this.isHeld(waiter.mountIds)) continue;
|
|
104
|
+
this.waiters.delete(waiter);
|
|
105
|
+
if (waiter.signal && waiter.onAbort) waiter.signal.removeEventListener("abort", waiter.onAbort);
|
|
106
|
+
waiter.resolve();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function abortReason(signal) {
|
|
111
|
+
const reason = signal.reason;
|
|
112
|
+
if (reason instanceof Error) return reason.message;
|
|
113
|
+
if (typeof reason === "string" && reason) return reason;
|
|
114
|
+
return "Workspace mount reservation was aborted";
|
|
115
|
+
}
|
|
116
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
117
|
+
0 && (module.exports = {
|
|
118
|
+
WorkspaceMountHoldAbortedError,
|
|
119
|
+
WorkspaceMountHoldFence
|
|
120
|
+
});
|
|
@@ -216,7 +216,9 @@ class WorkerCommandLauncher {
|
|
|
216
216
|
if (!argv.length) throw new Error("Command argv must not be empty");
|
|
217
217
|
return [...prefix, ...argv];
|
|
218
218
|
},
|
|
219
|
-
cancel: () =>
|
|
219
|
+
cancel: async () => {
|
|
220
|
+
await this.cancel(request.id);
|
|
221
|
+
},
|
|
220
222
|
diagnose: async () => {
|
|
221
223
|
this.assertHealthy();
|
|
222
224
|
if (!this.child) return void 0;
|
|
@@ -232,9 +234,10 @@ class WorkerCommandLauncher {
|
|
|
232
234
|
release: () => this.releaseRecord(record)
|
|
233
235
|
};
|
|
234
236
|
}
|
|
237
|
+
/** Revoke a launch. Returns whether this launcher still held it (queued or acquired, not yet released). */
|
|
235
238
|
async cancel(id) {
|
|
236
239
|
const record = this.launches.get(id);
|
|
237
|
-
if (!record || record.released) return;
|
|
240
|
+
if (!record || record.released) return false;
|
|
238
241
|
record.revoked = true;
|
|
239
242
|
record.rejectAdmission(new CommandLaunchCancelledError());
|
|
240
243
|
if (this.child) {
|
|
@@ -244,6 +247,7 @@ class WorkerCommandLauncher {
|
|
|
244
247
|
throw this.fail(error instanceof Error ? error : new Error(String(error)));
|
|
245
248
|
}
|
|
246
249
|
}
|
|
250
|
+
return true;
|
|
247
251
|
}
|
|
248
252
|
async cancelSession(sessionId) {
|
|
249
253
|
await this.cancelMatching((_id, ownerSessionId) => ownerSessionId === sessionId);
|