@ricsam/r5d-worker 0.0.137 → 0.0.139
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 +4 -94
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/main.mjs +46 -7543
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/personal/action-scheduler.mjs +31 -0
- package/dist/mjs/personal/client.mjs +215 -0
- package/dist/mjs/personal/runtime.mjs +359 -0
- package/dist/mjs/personal/tcp.mjs +217 -0
- package/dist/mjs/runtime/adapter.mjs +42 -0
- package/dist/mjs/runtime/client.mjs +95 -0
- package/dist/mjs/runtime/daemon.mjs +131 -0
- package/dist/mjs/runtime/executor.mjs +436 -0
- package/dist/mjs/runtime/index.mjs +15 -0
- package/dist/mjs/runtime/protocol.mjs +139 -0
- package/dist/mjs/runtime/pty-host.mjs +156 -0
- package/dist/mjs/runtime/pty.mjs +127 -0
- package/dist/mjs/runtime/releases/artifacts.mjs +201 -0
- package/dist/mjs/runtime/releases/grants.mjs +93 -0
- package/dist/mjs/runtime/releases/main.mjs +101 -0
- package/dist/mjs/runtime/releases/manager.mjs +541 -0
- package/dist/mjs/runtime/releases/process.mjs +88 -0
- package/dist/mjs/runtime/releases/retirement.mjs +18 -0
- package/dist/mjs/runtime/releases/rpc-client.mjs +184 -0
- package/dist/mjs/runtime/releases/rpc-main.mjs +213 -0
- package/dist/mjs/runtime/releases/rpc-protocol.mjs +103 -0
- package/dist/mjs/runtime/storage.mjs +156 -0
- package/dist/mjs/runtime/workspace/artifacts.mjs +121 -0
- package/dist/mjs/runtime/workspace/authority.mjs +1355 -0
- package/dist/mjs/runtime/workspace/contracts.mjs +60 -0
- package/dist/mjs/runtime/workspace/file-write.mjs +23 -0
- package/dist/mjs/runtime/workspace/files.mjs +308 -0
- package/dist/mjs/runtime/workspace/http-body.mjs +45 -0
- package/dist/mjs/runtime/workspace/storage-client.mjs +59 -0
- package/dist/mjs/runtime/workspace/storage-wire.mjs +53 -0
- package/dist/types/main.d.ts +0 -1167
- package/dist/types/personal/action-scheduler.d.ts +23 -0
- package/dist/types/personal/client.d.ts +14 -0
- package/dist/types/personal/runtime.d.ts +121 -0
- package/dist/types/personal/tcp.d.ts +14 -0
- package/dist/types/runtime/client.d.ts +3 -1
- package/dist/types/runtime/executor.d.ts +6 -1
- package/dist/types/runtime/protocol.d.ts +176 -4
- package/dist/types/runtime/pty.d.ts +1 -0
- package/dist/types/runtime/releases/artifacts.d.ts +51 -0
- package/dist/types/runtime/releases/grants.d.ts +16 -0
- package/dist/types/runtime/releases/manager.d.ts +145 -0
- package/dist/types/runtime/releases/process.d.ts +14 -0
- package/dist/types/runtime/releases/retirement.d.ts +15 -0
- package/dist/types/runtime/releases/rpc-client.d.ts +52 -0
- package/dist/types/runtime/releases/rpc-main.d.ts +10 -0
- package/dist/types/runtime/releases/rpc-protocol.d.ts +1139 -0
- package/dist/types/runtime/workspace/artifacts.d.ts +30 -0
- package/dist/types/runtime/workspace/authority.d.ts +338 -0
- package/dist/types/runtime/workspace/contracts.d.ts +86 -0
- package/dist/types/runtime/workspace/file-write.d.ts +14 -0
- package/dist/types/runtime/workspace/files.d.ts +21 -0
- package/dist/types/runtime/workspace/http-body.d.ts +9 -0
- package/dist/types/runtime/workspace/storage-client.d.ts +23 -0
- package/dist/types/runtime/workspace/storage-wire.d.ts +138 -0
- package/package.json +8 -6
- package/dist/cjs/atomic-rename.cjs +0 -303
- package/dist/cjs/browser-upload.cjs +0 -73
- package/dist/cjs/cli-update.cjs +0 -108
- package/dist/cjs/command-launcher.cjs +0 -423
- package/dist/cjs/control-command-policy.cjs +0 -177
- package/dist/cjs/git-blob-hash.cjs +0 -41
- package/dist/cjs/git-identity.cjs +0 -39
- package/dist/cjs/git-process-environment.cjs +0 -133
- package/dist/cjs/inline-output.cjs +0 -62
- package/dist/cjs/main.cjs +0 -7517
- package/dist/cjs/managed-paths.cjs +0 -215
- package/dist/cjs/plan-lint.cjs +0 -165
- package/dist/cjs/plan-parser.cjs +0 -127
- package/dist/cjs/plan-paths.cjs +0 -53
- package/dist/cjs/port-forward-client.cjs +0 -206
- package/dist/cjs/process-tree.cjs +0 -117
- package/dist/cjs/project-checkout-garbage.cjs +0 -219
- package/dist/cjs/project-mirror-fetch-policy.cjs +0 -82
- package/dist/cjs/project-mirror-refs-token.cjs +0 -85
- package/dist/cjs/project-workspace-state.cjs +0 -972
- package/dist/cjs/project-worktrees.cjs +0 -1713
- package/dist/cjs/pty-output-coalescer.cjs +0 -87
- package/dist/cjs/recovery-journal-protocol.cjs +0 -56
- package/dist/cjs/recovery-journal-runtime.cjs +0 -133
- package/dist/cjs/recovery-journal-thread.cjs +0 -9
- package/dist/cjs/recovery-journal.cjs +0 -742
- package/dist/cjs/recovery-output-window.cjs +0 -77
- package/dist/cjs/recovery-protocol.cjs +0 -31
- package/dist/cjs/recovery-store.cjs +0 -252
- package/dist/cjs/registry-auth.cjs +0 -310
- package/dist/cjs/repository-transition-policy.cjs +0 -49
- package/dist/cjs/runtime-version.cjs +0 -88
- package/dist/cjs/session-file-mutations.cjs +0 -61
- package/dist/cjs/supervisor.cjs +0 -147
- package/dist/cjs/three-way-merge.cjs +0 -346
- package/dist/cjs/working-tree-mirror.cjs +0 -1872
- package/dist/cjs/workspace-automatic-sync-policy.cjs +0 -79
- package/dist/cjs/workspace-branch-incarnation-policy.cjs +0 -37
- package/dist/cjs/workspace-command-sync-policy.cjs +0 -112
- package/dist/cjs/workspace-command-targets.cjs +0 -63
- package/dist/cjs/workspace-filesystem-executor-thread.cjs +0 -36
- package/dist/cjs/workspace-filesystem-executor.cjs +0 -327
- package/dist/cjs/workspace-filesystem-job-types.cjs +0 -144
- package/dist/cjs/workspace-filesystem-jobs.cjs +0 -59
- package/dist/cjs/workspace-git-sync.cjs +0 -3595
- package/dist/cjs/workspace-hydration-ledger.cjs +0 -83
- package/dist/cjs/workspace-hydration-merge.cjs +0 -448
- package/dist/cjs/workspace-hydration-recovery-state.cjs +0 -53
- package/dist/cjs/workspace-incident-state.cjs +0 -37
- package/dist/cjs/workspace-merge-projection.cjs +0 -628
- package/dist/cjs/workspace-mount-boundary.cjs +0 -71
- package/dist/cjs/workspace-mount-hold-fence.cjs +0 -120
- package/dist/cjs/workspace-mutation-gate.cjs +0 -127
- package/dist/cjs/workspace-path-move.cjs +0 -195
- package/dist/cjs/workspace-preserve-only-policy.cjs +0 -36
- package/dist/cjs/workspace-project-config-policy.cjs +0 -53
- package/dist/cjs/workspace-projection-ledger.cjs +0 -81
- package/dist/cjs/workspace-publication-evidence.cjs +0 -46
- package/dist/cjs/workspace-sync-coalescer.cjs +0 -58
- package/dist/mjs/atomic-rename.mjs +0 -261
- package/dist/mjs/browser-upload.mjs +0 -42
- package/dist/mjs/command-launcher.mjs +0 -393
- package/dist/mjs/control-command-policy.mjs +0 -146
- package/dist/mjs/git-blob-hash.mjs +0 -16
- package/dist/mjs/git-identity.mjs +0 -15
- package/dist/mjs/git-process-environment.mjs +0 -105
- package/dist/mjs/inline-output.mjs +0 -37
- package/dist/mjs/managed-paths.mjs +0 -174
- package/dist/mjs/plan-lint.mjs +0 -129
- package/dist/mjs/plan-parser.mjs +0 -94
- package/dist/mjs/plan-paths.mjs +0 -25
- package/dist/mjs/port-forward-client.mjs +0 -172
- package/dist/mjs/project-checkout-garbage.mjs +0 -178
- package/dist/mjs/project-mirror-fetch-policy.mjs +0 -56
- package/dist/mjs/project-mirror-refs-token.mjs +0 -53
- package/dist/mjs/project-workspace-state.mjs +0 -937
- package/dist/mjs/project-worktrees.mjs +0 -1657
- package/dist/mjs/pty-output-coalescer.mjs +0 -61
- package/dist/mjs/recovery-journal-protocol.mjs +0 -30
- package/dist/mjs/recovery-journal-runtime.mjs +0 -112
- package/dist/mjs/recovery-journal-thread.mjs +0 -8
- package/dist/mjs/recovery-journal.mjs +0 -694
- package/dist/mjs/recovery-output-window.mjs +0 -53
- package/dist/mjs/recovery-protocol.mjs +0 -6
- package/dist/mjs/recovery-store.mjs +0 -217
- package/dist/mjs/registry-auth.mjs +0 -269
- package/dist/mjs/repository-transition-policy.mjs +0 -22
- package/dist/mjs/runtime-version.mjs +0 -54
- package/dist/mjs/session-file-mutations.mjs +0 -37
- package/dist/mjs/supervisor.mjs +0 -114
- package/dist/mjs/three-way-merge.mjs +0 -318
- package/dist/mjs/working-tree-mirror.mjs +0 -1817
- package/dist/mjs/workspace-automatic-sync-policy.mjs +0 -48
- package/dist/mjs/workspace-branch-incarnation-policy.mjs +0 -13
- package/dist/mjs/workspace-command-sync-policy.mjs +0 -84
- package/dist/mjs/workspace-command-targets.mjs +0 -37
- package/dist/mjs/workspace-filesystem-executor-thread.mjs +0 -38
- package/dist/mjs/workspace-filesystem-executor.mjs +0 -287
- package/dist/mjs/workspace-filesystem-job-types.mjs +0 -116
- package/dist/mjs/workspace-filesystem-jobs.mjs +0 -55
- package/dist/mjs/workspace-git-sync.mjs +0 -3553
- package/dist/mjs/workspace-hydration-ledger.mjs +0 -58
- package/dist/mjs/workspace-hydration-merge.mjs +0 -414
- package/dist/mjs/workspace-hydration-recovery-state.mjs +0 -29
- package/dist/mjs/workspace-incident-state.mjs +0 -12
- package/dist/mjs/workspace-merge-projection.mjs +0 -594
- package/dist/mjs/workspace-mount-boundary.mjs +0 -37
- package/dist/mjs/workspace-mount-hold-fence.mjs +0 -95
- package/dist/mjs/workspace-mutation-gate.mjs +0 -103
- package/dist/mjs/workspace-path-move.mjs +0 -160
- package/dist/mjs/workspace-preserve-only-policy.mjs +0 -11
- package/dist/mjs/workspace-project-config-policy.mjs +0 -27
- package/dist/mjs/workspace-projection-ledger.mjs +0 -57
- package/dist/mjs/workspace-publication-evidence.mjs +0 -21
- package/dist/mjs/workspace-sync-coalescer.mjs +0 -34
- package/dist/types/atomic-rename.d.ts +0 -78
- package/dist/types/browser-upload.d.ts +0 -7
- package/dist/types/command-launcher.d.ts +0 -104
- package/dist/types/control-command-policy.d.ts +0 -53
- package/dist/types/git-blob-hash.d.ts +0 -10
- package/dist/types/git-identity.d.ts +0 -9
- package/dist/types/git-process-environment.d.ts +0 -9
- package/dist/types/inline-output.d.ts +0 -3
- package/dist/types/managed-paths.d.ts +0 -19
- package/dist/types/plan-lint.d.ts +0 -16
- package/dist/types/plan-parser.d.ts +0 -38
- package/dist/types/plan-paths.d.ts +0 -36
- package/dist/types/port-forward-client.d.ts +0 -8
- package/dist/types/project-checkout-garbage.d.ts +0 -86
- package/dist/types/project-mirror-fetch-policy.d.ts +0 -84
- package/dist/types/project-mirror-refs-token.d.ts +0 -53
- package/dist/types/project-workspace-state.d.ts +0 -188
- package/dist/types/project-worktrees.d.ts +0 -397
- package/dist/types/pty-output-coalescer.d.ts +0 -20
- package/dist/types/recovery-journal-protocol.d.ts +0 -35
- package/dist/types/recovery-journal-runtime.d.ts +0 -12
- package/dist/types/recovery-journal-stall-fixture.d.ts +0 -1
- package/dist/types/recovery-journal-thread.d.ts +0 -1
- package/dist/types/recovery-journal.d.ts +0 -248
- package/dist/types/recovery-output-window.d.ts +0 -19
- package/dist/types/recovery-protocol.d.ts +0 -59
- package/dist/types/recovery-store.d.ts +0 -52
- package/dist/types/registry-auth.d.ts +0 -47
- package/dist/types/repository-transition-policy.d.ts +0 -26
- package/dist/types/runtime-version.d.ts +0 -1
- package/dist/types/session-file-mutations.d.ts +0 -22
- package/dist/types/supervisor-daemonized-fixture.d.ts +0 -1
- package/dist/types/supervisor-launcher-cleanup-fixture.d.ts +0 -1
- package/dist/types/supervisor-signal-fixture.d.ts +0 -1
- package/dist/types/supervisor.d.ts +0 -23
- package/dist/types/three-way-merge.d.ts +0 -77
- package/dist/types/working-tree-mirror.d.ts +0 -424
- package/dist/types/workspace-automatic-sync-policy.d.ts +0 -57
- package/dist/types/workspace-branch-incarnation-policy.d.ts +0 -14
- package/dist/types/workspace-command-sync-policy.d.ts +0 -57
- package/dist/types/workspace-command-targets.d.ts +0 -37
- package/dist/types/workspace-filesystem-executor-thread.d.ts +0 -1
- package/dist/types/workspace-filesystem-executor.d.ts +0 -123
- package/dist/types/workspace-filesystem-job-types.d.ts +0 -302
- package/dist/types/workspace-filesystem-jobs.d.ts +0 -7
- package/dist/types/workspace-git-sync.d.ts +0 -514
- package/dist/types/workspace-hydration-ledger.d.ts +0 -76
- package/dist/types/workspace-hydration-merge.d.ts +0 -103
- package/dist/types/workspace-hydration-recovery-state.d.ts +0 -10
- package/dist/types/workspace-incident-state.d.ts +0 -19
- package/dist/types/workspace-merge-projection.d.ts +0 -69
- package/dist/types/workspace-mount-boundary.d.ts +0 -10
- package/dist/types/workspace-mount-hold-fence.d.ts +0 -42
- package/dist/types/workspace-mutation-gate.d.ts +0 -42
- package/dist/types/workspace-path-move.d.ts +0 -21
- package/dist/types/workspace-preserve-only-policy.d.ts +0 -15
- package/dist/types/workspace-project-config-policy.d.ts +0 -48
- package/dist/types/workspace-projection-ledger.d.ts +0 -59
- package/dist/types/workspace-publication-evidence.d.ts +0 -17
- package/dist/types/workspace-sync-coalescer.d.ts +0 -28
- /package/dist/types/{credential-authority-lock-fixture.d.ts → runtime/releases/main.d.ts} +0 -0
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
const PENDING_CREATED_BRANCH_AUTOMATIC_SYNC_GRACE_MS = 12e4;
|
|
2
|
-
function pendingCreatedBranchKey(projectId, branchName) {
|
|
3
|
-
return `${projectId}\0${branchName}`;
|
|
4
|
-
}
|
|
5
|
-
function hasActiveVisibleProjectsWorkspaceTarget(activeTargets) {
|
|
6
|
-
for (const target of activeTargets) {
|
|
7
|
-
if (target.type === "workspace" && target.rootProfile === "visible_projects") return true;
|
|
8
|
-
}
|
|
9
|
-
return false;
|
|
10
|
-
}
|
|
11
|
-
function projectBranchHasActiveWorkspaceTarget(projectId, branchName, activeTargets) {
|
|
12
|
-
for (const target of activeTargets) {
|
|
13
|
-
if (target.type === "project" && target.projectId === projectId && target.branchName === branchName) return true;
|
|
14
|
-
if (target.type === "workspace" && target.rootProfile === "visible_projects") return true;
|
|
15
|
-
}
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
function projectBranchMountBusyDuringExclusiveSync(input) {
|
|
19
|
-
return input.executionDisabled || input.worktreeOperationInProgress || input.retainedCanonicalProcessGroup || projectBranchHasActiveWorkspaceTarget(input.projectId, input.branchName, input.activeTargets);
|
|
20
|
-
}
|
|
21
|
-
function workspacePlansMountBusyDuringExclusiveSync(activeTargets, retainedCanonicalProcessGroup = false) {
|
|
22
|
-
return retainedCanonicalProcessGroup || hasActiveVisibleProjectsWorkspaceTarget(activeTargets);
|
|
23
|
-
}
|
|
24
|
-
function shouldDeferAutomaticWorkspaceSyncForPendingBranch(pendingCreatedBranches, activeTargets) {
|
|
25
|
-
if (pendingCreatedBranches.length === 0) return false;
|
|
26
|
-
const targets = [...activeTargets];
|
|
27
|
-
return pendingCreatedBranches.some(({ projectId, branchName }) => projectBranchHasActiveWorkspaceTarget(projectId, branchName, targets));
|
|
28
|
-
}
|
|
29
|
-
function pendingCreatedBranchAutomaticSyncDeferral(pendingCreatedBranches, activeTargets, publicationNotBeforeByBranch, nowMs = Date.now()) {
|
|
30
|
-
if (shouldDeferAutomaticWorkspaceSyncForPendingBranch(pendingCreatedBranches, activeTargets)) {
|
|
31
|
-
return { kind: "active_target" };
|
|
32
|
-
}
|
|
33
|
-
const notBeforeMs = pendingCreatedBranches.reduce(
|
|
34
|
-
(latest, { projectId, branchName }) => Math.max(latest, publicationNotBeforeByBranch.get(pendingCreatedBranchKey(projectId, branchName)) ?? 0),
|
|
35
|
-
0
|
|
36
|
-
);
|
|
37
|
-
return notBeforeMs > nowMs ? { kind: "creation_grace", retryAfterMs: notBeforeMs - nowMs } : null;
|
|
38
|
-
}
|
|
39
|
-
export {
|
|
40
|
-
PENDING_CREATED_BRANCH_AUTOMATIC_SYNC_GRACE_MS,
|
|
41
|
-
hasActiveVisibleProjectsWorkspaceTarget,
|
|
42
|
-
pendingCreatedBranchAutomaticSyncDeferral,
|
|
43
|
-
pendingCreatedBranchKey,
|
|
44
|
-
projectBranchHasActiveWorkspaceTarget,
|
|
45
|
-
projectBranchMountBusyDuringExclusiveSync,
|
|
46
|
-
shouldDeferAutomaticWorkspaceSyncForPendingBranch,
|
|
47
|
-
workspacePlansMountBusyDuringExclusiveSync
|
|
48
|
-
};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
function assertProjectBranchDeletionIncarnation(input) {
|
|
2
|
-
if (!/^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/.test(input.requiredBranchId)) {
|
|
3
|
-
throw new Error("Project branch deletion requires a valid durable branch incarnation");
|
|
4
|
-
}
|
|
5
|
-
for (const branch of [input.configuredBranch, input.pendingLocalBranch]) {
|
|
6
|
-
if (branch && branch.branchId !== input.requiredBranchId) {
|
|
7
|
-
throw new Error("Project branch deletion belongs to another durable branch incarnation");
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
export {
|
|
12
|
-
assertProjectBranchDeletionIncarnation
|
|
13
|
-
};
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { WorkspaceMountHoldAbortedError } from "./workspace-mount-hold-fence.mjs";
|
|
2
|
-
function requiresCurrentSyncBarrier(targets) {
|
|
3
|
-
return targets.some((target) => target.type === "workspace" && target.rootProfile === "visible_projects");
|
|
4
|
-
}
|
|
5
|
-
function asTargetList(target) {
|
|
6
|
-
return Array.isArray(target) ? target : [target];
|
|
7
|
-
}
|
|
8
|
-
async function reserveWorkspaceCommandAfterCurrentSync(target, coordinator, reserve, options = {}) {
|
|
9
|
-
const targets = asTargetList(target);
|
|
10
|
-
while (true) {
|
|
11
|
-
if (requiresCurrentSyncBarrier(targets)) {
|
|
12
|
-
const currentSync = coordinator.afterCurrent();
|
|
13
|
-
await raceWithAbort(currentSync, options.signal);
|
|
14
|
-
if (currentSync !== coordinator.afterCurrent()) continue;
|
|
15
|
-
}
|
|
16
|
-
if (options.signal?.aborted) throw new WorkspaceMountHoldAbortedError(abortReason(options.signal));
|
|
17
|
-
const hold = coordinator.mountHold(targets, options.signal);
|
|
18
|
-
if (hold) {
|
|
19
|
-
await hold;
|
|
20
|
-
continue;
|
|
21
|
-
}
|
|
22
|
-
reserve();
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
function raceWithAbort(waited, signal) {
|
|
27
|
-
if (!signal) return waited;
|
|
28
|
-
if (signal.aborted) return Promise.reject(new WorkspaceMountHoldAbortedError(abortReason(signal)));
|
|
29
|
-
return new Promise((resolve, reject) => {
|
|
30
|
-
const onAbort = () => reject(new WorkspaceMountHoldAbortedError(abortReason(signal)));
|
|
31
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
32
|
-
waited.then(
|
|
33
|
-
() => {
|
|
34
|
-
signal.removeEventListener("abort", onAbort);
|
|
35
|
-
resolve();
|
|
36
|
-
},
|
|
37
|
-
(error) => {
|
|
38
|
-
signal.removeEventListener("abort", onAbort);
|
|
39
|
-
reject(error instanceof Error ? error : new Error(String(error)));
|
|
40
|
-
}
|
|
41
|
-
);
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
function abortReason(signal) {
|
|
45
|
-
const reason = signal.reason;
|
|
46
|
-
if (reason instanceof Error) return reason.message;
|
|
47
|
-
if (typeof reason === "string" && reason) return reason;
|
|
48
|
-
return "Workspace command reservation was aborted";
|
|
49
|
-
}
|
|
50
|
-
function shouldSerializeWorkspaceCommand(target) {
|
|
51
|
-
return target.type === "workspace" && target.rootProfile === "canonical_sync";
|
|
52
|
-
}
|
|
53
|
-
function runWorkspaceCommand(target, coordinator, operation) {
|
|
54
|
-
return shouldSerializeWorkspaceCommand(target) ? coordinator.runMutation(operation) : Promise.resolve().then(operation);
|
|
55
|
-
}
|
|
56
|
-
async function runReservedWorkspaceCommand(target, coordinator, operation, releaseReservation) {
|
|
57
|
-
let released = false;
|
|
58
|
-
const releaseOnce = () => {
|
|
59
|
-
if (released) return;
|
|
60
|
-
released = true;
|
|
61
|
-
releaseReservation();
|
|
62
|
-
};
|
|
63
|
-
try {
|
|
64
|
-
return await runWorkspaceCommand(target, coordinator, async () => {
|
|
65
|
-
try {
|
|
66
|
-
return await operation();
|
|
67
|
-
} finally {
|
|
68
|
-
releaseOnce();
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
} finally {
|
|
72
|
-
releaseOnce();
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
function acquireWorkspaceCommandMutation(target, coordinator) {
|
|
76
|
-
return shouldSerializeWorkspaceCommand(target) ? coordinator.acquireMutation() : Promise.resolve(void 0);
|
|
77
|
-
}
|
|
78
|
-
export {
|
|
79
|
-
acquireWorkspaceCommandMutation,
|
|
80
|
-
reserveWorkspaceCommandAfterCurrentSync,
|
|
81
|
-
runReservedWorkspaceCommand,
|
|
82
|
-
runWorkspaceCommand,
|
|
83
|
-
shouldSerializeWorkspaceCommand
|
|
84
|
-
};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
function targetKey(target) {
|
|
2
|
-
return `${target.projectId}\0${target.branchName}`;
|
|
3
|
-
}
|
|
4
|
-
function normalizeCommandAdditionalTargets(primary, additional, validators) {
|
|
5
|
-
if (additional === void 0 || additional === null) return [];
|
|
6
|
-
if (!Array.isArray(additional)) throw new Error("Command additional targets must be a list of project branches");
|
|
7
|
-
const seen = new Set(primary.type === "project" ? [targetKey(primary)] : []);
|
|
8
|
-
const normalized = [];
|
|
9
|
-
for (const entry of additional) {
|
|
10
|
-
if (!entry || typeof entry !== "object" || entry.type !== "project") {
|
|
11
|
-
throw new Error("Command additional targets must be project branches");
|
|
12
|
-
}
|
|
13
|
-
const { projectId, branchName } = entry;
|
|
14
|
-
if (typeof projectId !== "string" || typeof branchName !== "string")
|
|
15
|
-
throw new Error("Command additional target is missing its project or branch");
|
|
16
|
-
validators.validateProjectId(projectId);
|
|
17
|
-
validators.validateBranchName(branchName);
|
|
18
|
-
const target = { type: "project", projectId, branchName };
|
|
19
|
-
const key = targetKey(target);
|
|
20
|
-
if (seen.has(key)) continue;
|
|
21
|
-
seen.add(key);
|
|
22
|
-
normalized.push(target);
|
|
23
|
-
}
|
|
24
|
-
return normalized;
|
|
25
|
-
}
|
|
26
|
-
function commandTargets(primary, additional) {
|
|
27
|
-
return [primary, ...additional];
|
|
28
|
-
}
|
|
29
|
-
function describeCommandAdditionalTargets(additional) {
|
|
30
|
-
if (additional.length === 0) return "";
|
|
31
|
-
return ` (also fencing ${additional.map((target) => `${target.projectId}/${target.branchName}`).join(", ")})`;
|
|
32
|
-
}
|
|
33
|
-
export {
|
|
34
|
-
commandTargets,
|
|
35
|
-
describeCommandAdditionalTargets,
|
|
36
|
-
normalizeCommandAdditionalTargets
|
|
37
|
-
};
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { isMainThread, parentPort } from "node:worker_threads";
|
|
2
|
-
import {
|
|
3
|
-
isWorkspaceFilesystemJobKind,
|
|
4
|
-
serializeWorkspaceFilesystemError
|
|
5
|
-
} from "./workspace-filesystem-job-types.mjs";
|
|
6
|
-
import { workspaceFilesystemJobOperations } from "./workspace-filesystem-jobs.mjs";
|
|
7
|
-
if (isMainThread || !parentPort) {
|
|
8
|
-
throw new Error("The workspace filesystem executor thread must be started by the worker runtime");
|
|
9
|
-
}
|
|
10
|
-
const port = parentPort;
|
|
11
|
-
function runRequest(request) {
|
|
12
|
-
if (!isWorkspaceFilesystemJobKind(request.kind)) {
|
|
13
|
-
return {
|
|
14
|
-
type: "failure",
|
|
15
|
-
id: request.id,
|
|
16
|
-
error: serializeWorkspaceFilesystemError(new Error(`Unknown workspace filesystem job kind: ${String(request.kind)}`))
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
const operation = workspaceFilesystemJobOperations[request.kind];
|
|
20
|
-
const previousEnvironment = process.env;
|
|
21
|
-
process.env = { ...request.environment };
|
|
22
|
-
try {
|
|
23
|
-
const result = operation(request.input, {
|
|
24
|
-
progress: (progress) => port.postMessage({ type: "progress", id: request.id, progress })
|
|
25
|
-
});
|
|
26
|
-
return { type: "result", id: request.id, result };
|
|
27
|
-
} catch (error) {
|
|
28
|
-
return { type: "failure", id: request.id, error: serializeWorkspaceFilesystemError(error) };
|
|
29
|
-
} finally {
|
|
30
|
-
process.env = previousEnvironment;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
port.on("message", (message) => {
|
|
34
|
-
if (!message || typeof message !== "object") return;
|
|
35
|
-
const request = message;
|
|
36
|
-
if (request.type !== "run" || typeof request.id !== "number") return;
|
|
37
|
-
port.postMessage(runRequest(request));
|
|
38
|
-
});
|
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { Worker } from "node:worker_threads";
|
|
3
|
-
import { workerGitProcessEnvironment } from "./git-process-environment.mjs";
|
|
4
|
-
import {
|
|
5
|
-
describeWorkspaceFilesystemJob,
|
|
6
|
-
restoreWorkspaceFilesystemError
|
|
7
|
-
} from "./workspace-filesystem-job-types.mjs";
|
|
8
|
-
const WORKSPACE_FILESYSTEM_EXECUTOR_MAX_QUEUED = 32;
|
|
9
|
-
const WORKSPACE_FILESYSTEM_EXECUTOR_QUEUE_TIMEOUT_MS = 5 * 6e4;
|
|
10
|
-
const WORKSPACE_FILESYSTEM_EXECUTOR_STALL_LOG_INTERVAL_MS = 3e4;
|
|
11
|
-
class WorkspaceFilesystemExecutorError extends Error {
|
|
12
|
-
name = "WorkspaceFilesystemExecutorError";
|
|
13
|
-
}
|
|
14
|
-
class WorkspaceFilesystemExecutorThreadExitedError extends WorkspaceFilesystemExecutorError {
|
|
15
|
-
constructor(exitCode, description, cause) {
|
|
16
|
-
super(
|
|
17
|
-
`Workspace filesystem executor thread exited${exitCode === null ? "" : ` with code ${exitCode}`} while running ${description}; the filesystem state is whatever a process crash would have left`,
|
|
18
|
-
cause === void 0 ? void 0 : { cause }
|
|
19
|
-
);
|
|
20
|
-
this.exitCode = exitCode;
|
|
21
|
-
this.description = description;
|
|
22
|
-
}
|
|
23
|
-
exitCode;
|
|
24
|
-
description;
|
|
25
|
-
}
|
|
26
|
-
class WorkspaceFilesystemExecutor {
|
|
27
|
-
threadModulePath;
|
|
28
|
-
log;
|
|
29
|
-
now;
|
|
30
|
-
maxQueued;
|
|
31
|
-
queueTimeoutMs;
|
|
32
|
-
stallLogIntervalMs;
|
|
33
|
-
worker = null;
|
|
34
|
-
queue = [];
|
|
35
|
-
running = null;
|
|
36
|
-
nextJobId = 1;
|
|
37
|
-
failed = null;
|
|
38
|
-
closed = false;
|
|
39
|
-
/** Invoked once when the executor fails closed (thread exit under a running job). */
|
|
40
|
-
onFailure;
|
|
41
|
-
constructor(options) {
|
|
42
|
-
this.threadModulePath = options.threadModulePath;
|
|
43
|
-
this.log = options.log ?? ((line) => process.stderr.write(`${line}
|
|
44
|
-
`));
|
|
45
|
-
this.now = options.now ?? (() => Date.now());
|
|
46
|
-
this.maxQueued = options.maxQueued ?? WORKSPACE_FILESYSTEM_EXECUTOR_MAX_QUEUED;
|
|
47
|
-
this.queueTimeoutMs = options.queueTimeoutMs ?? WORKSPACE_FILESYSTEM_EXECUTOR_QUEUE_TIMEOUT_MS;
|
|
48
|
-
this.stallLogIntervalMs = options.stallLogIntervalMs ?? WORKSPACE_FILESYSTEM_EXECUTOR_STALL_LOG_INTERVAL_MS;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Run one job to completion on the executor thread. Resolves with the
|
|
52
|
-
* job's result; rejects with the job's own error (properties preserved),
|
|
53
|
-
* with a queue-wait or capacity error when the job never started, or with
|
|
54
|
-
* WorkspaceFilesystemExecutorThreadExitedError when the thread died under it.
|
|
55
|
-
*/
|
|
56
|
-
run(kind, input, options = {}) {
|
|
57
|
-
const description = describeWorkspaceFilesystemJob(kind, input);
|
|
58
|
-
if (this.closed)
|
|
59
|
-
return Promise.reject(new WorkspaceFilesystemExecutorError(`Workspace filesystem executor is closed; refusing ${description}`));
|
|
60
|
-
if (this.failed) return Promise.reject(new WorkspaceFilesystemExecutorError(`${this.failed}; refusing ${description}`));
|
|
61
|
-
if (this.queue.length >= this.maxQueued) {
|
|
62
|
-
return Promise.reject(
|
|
63
|
-
new WorkspaceFilesystemExecutorError(
|
|
64
|
-
`Workspace filesystem executor queue is full (${this.queue.length} waiting behind ${this.describeRunning()}); refusing ${description}`
|
|
65
|
-
)
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
return new Promise((resolve, reject) => {
|
|
69
|
-
const job = {
|
|
70
|
-
id: this.nextJobId++,
|
|
71
|
-
kind,
|
|
72
|
-
input,
|
|
73
|
-
description,
|
|
74
|
-
onProgress: options.onProgress,
|
|
75
|
-
resolve: (result) => resolve(result),
|
|
76
|
-
reject,
|
|
77
|
-
queuedAtMs: this.now(),
|
|
78
|
-
queueTimer: void 0
|
|
79
|
-
};
|
|
80
|
-
this.queue.push(job);
|
|
81
|
-
if (this.running) {
|
|
82
|
-
job.queueTimer = setTimeout(() => this.expireQueued(job), this.queueTimeoutMs);
|
|
83
|
-
}
|
|
84
|
-
this.dispatch();
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
status() {
|
|
88
|
-
const running = this.running;
|
|
89
|
-
return {
|
|
90
|
-
running: running ? {
|
|
91
|
-
kind: running.kind,
|
|
92
|
-
description: running.description,
|
|
93
|
-
startedAtMs: running.startedAtMs,
|
|
94
|
-
ageMs: this.now() - running.startedAtMs
|
|
95
|
-
} : null,
|
|
96
|
-
queued: this.queue.length,
|
|
97
|
-
failed: this.failed
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Stop accepting jobs, fail everything still queued and ask the thread to
|
|
102
|
-
* stop. A running job settles when the thread actually exits; a thread
|
|
103
|
-
* blocked in the kernel only exits with the process, which is the point.
|
|
104
|
-
*/
|
|
105
|
-
close() {
|
|
106
|
-
if (this.closed) return;
|
|
107
|
-
this.closed = true;
|
|
108
|
-
for (const job of this.queue.splice(0)) {
|
|
109
|
-
if (job.queueTimer) clearTimeout(job.queueTimer);
|
|
110
|
-
job.reject(new WorkspaceFilesystemExecutorError(`Workspace filesystem executor is closed; ${job.description} did not start`));
|
|
111
|
-
}
|
|
112
|
-
const worker = this.worker;
|
|
113
|
-
if (worker && !this.running) {
|
|
114
|
-
this.worker = null;
|
|
115
|
-
void worker.terminate();
|
|
116
|
-
} else if (worker) {
|
|
117
|
-
void worker.terminate();
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
describeRunning() {
|
|
121
|
-
const running = this.running;
|
|
122
|
-
if (!running) return "an idle executor";
|
|
123
|
-
return `${running.description} (running for ${Math.round((this.now() - running.startedAtMs) / 1e3)}s)`;
|
|
124
|
-
}
|
|
125
|
-
expireQueued(job) {
|
|
126
|
-
const index = this.queue.indexOf(job);
|
|
127
|
-
if (index < 0) return;
|
|
128
|
-
this.queue.splice(index, 1);
|
|
129
|
-
job.queueTimer = void 0;
|
|
130
|
-
job.reject(
|
|
131
|
-
new WorkspaceFilesystemExecutorError(
|
|
132
|
-
`Workspace filesystem executor is blocked: ${this.describeRunning()} while ${job.description} waited ${Math.round((this.now() - job.queuedAtMs) / 1e3)}s for its turn; filesystem I/O may be stalled`
|
|
133
|
-
)
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
dispatch() {
|
|
137
|
-
if (this.running || this.closed || this.failed) return;
|
|
138
|
-
const job = this.queue.shift();
|
|
139
|
-
if (!job) {
|
|
140
|
-
this.worker?.unref();
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
if (job.queueTimer) {
|
|
144
|
-
clearTimeout(job.queueTimer);
|
|
145
|
-
job.queueTimer = void 0;
|
|
146
|
-
}
|
|
147
|
-
let worker;
|
|
148
|
-
try {
|
|
149
|
-
worker = this.ensureWorker();
|
|
150
|
-
} catch (error) {
|
|
151
|
-
job.reject(error instanceof Error ? error : new Error(String(error)));
|
|
152
|
-
this.dispatch();
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
const environment = {};
|
|
156
|
-
for (const [key, value] of Object.entries(workerGitProcessEnvironment(process.env))) if (value !== void 0) environment[key] = value;
|
|
157
|
-
const request = { type: "run", id: job.id, kind: job.kind, input: job.input, environment };
|
|
158
|
-
const startedAtMs = this.now();
|
|
159
|
-
const running = {
|
|
160
|
-
...job,
|
|
161
|
-
startedAtMs,
|
|
162
|
-
stallTimer: setInterval(() => {
|
|
163
|
-
this.log(
|
|
164
|
-
`[r5d-worker] workspace filesystem job ${running.kind} (${running.description}) has run for ${Math.round((this.now() - startedAtMs) / 1e3)}s; filesystem I/O may be stalled (${this.queue.length} job(s) queued behind it)`
|
|
165
|
-
);
|
|
166
|
-
}, this.stallLogIntervalMs)
|
|
167
|
-
};
|
|
168
|
-
running.stallTimer.unref();
|
|
169
|
-
this.running = running;
|
|
170
|
-
worker.ref();
|
|
171
|
-
try {
|
|
172
|
-
worker.postMessage(request);
|
|
173
|
-
} catch (error) {
|
|
174
|
-
this.settleRunning(running, () => running.reject(error instanceof Error ? error : new Error(String(error))));
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
settleRunning(job, settle) {
|
|
178
|
-
if (this.running !== job) return;
|
|
179
|
-
clearInterval(job.stallTimer);
|
|
180
|
-
this.running = null;
|
|
181
|
-
settle();
|
|
182
|
-
this.dispatch();
|
|
183
|
-
}
|
|
184
|
-
ensureWorker() {
|
|
185
|
-
if (this.worker) return this.worker;
|
|
186
|
-
const worker = new Worker(this.threadModulePath);
|
|
187
|
-
this.worker = worker;
|
|
188
|
-
worker.on("message", (message) => this.onReply(worker, message));
|
|
189
|
-
worker.on("error", (error) => {
|
|
190
|
-
this.log(`[r5d-worker] workspace filesystem executor thread error: ${error.stack ?? error.message}`);
|
|
191
|
-
this.lastThreadError = error;
|
|
192
|
-
});
|
|
193
|
-
worker.on("exit", (code) => this.onExit(worker, code));
|
|
194
|
-
worker.unref();
|
|
195
|
-
return worker;
|
|
196
|
-
}
|
|
197
|
-
lastThreadError;
|
|
198
|
-
onReply(worker, message) {
|
|
199
|
-
if (this.worker !== worker) return;
|
|
200
|
-
const running = this.running;
|
|
201
|
-
if (!running || !message || typeof message !== "object" || message.id !== running.id) return;
|
|
202
|
-
if (message.type === "progress") {
|
|
203
|
-
running.onProgress?.(message.progress);
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
if (message.type === "result") {
|
|
207
|
-
this.settleRunning(running, () => running.resolve(message.result));
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
if (message.type === "failure") {
|
|
211
|
-
this.settleRunning(running, () => running.reject(restoreWorkspaceFilesystemError(message.error)));
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
onExit(worker, code) {
|
|
215
|
-
if (this.worker !== worker) return;
|
|
216
|
-
this.worker = null;
|
|
217
|
-
const cause = this.lastThreadError;
|
|
218
|
-
this.lastThreadError = void 0;
|
|
219
|
-
const running = this.running;
|
|
220
|
-
if (!running) {
|
|
221
|
-
if (!this.closed) this.dispatch();
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
const failure = new WorkspaceFilesystemExecutorThreadExitedError(code, running.description, cause);
|
|
225
|
-
if (!this.closed) {
|
|
226
|
-
this.failed = `Workspace filesystem executor thread exited with code ${code} while running ${running.description}; the worker must restart and recover before it mutates the workspace again`;
|
|
227
|
-
this.log(`[r5d-worker] ${this.failed}`);
|
|
228
|
-
}
|
|
229
|
-
this.settleRunning(running, () => running.reject(failure));
|
|
230
|
-
for (const job of this.queue.splice(0)) {
|
|
231
|
-
if (job.queueTimer) clearTimeout(job.queueTimer);
|
|
232
|
-
job.reject(
|
|
233
|
-
new WorkspaceFilesystemExecutorError(
|
|
234
|
-
`${this.failed ?? "Workspace filesystem executor is closed"}; ${job.description} did not start`
|
|
235
|
-
)
|
|
236
|
-
);
|
|
237
|
-
}
|
|
238
|
-
if (!this.closed) this.onFailure?.(failure);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
function workspaceFilesystemExecutorThreadModulePath() {
|
|
242
|
-
return path.join(path.dirname(__filename), `workspace-filesystem-executor-thread${path.extname(__filename)}`);
|
|
243
|
-
}
|
|
244
|
-
let processExecutor = null;
|
|
245
|
-
let inlineRunner = null;
|
|
246
|
-
function workspaceFilesystemExecutor() {
|
|
247
|
-
if (inlineRunner) return inlineRunner;
|
|
248
|
-
processExecutor ??= new WorkspaceFilesystemExecutor({ threadModulePath: workspaceFilesystemExecutorThreadModulePath() });
|
|
249
|
-
return processExecutor;
|
|
250
|
-
}
|
|
251
|
-
function installWorkspaceFilesystemExecutorFailureHandler(handler) {
|
|
252
|
-
processExecutor ??= new WorkspaceFilesystemExecutor({ threadModulePath: workspaceFilesystemExecutorThreadModulePath() });
|
|
253
|
-
processExecutor.onFailure = handler;
|
|
254
|
-
}
|
|
255
|
-
const workspaceFilesystemExecutorTestHarness = {
|
|
256
|
-
async runJobsInline(body) {
|
|
257
|
-
const { workspaceFilesystemJobOperations } = await import("./workspace-filesystem-jobs.mjs");
|
|
258
|
-
const previous = inlineRunner;
|
|
259
|
-
inlineRunner = {
|
|
260
|
-
async run(kind, input, options = {}) {
|
|
261
|
-
await Promise.resolve();
|
|
262
|
-
const operation = workspaceFilesystemJobOperations[kind];
|
|
263
|
-
return operation(input, { progress: (progress) => options.onProgress?.(progress) });
|
|
264
|
-
}
|
|
265
|
-
};
|
|
266
|
-
try {
|
|
267
|
-
return await body();
|
|
268
|
-
} finally {
|
|
269
|
-
inlineRunner = previous;
|
|
270
|
-
}
|
|
271
|
-
},
|
|
272
|
-
processExecutor() {
|
|
273
|
-
return processExecutor;
|
|
274
|
-
}
|
|
275
|
-
};
|
|
276
|
-
export {
|
|
277
|
-
WORKSPACE_FILESYSTEM_EXECUTOR_MAX_QUEUED,
|
|
278
|
-
WORKSPACE_FILESYSTEM_EXECUTOR_QUEUE_TIMEOUT_MS,
|
|
279
|
-
WORKSPACE_FILESYSTEM_EXECUTOR_STALL_LOG_INTERVAL_MS,
|
|
280
|
-
WorkspaceFilesystemExecutor,
|
|
281
|
-
WorkspaceFilesystemExecutorError,
|
|
282
|
-
WorkspaceFilesystemExecutorThreadExitedError,
|
|
283
|
-
installWorkspaceFilesystemExecutorFailureHandler,
|
|
284
|
-
workspaceFilesystemExecutor,
|
|
285
|
-
workspaceFilesystemExecutorTestHarness,
|
|
286
|
-
workspaceFilesystemExecutorThreadModulePath
|
|
287
|
-
};
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
const WORKSPACE_FILESYSTEM_JOB_KINDS = [
|
|
2
|
-
"checkout_durability_recovery",
|
|
3
|
-
"hydration_recovery",
|
|
4
|
-
"hydration_recovery_inspect",
|
|
5
|
-
"hydration_preserve_interrupted",
|
|
6
|
-
"hydration_transaction",
|
|
7
|
-
"hydration_raw",
|
|
8
|
-
"checkout_transition_begin",
|
|
9
|
-
"checkout_transition_complete",
|
|
10
|
-
"outer_checkout_fsync",
|
|
11
|
-
"projection_merge",
|
|
12
|
-
"projection_mirror",
|
|
13
|
-
"projection_outer_apply",
|
|
14
|
-
"projection_receipt",
|
|
15
|
-
"project_snapshot_create",
|
|
16
|
-
"project_snapshot_apply",
|
|
17
|
-
"project_snapshot_persist",
|
|
18
|
-
"project_snapshot_rollback",
|
|
19
|
-
"project_snapshots_recover",
|
|
20
|
-
"project_branch_create",
|
|
21
|
-
"project_checkout_path_move"
|
|
22
|
-
];
|
|
23
|
-
function isWorkspaceFilesystemJobKind(value) {
|
|
24
|
-
return typeof value === "string" && WORKSPACE_FILESYSTEM_JOB_KINDS.includes(value);
|
|
25
|
-
}
|
|
26
|
-
function summarizeIds(ids) {
|
|
27
|
-
if (ids.length === 0) return "no mounts";
|
|
28
|
-
const shown = ids.slice(0, 3).join(", ");
|
|
29
|
-
return ids.length > 3 ? `${ids.length} mounts (${shown}, \u2026)` : `${ids.length === 1 ? "mount" : "mounts"} ${shown}`;
|
|
30
|
-
}
|
|
31
|
-
function describeWorkspaceFilesystemJob(kind, input) {
|
|
32
|
-
switch (kind) {
|
|
33
|
-
case "checkout_durability_recovery":
|
|
34
|
-
case "hydration_recovery":
|
|
35
|
-
case "hydration_recovery_inspect":
|
|
36
|
-
case "checkout_transition_begin":
|
|
37
|
-
case "checkout_transition_complete":
|
|
38
|
-
case "outer_checkout_fsync":
|
|
39
|
-
return `${kind.replaceAll("_", " ")} of ${input.workspacePath}`;
|
|
40
|
-
case "hydration_preserve_interrupted": {
|
|
41
|
-
const recovery = input;
|
|
42
|
-
return `preservation of hydration transaction ${recovery.expectedTransactionId} in ${recovery.workspacePath}`;
|
|
43
|
-
}
|
|
44
|
-
case "hydration_transaction": {
|
|
45
|
-
const hydration = input;
|
|
46
|
-
const merged = Object.keys(hydration.mergeBases ?? {}).length;
|
|
47
|
-
return `hydration of ${summarizeIds(hydration.hydrationMounts.map(({ id }) => id))}${merged > 0 ? ` (${merged} merge-hydrated)` : ""} (durability ${summarizeIds(hydration.advancedDurabilityMounts.map(({ id }) => id))})`;
|
|
48
|
-
}
|
|
49
|
-
case "hydration_raw":
|
|
50
|
-
return `pre-clone hydration of ${summarizeIds(input.mounts.map(({ id }) => id))}`;
|
|
51
|
-
case "projection_merge":
|
|
52
|
-
return `merge projection of mount ${input.mount.id}`;
|
|
53
|
-
case "projection_mirror":
|
|
54
|
-
return `projection of mount ${input.mount.id}`;
|
|
55
|
-
case "projection_outer_apply": {
|
|
56
|
-
const apply = input;
|
|
57
|
-
return `outer-tree apply (${apply.removeMounts.length} removal(s), ${apply.materialize.length} merged subtree(s), ${apply.restoreFromHead.length} deferred restore(s))`;
|
|
58
|
-
}
|
|
59
|
-
case "projection_receipt":
|
|
60
|
-
return `projection receipt for ${summarizeIds(input.fsyncMounts.map(({ id }) => id))}`;
|
|
61
|
-
case "project_snapshot_create":
|
|
62
|
-
return `checkout snapshot of ${input.projectRoot}`;
|
|
63
|
-
case "project_snapshot_apply":
|
|
64
|
-
return `checkout snapshot restore into ${input.mirrors.map(({ targetPath }) => targetPath).join(", ") || "no checkouts"}`;
|
|
65
|
-
case "project_snapshot_persist":
|
|
66
|
-
return `checkout durability of ${input.snapshot.manifest.projectRoot}`;
|
|
67
|
-
case "project_snapshot_rollback":
|
|
68
|
-
return `checkout snapshot rollback of ${input.snapshot.manifest.projectRoot}`;
|
|
69
|
-
case "project_snapshots_recover":
|
|
70
|
-
return `interrupted checkout snapshot recovery under ${input.temporaryRoot}`;
|
|
71
|
-
case "project_branch_create": {
|
|
72
|
-
const create = input;
|
|
73
|
-
return `branch creation ${create.branchName} from ${create.sourceBranchName} in ${create.projectRoot}`;
|
|
74
|
-
}
|
|
75
|
-
case "project_checkout_path_move": {
|
|
76
|
-
const move = input;
|
|
77
|
-
return `checkout path move ${move.oldProjectRoot} \u2192 ${move.newProjectRoot}`;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
function serializeWorkspaceFilesystemError(error, depth = 0) {
|
|
82
|
-
if (!(error instanceof Error)) return { name: "Error", message: String(error) };
|
|
83
|
-
const record = error;
|
|
84
|
-
const serialized = { name: error.name, message: error.message };
|
|
85
|
-
if (typeof error.stack === "string") serialized.stack = error.stack;
|
|
86
|
-
if (typeof record.code === "string") serialized.code = record.code;
|
|
87
|
-
if (record.branchMayExist === true) serialized.branchMayExist = true;
|
|
88
|
-
if (record.hydrationRecovery) serialized.hydrationRecovery = structuredClone(record.hydrationRecovery);
|
|
89
|
-
if (Array.isArray(record.cleanupFailures) && record.cleanupFailures.every((failure) => typeof failure === "string")) {
|
|
90
|
-
serialized.cleanupFailures = [...record.cleanupFailures];
|
|
91
|
-
}
|
|
92
|
-
if (depth < 4) {
|
|
93
|
-
if (Array.isArray(record.errors)) serialized.errors = record.errors.map((inner) => serializeWorkspaceFilesystemError(inner, depth + 1));
|
|
94
|
-
if (record.cause !== void 0) serialized.cause = serializeWorkspaceFilesystemError(record.cause, depth + 1);
|
|
95
|
-
}
|
|
96
|
-
return serialized;
|
|
97
|
-
}
|
|
98
|
-
function restoreWorkspaceFilesystemError(serialized) {
|
|
99
|
-
const cause = serialized.cause ? restoreWorkspaceFilesystemError(serialized.cause) : void 0;
|
|
100
|
-
const options = cause ? { cause } : void 0;
|
|
101
|
-
const error = serialized.errors ? new AggregateError(serialized.errors.map(restoreWorkspaceFilesystemError), serialized.message, options) : new Error(serialized.message, options);
|
|
102
|
-
error.name = serialized.name;
|
|
103
|
-
if (serialized.stack) error.stack = serialized.stack;
|
|
104
|
-
if (serialized.code !== void 0) error.code = serialized.code;
|
|
105
|
-
if (serialized.branchMayExist) error.branchMayExist = true;
|
|
106
|
-
if (serialized.cleanupFailures) error.cleanupFailures = [...serialized.cleanupFailures];
|
|
107
|
-
if (serialized.hydrationRecovery) error.hydrationRecovery = structuredClone(serialized.hydrationRecovery);
|
|
108
|
-
return error;
|
|
109
|
-
}
|
|
110
|
-
export {
|
|
111
|
-
WORKSPACE_FILESYSTEM_JOB_KINDS,
|
|
112
|
-
describeWorkspaceFilesystemJob,
|
|
113
|
-
isWorkspaceFilesystemJobKind,
|
|
114
|
-
restoreWorkspaceFilesystemError,
|
|
115
|
-
serializeWorkspaceFilesystemError
|
|
116
|
-
};
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createLinkedProjectBranch,
|
|
3
|
-
recoverStaleProjectWorktreeSnapshots,
|
|
4
|
-
runProjectSnapshotApplyJob,
|
|
5
|
-
runProjectSnapshotCreateJob,
|
|
6
|
-
runProjectSnapshotPersistJob,
|
|
7
|
-
runProjectSnapshotRollbackJob
|
|
8
|
-
} from "./project-worktrees.mjs";
|
|
9
|
-
import {
|
|
10
|
-
runCheckoutDurabilityRecoveryJob,
|
|
11
|
-
runCheckoutTransitionBeginJob,
|
|
12
|
-
runCheckoutTransitionCompleteJob,
|
|
13
|
-
runHydrationRawJob,
|
|
14
|
-
runHydrationRecoveryJob,
|
|
15
|
-
runHydrationRecoveryInspectJob,
|
|
16
|
-
runHydrationPreserveInterruptedJob,
|
|
17
|
-
runHydrationTransactionJob,
|
|
18
|
-
runOuterCheckoutFsyncJob,
|
|
19
|
-
runProjectionMirrorJob,
|
|
20
|
-
runProjectionOuterApplyJob,
|
|
21
|
-
runProjectionReceiptJob
|
|
22
|
-
} from "./workspace-git-sync.mjs";
|
|
23
|
-
import { mergeWorkspaceProjectionMount } from "./workspace-merge-projection.mjs";
|
|
24
|
-
import { preserveProjectCheckoutPathMove } from "./workspace-path-move.mjs";
|
|
25
|
-
const workspaceFilesystemJobOperations = {
|
|
26
|
-
checkout_durability_recovery: (input) => runCheckoutDurabilityRecoveryJob(input),
|
|
27
|
-
hydration_recovery: (input) => runHydrationRecoveryJob(input),
|
|
28
|
-
hydration_recovery_inspect: (input) => runHydrationRecoveryInspectJob(input),
|
|
29
|
-
hydration_preserve_interrupted: (input) => runHydrationPreserveInterruptedJob(input),
|
|
30
|
-
hydration_transaction: (input) => runHydrationTransactionJob(input),
|
|
31
|
-
hydration_raw: (input) => runHydrationRawJob(input),
|
|
32
|
-
checkout_transition_begin: (input) => runCheckoutTransitionBeginJob(input),
|
|
33
|
-
checkout_transition_complete: (input) => runCheckoutTransitionCompleteJob(input),
|
|
34
|
-
outer_checkout_fsync: (input) => runOuterCheckoutFsyncJob(input),
|
|
35
|
-
projection_merge: (input) => mergeWorkspaceProjectionMount(input),
|
|
36
|
-
projection_mirror: (input) => runProjectionMirrorJob(input),
|
|
37
|
-
projection_outer_apply: (input) => runProjectionOuterApplyJob(input),
|
|
38
|
-
projection_receipt: (input) => runProjectionReceiptJob(input),
|
|
39
|
-
project_snapshot_create: (input, context) => runProjectSnapshotCreateJob(input, context),
|
|
40
|
-
project_snapshot_apply: (input) => runProjectSnapshotApplyJob(input),
|
|
41
|
-
project_snapshot_persist: (input) => runProjectSnapshotPersistJob(input),
|
|
42
|
-
project_snapshot_rollback: (input) => runProjectSnapshotRollbackJob(input),
|
|
43
|
-
project_snapshots_recover: (input, context) => recoverStaleProjectWorktreeSnapshots({
|
|
44
|
-
projectsRoot: input.projectsRoot,
|
|
45
|
-
temporaryRoot: input.temporaryRoot,
|
|
46
|
-
currentProcessId: input.currentProcessId,
|
|
47
|
-
currentOwnerSessionId: input.currentOwnerSessionId,
|
|
48
|
-
onProgress: context.progress
|
|
49
|
-
}),
|
|
50
|
-
project_branch_create: (input) => createLinkedProjectBranch(input),
|
|
51
|
-
project_checkout_path_move: (input) => preserveProjectCheckoutPathMove(input)
|
|
52
|
-
};
|
|
53
|
-
export {
|
|
54
|
-
workspaceFilesystemJobOperations
|
|
55
|
-
};
|