@ricsam/r5d-worker 0.0.83 → 0.0.87
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/cjs/main.cjs +180 -106
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/project-worktrees.cjs +183 -104
- package/dist/cjs/workspace-automatic-sync-policy.cjs +12 -2
- package/dist/cjs/workspace-command-sync-policy.cjs +21 -0
- package/dist/cjs/workspace-git-sync.cjs +501 -191
- package/dist/mjs/main.mjs +185 -107
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/project-worktrees.mjs +183 -104
- package/dist/mjs/workspace-automatic-sync-policy.mjs +9 -1
- package/dist/mjs/workspace-command-sync-policy.mjs +20 -0
- package/dist/mjs/workspace-git-sync.mjs +500 -191
- package/dist/types/main.d.ts +19 -2
- package/dist/types/project-worktrees.d.ts +12 -12
- package/dist/types/workspace-automatic-sync-policy.d.ts +24 -4
- package/dist/types/workspace-command-sync-policy.d.ts +7 -0
- package/dist/types/workspace-git-sync.d.ts +17 -9
- package/package.json +1 -1
package/dist/mjs/main.mjs
CHANGED
|
@@ -28,11 +28,14 @@ import {
|
|
|
28
28
|
PENDING_CREATED_BRANCH_AUTOMATIC_SYNC_GRACE_MS,
|
|
29
29
|
pendingCreatedBranchAutomaticSyncDeferral,
|
|
30
30
|
pendingCreatedBranchKey,
|
|
31
|
-
projectBranchHasActiveWorkspaceTarget
|
|
31
|
+
projectBranchHasActiveWorkspaceTarget,
|
|
32
|
+
projectBranchMountBusyDuringExclusiveSync,
|
|
33
|
+
workspacePlansMountBusyDuringExclusiveSync
|
|
32
34
|
} from "./workspace-automatic-sync-policy.mjs";
|
|
33
35
|
import {
|
|
34
36
|
acquireWorkspaceCommandMutation,
|
|
35
37
|
reserveWorkspaceCommandAfterCurrentSync,
|
|
38
|
+
runReservedWorkspaceCommand,
|
|
36
39
|
runWorkspaceCommand
|
|
37
40
|
} from "./workspace-command-sync-policy.mjs";
|
|
38
41
|
import { WorkspaceMutationGate } from "./workspace-mutation-gate.mjs";
|
|
@@ -86,6 +89,7 @@ import {
|
|
|
86
89
|
resetWorkspaceGit,
|
|
87
90
|
synchronizeWorkspaceGit,
|
|
88
91
|
workspaceGitHydrationIsCurrent,
|
|
92
|
+
workspaceGitMountsForRemediation,
|
|
89
93
|
WorkspaceRemediationAncestryError
|
|
90
94
|
} from "./workspace-git-sync.mjs";
|
|
91
95
|
class ProjectWorkspaceConfigurationDeferredError extends Error {
|
|
@@ -843,6 +847,33 @@ function tryGit(args, options = {}) {
|
|
|
843
847
|
return false;
|
|
844
848
|
}
|
|
845
849
|
}
|
|
850
|
+
async function runGitAsync(args, options = {}) {
|
|
851
|
+
const command = workerGitCommand.commandArgs(args);
|
|
852
|
+
const subprocess = Bun.spawn(command, {
|
|
853
|
+
cwd: options.cwd,
|
|
854
|
+
stdin: "ignore",
|
|
855
|
+
stdout: "pipe",
|
|
856
|
+
stderr: "pipe",
|
|
857
|
+
env: workerGitProcessEnvironment()
|
|
858
|
+
});
|
|
859
|
+
const [stdout, stderr, exitCode] = await Promise.all([
|
|
860
|
+
new Response(subprocess.stdout).text(),
|
|
861
|
+
new Response(subprocess.stderr).text(),
|
|
862
|
+
subprocess.exited
|
|
863
|
+
]);
|
|
864
|
+
if (exitCode !== 0) {
|
|
865
|
+
throw new Error(`git ${args.join(" ")} failed: ${stderr.trim() || stdout.trim() || `exit ${exitCode}`}`);
|
|
866
|
+
}
|
|
867
|
+
return stdout.trim();
|
|
868
|
+
}
|
|
869
|
+
async function tryGitAsync(args, options = {}) {
|
|
870
|
+
try {
|
|
871
|
+
await runGitAsync(args, options);
|
|
872
|
+
return true;
|
|
873
|
+
} catch {
|
|
874
|
+
return false;
|
|
875
|
+
}
|
|
876
|
+
}
|
|
846
877
|
function getGitBlobHashForContent(content) {
|
|
847
878
|
const buffer = typeof content === "string" ? Buffer.from(content, "utf8") : content;
|
|
848
879
|
return createHash("sha1").update(`blob ${buffer.length}\0`).update(buffer).digest("hex");
|
|
@@ -1539,10 +1570,20 @@ function workspaceConfigurationIncidentDeferral(input) {
|
|
|
1539
1570
|
return { incidentId };
|
|
1540
1571
|
}
|
|
1541
1572
|
function workspaceIncidentTerminalClearDisposition(input) {
|
|
1542
|
-
if (!input.deferredConfiguration) return "
|
|
1543
|
-
|
|
1573
|
+
if (!input.deferredConfiguration) return "await_server_refresh";
|
|
1574
|
+
if (input.deferredConfiguration.incidentId !== input.clearedIncidentId) return "reconnect_for_refresh";
|
|
1544
1575
|
return input.deferredConfiguration.serverRefreshExpected ? "await_server_refresh" : "reconnect_for_refresh";
|
|
1545
1576
|
}
|
|
1577
|
+
function workspaceIncidentTerminalRefreshFence(input) {
|
|
1578
|
+
const disposition = workspaceIncidentTerminalClearDisposition(input);
|
|
1579
|
+
return {
|
|
1580
|
+
disposition,
|
|
1581
|
+
deferredConfiguration: input.deferredConfiguration ?? { incidentId: input.clearedIncidentId, serverRefreshExpected: true }
|
|
1582
|
+
};
|
|
1583
|
+
}
|
|
1584
|
+
function workspaceAutomaticSyncIsAdmitted(input) {
|
|
1585
|
+
return input.workspaceConfigured && input.activeIncidentId === null && input.deferredConfiguration === null;
|
|
1586
|
+
}
|
|
1546
1587
|
function deferredWorkspaceTargetIsAllowed(deferredConfiguration, activeIncidentId, target) {
|
|
1547
1588
|
const canonicalTarget = target.type === "workspace" && target.rootProfile === "canonical_sync";
|
|
1548
1589
|
if (deferredConfiguration) return activeIncidentId === deferredConfiguration.incidentId && canonicalTarget;
|
|
@@ -1564,6 +1605,9 @@ function deferredCredentialTransitionMustWait(input) {
|
|
|
1564
1605
|
function workspaceConfigurationIncidentSnapshotIsCurrent(capturedIncidentId, activeIncidentId) {
|
|
1565
1606
|
return capturedIncidentId === null ? activeIncidentId === null : activeIncidentId === null || activeIncidentId === capturedIncidentId;
|
|
1566
1607
|
}
|
|
1608
|
+
function workspaceConfigurationResetToCanonicalIsAllowed(requested, incidentId) {
|
|
1609
|
+
return requested === true && incidentId === null;
|
|
1610
|
+
}
|
|
1567
1611
|
function deferredWorkspaceRefreshWatchdogIsCurrent(input) {
|
|
1568
1612
|
return input.deferredConfiguration?.incidentId === input.capturedIncidentId && input.activeIncidentId === null;
|
|
1569
1613
|
}
|
|
@@ -1636,12 +1680,15 @@ const workerGitSecurityTestHarness = {
|
|
|
1636
1680
|
fenceUnsafeWorkspaceSyncFailure,
|
|
1637
1681
|
workspaceConfigurationIncidentDeferral,
|
|
1638
1682
|
workspaceIncidentTerminalClearDisposition,
|
|
1683
|
+
workspaceIncidentTerminalRefreshFence,
|
|
1684
|
+
workspaceAutomaticSyncIsAdmitted,
|
|
1639
1685
|
deferredWorkspaceTargetIsAllowed,
|
|
1640
1686
|
deferredWorkspaceSyncTriggerIsAllowed,
|
|
1641
1687
|
workspaceOperationsAreFenced,
|
|
1642
1688
|
workspaceCommandTransportIsAllowed,
|
|
1643
1689
|
deferredCredentialTransitionMustWait,
|
|
1644
1690
|
workspaceConfigurationIncidentSnapshotIsCurrent,
|
|
1691
|
+
workspaceConfigurationResetToCanonicalIsAllowed,
|
|
1645
1692
|
deferredWorkspaceRefreshWatchdogIsCurrent,
|
|
1646
1693
|
incidentDeferredProjectCheckouts,
|
|
1647
1694
|
deferredIncidentWorkspaceConfigurationResult,
|
|
@@ -3402,6 +3449,11 @@ async function startWorker(options) {
|
|
|
3402
3449
|
let cliUpdateInProgress = false;
|
|
3403
3450
|
let reloadAfterClose = false;
|
|
3404
3451
|
let shutdownAfterClose = false;
|
|
3452
|
+
const automaticWorkspaceSyncIsCurrentlyAdmitted = () => workspaceAutomaticSyncIsAdmitted({
|
|
3453
|
+
workspaceConfigured,
|
|
3454
|
+
activeIncidentId: activeWorkspaceIncidentId,
|
|
3455
|
+
deferredConfiguration: deferredWorkspaceConfiguration
|
|
3456
|
+
});
|
|
3405
3457
|
const bearerAuthHeader = `Authorization: Bearer ${token}`;
|
|
3406
3458
|
const workerCredentialUsername = credentialUsernameForAuthHeader(bearerAuthHeader);
|
|
3407
3459
|
const projectBranchKey = (projectId, branchName) => `${projectId}\0${branchName}`;
|
|
@@ -3683,6 +3735,17 @@ async function startWorker(options) {
|
|
|
3683
3735
|
const activeTargets = activeWorkspaceMutationTargets();
|
|
3684
3736
|
return projectConfigById.get(projectId)?.executionDisabled === true || hasProjectWorktree(branchPath) && projectWorktreeOperationInProgress(branchPath) || canonicalWorkspaceMutationIsActive(activeTargets) || projectBranchHasActiveWorkspaceTarget(projectId, branchName, activeTargets);
|
|
3685
3737
|
};
|
|
3738
|
+
const projectBranchMountExclusiveSyncBusy = (projectId, branchName, branchPath) => {
|
|
3739
|
+
const activeTargets = activeWorkspaceMutationTargets();
|
|
3740
|
+
return projectBranchMountBusyDuringExclusiveSync({
|
|
3741
|
+
projectId,
|
|
3742
|
+
branchName,
|
|
3743
|
+
executionDisabled: projectConfigById.get(projectId)?.executionDisabled === true,
|
|
3744
|
+
worktreeOperationInProgress: hasProjectWorktree(branchPath) && projectWorktreeOperationInProgress(branchPath),
|
|
3745
|
+
retainedCanonicalProcessGroup: canonicalWorkspaceMutationIsActive([...credentialBearingProcessGroupTargets.values()]),
|
|
3746
|
+
activeTargets
|
|
3747
|
+
});
|
|
3748
|
+
};
|
|
3686
3749
|
const projectBranchMountBusy = (projectId, branchName, branchPath) => !readyProjectIds.has(projectId) || projectBranchMountActivityBusy(projectId, branchName, branchPath);
|
|
3687
3750
|
const buildWorkspaceMounts = (projects = projectConfigById.values()) => {
|
|
3688
3751
|
const mounts = [];
|
|
@@ -3715,7 +3778,7 @@ async function startWorker(options) {
|
|
|
3715
3778
|
preserveLocalOnHydrationBasisChange: preservesCheckoutPathMove,
|
|
3716
3779
|
busy: () => projectBranchMountBusy(project.projectId, branch.branchName, branchPath),
|
|
3717
3780
|
mutationToken: () => projectWorkspaceMutationToken(project.projectId, branch.branchName),
|
|
3718
|
-
busyForRecovery: () =>
|
|
3781
|
+
busyForRecovery: () => projectBranchMountExclusiveSyncBusy(project.projectId, branch.branchName, branchPath)
|
|
3719
3782
|
});
|
|
3720
3783
|
mounts.push({
|
|
3721
3784
|
id: projectPlanMountId(project.projectId, branch.branchName),
|
|
@@ -3729,7 +3792,7 @@ async function startWorker(options) {
|
|
|
3729
3792
|
preserveLocalOnHydrationBasisChange: preservesCheckoutPathMove,
|
|
3730
3793
|
busy: () => projectBranchMountBusy(project.projectId, branch.branchName, branchPath),
|
|
3731
3794
|
mutationToken: () => projectWorkspaceMutationToken(project.projectId, branch.branchName),
|
|
3732
|
-
busyForRecovery: () =>
|
|
3795
|
+
busyForRecovery: () => projectBranchMountExclusiveSyncBusy(project.projectId, branch.branchName, branchPath)
|
|
3733
3796
|
});
|
|
3734
3797
|
}
|
|
3735
3798
|
void projectRoot;
|
|
@@ -3752,7 +3815,10 @@ async function startWorker(options) {
|
|
|
3752
3815
|
mutationToken: () => String(visibleWorkspaceMutationEpoch),
|
|
3753
3816
|
busyForRecovery: () => {
|
|
3754
3817
|
const activeTargets = activeWorkspaceMutationTargets();
|
|
3755
|
-
return
|
|
3818
|
+
return workspacePlansMountBusyDuringExclusiveSync(
|
|
3819
|
+
activeTargets,
|
|
3820
|
+
canonicalWorkspaceMutationIsActive([...credentialBearingProcessGroupTargets.values()])
|
|
3821
|
+
);
|
|
3756
3822
|
}
|
|
3757
3823
|
});
|
|
3758
3824
|
for (const deletion of pendingMirrorDeletes.values()) {
|
|
@@ -3779,10 +3845,14 @@ async function startWorker(options) {
|
|
|
3779
3845
|
}
|
|
3780
3846
|
return mounts;
|
|
3781
3847
|
};
|
|
3782
|
-
const workspaceLocalHead = () =>
|
|
3783
|
-
|
|
3848
|
+
const workspaceLocalHead = async () => {
|
|
3849
|
+
if (!fs.existsSync(path.join(workspaceShadowRoot, ".git"))) return null;
|
|
3850
|
+
if (!await tryGitAsync(["rev-parse", "--verify", "HEAD"], { cwd: workspaceShadowRoot })) return null;
|
|
3851
|
+
return runGitAsync(["rev-parse", "HEAD"], { cwd: workspaceShadowRoot });
|
|
3852
|
+
};
|
|
3853
|
+
const workspaceGitStatus = async () => {
|
|
3784
3854
|
try {
|
|
3785
|
-
return
|
|
3855
|
+
return await runGitAsync(["status", "--porcelain"], { cwd: workspaceShadowRoot });
|
|
3786
3856
|
} catch {
|
|
3787
3857
|
return "";
|
|
3788
3858
|
}
|
|
@@ -3795,7 +3865,7 @@ async function startWorker(options) {
|
|
|
3795
3865
|
})
|
|
3796
3866
|
)
|
|
3797
3867
|
].sort();
|
|
3798
|
-
const ensureConfiguredProjects = () => {
|
|
3868
|
+
const ensureConfiguredProjects = async () => {
|
|
3799
3869
|
for (const project of projectConfigById.values()) {
|
|
3800
3870
|
validateProjectId(project.projectId);
|
|
3801
3871
|
assertRepositoryTransitionState(project);
|
|
@@ -3832,7 +3902,7 @@ async function startWorker(options) {
|
|
|
3832
3902
|
}
|
|
3833
3903
|
try {
|
|
3834
3904
|
const connection = projectConnection(project);
|
|
3835
|
-
const states = ensureProjectWorktrees({
|
|
3905
|
+
const states = await ensureProjectWorktrees({
|
|
3836
3906
|
projectRoot,
|
|
3837
3907
|
snapshotRoot: projectWorktreeSnapshotsRoot,
|
|
3838
3908
|
primaryBranchName: primaryProjectBranch(project),
|
|
@@ -3881,13 +3951,13 @@ async function startWorker(options) {
|
|
|
3881
3951
|
}
|
|
3882
3952
|
}
|
|
3883
3953
|
};
|
|
3884
|
-
const collectAheadOfOriginBranches = () => {
|
|
3954
|
+
const collectAheadOfOriginBranches = async () => {
|
|
3885
3955
|
const aheadBranches = [];
|
|
3886
3956
|
for (const project of projectConfigById.values()) {
|
|
3887
3957
|
if (project.executionDisabled || !readyProjectIds.has(project.projectId) || project.branches.length === 0) continue;
|
|
3888
3958
|
const connection = projectConnection(project);
|
|
3889
3959
|
const primaryPath = configuredProjectBranchPath(projectsRoot, project, primaryProjectBranch(project));
|
|
3890
|
-
if (!
|
|
3960
|
+
if (!await tryGitAsync(
|
|
3891
3961
|
[
|
|
3892
3962
|
...gitTransportSecurityArgs(connection.originUrl, connection.credentialHelper, connection.originCredentialUsername),
|
|
3893
3963
|
"fetch",
|
|
@@ -3911,11 +3981,11 @@ async function startWorker(options) {
|
|
|
3911
3981
|
primaryBranchName: primaryProjectBranch(project),
|
|
3912
3982
|
defaultBranch: project.defaultBranch
|
|
3913
3983
|
})}`;
|
|
3914
|
-
if (
|
|
3915
|
-
const counts =
|
|
3984
|
+
if (await tryGitAsync(["show-ref", "--verify", "--quiet", originRef], { cwd: branchPath })) {
|
|
3985
|
+
const counts = (await runGitAsync(["rev-list", "--left-right", "--count", `${originRef}...HEAD`], { cwd: branchPath })).split(/\s+/).map(Number);
|
|
3916
3986
|
ahead = Number.isSafeInteger(counts[1]) ? counts[1] : 0;
|
|
3917
|
-
} else if (
|
|
3918
|
-
const count = Number(
|
|
3987
|
+
} else if (await tryGitAsync(["cat-file", "-e", `${branch.baseCommitHash}^{commit}`], { cwd: branchPath })) {
|
|
3988
|
+
const count = Number(await runGitAsync(["rev-list", "--count", `${branch.baseCommitHash}..HEAD`], { cwd: branchPath }));
|
|
3919
3989
|
ahead = Number.isSafeInteger(count) ? count : 0;
|
|
3920
3990
|
}
|
|
3921
3991
|
if (ahead > 0) aheadBranches.push({ projectId: project.projectId, branchName: branch.branchName, ahead });
|
|
@@ -3931,19 +4001,19 @@ async function startWorker(options) {
|
|
|
3931
4001
|
(left, right) => left.projectId.localeCompare(right.projectId) || left.branchName.localeCompare(right.branchName)
|
|
3932
4002
|
);
|
|
3933
4003
|
};
|
|
3934
|
-
const captureProjectHeadsForWorkspacePublication = () => {
|
|
4004
|
+
const captureProjectHeadsForWorkspacePublication = async () => {
|
|
3935
4005
|
const heads = /* @__PURE__ */ new Map();
|
|
3936
4006
|
for (const project of projectConfigById.values()) {
|
|
3937
4007
|
if (!readyProjectIds.has(project.projectId)) continue;
|
|
3938
4008
|
for (const branch of project.branches) {
|
|
3939
4009
|
const branchPath = configuredProjectBranchPath(projectsRoot, project, branch.branchName);
|
|
3940
4010
|
if (!hasProjectWorktree(branchPath)) continue;
|
|
3941
|
-
heads.set(projectMountId(project.projectId, branch.branchName),
|
|
4011
|
+
heads.set(projectMountId(project.projectId, branch.branchName), await runGitAsync(["rev-parse", "HEAD"], { cwd: branchPath }));
|
|
3942
4012
|
}
|
|
3943
4013
|
}
|
|
3944
4014
|
return heads;
|
|
3945
4015
|
};
|
|
3946
|
-
const pushChangedProjectHeads = (activeMountIds, publishedHead, publicationHeads, suppressedMountIds = /* @__PURE__ */ new Set()) => {
|
|
4016
|
+
const pushChangedProjectHeads = async (activeMountIds, publishedHead, publicationHeads, suppressedMountIds = /* @__PURE__ */ new Set()) => {
|
|
3947
4017
|
const active = new Set(activeMountIds);
|
|
3948
4018
|
for (const project of projectConfigById.values()) {
|
|
3949
4019
|
if (!readyProjectIds.has(project.projectId) || !repositoryMirrorWritesAllowed(project)) continue;
|
|
@@ -3959,7 +4029,7 @@ async function startWorker(options) {
|
|
|
3959
4029
|
}
|
|
3960
4030
|
if (changed.size === 0) continue;
|
|
3961
4031
|
const connection = projectConnection(project);
|
|
3962
|
-
const results = pushProjectMirrorHeads({
|
|
4032
|
+
const results = await pushProjectMirrorHeads({
|
|
3963
4033
|
projectRoot: configuredProjectRoot(projectsRoot, project),
|
|
3964
4034
|
branchNames: project.branches.map(({ branchName }) => branchName),
|
|
3965
4035
|
mirrorUrl: connection.mirrorUrl,
|
|
@@ -3990,7 +4060,7 @@ async function startWorker(options) {
|
|
|
3990
4060
|
if (!active.has(deletion.id)) continue;
|
|
3991
4061
|
if (!repositoryMirrorWritesAllowed(projectConfigById.get(deletion.projectId))) continue;
|
|
3992
4062
|
if (!deletion.projectDeleted) {
|
|
3993
|
-
deleteProjectMirrorBranch({
|
|
4063
|
+
await deleteProjectMirrorBranch({
|
|
3994
4064
|
gitDirectory: deletion.gitDirectory,
|
|
3995
4065
|
branchName: deletion.branchName,
|
|
3996
4066
|
mirrorUrl: deletion.mirrorUrl,
|
|
@@ -4011,7 +4081,7 @@ async function startWorker(options) {
|
|
|
4011
4081
|
lastObservedProjectHeads.delete(key);
|
|
4012
4082
|
}
|
|
4013
4083
|
};
|
|
4014
|
-
const observeProjectHeadsBeforeOuterWorkspace = (input) => {
|
|
4084
|
+
const observeProjectHeadsBeforeOuterWorkspace = async (input) => {
|
|
4015
4085
|
const bundles = [];
|
|
4016
4086
|
for (const project of projectConfigById.values()) {
|
|
4017
4087
|
if (project.executionDisabled || !readyProjectIds.has(project.projectId) || project.branches.length === 0) continue;
|
|
@@ -4023,7 +4093,7 @@ async function startWorker(options) {
|
|
|
4023
4093
|
projectId: project.projectId,
|
|
4024
4094
|
projectRoot,
|
|
4025
4095
|
primaryBranchName,
|
|
4026
|
-
observations: observeProjectMirrorHeads({
|
|
4096
|
+
observations: await observeProjectMirrorHeads({
|
|
4027
4097
|
projectRoot,
|
|
4028
4098
|
primaryBranchName,
|
|
4029
4099
|
branchNames: project.branches.map(({ branchName }) => branchName),
|
|
@@ -4043,7 +4113,7 @@ async function startWorker(options) {
|
|
|
4043
4113
|
}
|
|
4044
4114
|
return bundles;
|
|
4045
4115
|
};
|
|
4046
|
-
const applyObservedProjectHeadsAfterInboundWorkspace = (bundles, activeMountIds, requireObservedHeads) => {
|
|
4116
|
+
const applyObservedProjectHeadsAfterInboundWorkspace = async (bundles, activeMountIds, requireObservedHeads) => {
|
|
4047
4117
|
const active = new Set(activeMountIds);
|
|
4048
4118
|
for (const bundle of bundles) {
|
|
4049
4119
|
const project = projectConfigById.get(bundle.projectId);
|
|
@@ -4051,7 +4121,7 @@ async function startWorker(options) {
|
|
|
4051
4121
|
const observations = bundle.observations.filter(({ branchName }) => active.has(projectMountId(project.projectId, branchName)));
|
|
4052
4122
|
if (observations.length === 0) continue;
|
|
4053
4123
|
try {
|
|
4054
|
-
const refreshed = applyObservedProjectMirrorHeads({
|
|
4124
|
+
const refreshed = await applyObservedProjectMirrorHeads({
|
|
4055
4125
|
projectRoot: bundle.projectRoot,
|
|
4056
4126
|
primaryBranchName: bundle.primaryBranchName,
|
|
4057
4127
|
observations,
|
|
@@ -4061,7 +4131,7 @@ async function startWorker(options) {
|
|
|
4061
4131
|
for (const observation of observations) {
|
|
4062
4132
|
if (!observation.shouldMove || !observation.mirrorHead) continue;
|
|
4063
4133
|
const checkoutPath = configuredProjectBranchPath(projectsRoot, project, observation.branchName);
|
|
4064
|
-
const currentHead =
|
|
4134
|
+
const currentHead = await runGitAsync(["rev-parse", "HEAD"], { cwd: checkoutPath });
|
|
4065
4135
|
if (currentHead !== observation.mirrorHead) {
|
|
4066
4136
|
throw new Error(
|
|
4067
4137
|
`Project ${project.projectId}/${observation.branchName} did not apply observed hidden mirror head ${observation.mirrorHead}`
|
|
@@ -4084,7 +4154,7 @@ async function startWorker(options) {
|
|
|
4084
4154
|
}
|
|
4085
4155
|
}
|
|
4086
4156
|
};
|
|
4087
|
-
const mapWorkspaceGitResult = (attemptId, trigger, result) => {
|
|
4157
|
+
const mapWorkspaceGitResult = async (attemptId, trigger, result) => {
|
|
4088
4158
|
const activeProjectBranchPublications = activeProjectBranchPublicationEvidence([...projectConfigById.values()], result.activeMountIds);
|
|
4089
4159
|
return {
|
|
4090
4160
|
type: "workspace_sync",
|
|
@@ -4097,7 +4167,7 @@ async function startWorker(options) {
|
|
|
4097
4167
|
...result.publishedHead ? { publishedHead: result.publishedHead } : {},
|
|
4098
4168
|
rebaseCount: result.rebaseCount,
|
|
4099
4169
|
diffSizeBytes: result.diffSizeBytes,
|
|
4100
|
-
gitStatus: workspaceGitStatus(),
|
|
4170
|
+
gitStatus: await workspaceGitStatus(),
|
|
4101
4171
|
affectedProjects: affectedProjects(result.affectedPaths),
|
|
4102
4172
|
affectedPaths: result.affectedPaths,
|
|
4103
4173
|
activeMountIds: result.activeMountIds,
|
|
@@ -4112,48 +4182,51 @@ async function startWorker(options) {
|
|
|
4112
4182
|
...result.error ? { error: result.error } : {}
|
|
4113
4183
|
};
|
|
4114
4184
|
};
|
|
4115
|
-
const failedWorkspaceSyncResult = (attemptId, trigger, error) =>
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4185
|
+
const failedWorkspaceSyncResult = async (attemptId, trigger, error) => {
|
|
4186
|
+
const localHead = await workspaceLocalHead();
|
|
4187
|
+
return {
|
|
4188
|
+
type: "workspace_sync",
|
|
4189
|
+
attemptId,
|
|
4190
|
+
workerLabel: label,
|
|
4191
|
+
trigger,
|
|
4192
|
+
outcome: "failed",
|
|
4193
|
+
startingHead: localHead,
|
|
4194
|
+
...localHead ? { localHead } : {},
|
|
4195
|
+
rebaseCount: 0,
|
|
4196
|
+
diffSizeBytes: 0,
|
|
4197
|
+
gitStatus: await workspaceGitStatus(),
|
|
4198
|
+
affectedProjects: [],
|
|
4199
|
+
affectedPaths: [],
|
|
4200
|
+
discardedPaths: [],
|
|
4201
|
+
localChangesDiscarded: false,
|
|
4202
|
+
error: error instanceof Error ? error.message : String(error)
|
|
4203
|
+
};
|
|
4204
|
+
};
|
|
4132
4205
|
const performWorkspaceSync = async (input) => {
|
|
4133
4206
|
if (!workspaceRemoteUrl || !workspaceCredentialHelper || !workspaceCredentialUsername || !workspaceGitIdentity) {
|
|
4134
4207
|
throw new Error("Worker workspace configuration has not been received");
|
|
4135
4208
|
}
|
|
4136
|
-
const
|
|
4209
|
+
const configuredMounts = buildWorkspaceMounts();
|
|
4137
4210
|
if (input.resetToCanonical) {
|
|
4138
|
-
const resetHasBusyLiveMount =
|
|
4211
|
+
const resetHasBusyLiveMount = configuredMounts.some(
|
|
4139
4212
|
(mount) => !(mount.deleteWhenSourceMissing && !fs.existsSync(mount.sourcePath)) && mount.busy?.()
|
|
4140
4213
|
);
|
|
4141
4214
|
if (resetHasBusyLiveMount) {
|
|
4142
4215
|
throw new Error("Workspace reset cannot observe project mirror heads while a live mount is busy; remediation remains active");
|
|
4143
4216
|
}
|
|
4144
|
-
const observedProjectHeads2 = observeProjectHeadsBeforeOuterWorkspace({
|
|
4217
|
+
const observedProjectHeads2 = await observeProjectHeadsBeforeOuterWorkspace({
|
|
4145
4218
|
allowNonFastForward: true,
|
|
4146
4219
|
failClosed: true
|
|
4147
4220
|
});
|
|
4148
|
-
const reset = resetWorkspaceGit({
|
|
4221
|
+
const reset = await resetWorkspaceGit({
|
|
4149
4222
|
workspacePath: workspaceShadowRoot,
|
|
4150
4223
|
remoteUrl: workspaceRemoteUrl,
|
|
4151
4224
|
credentialHelper: workspaceCredentialHelper,
|
|
4152
4225
|
credentialUsername: workspaceCredentialUsername,
|
|
4153
4226
|
gitIdentity: workspaceGitIdentity,
|
|
4154
|
-
mounts
|
|
4227
|
+
mounts: configuredMounts
|
|
4155
4228
|
});
|
|
4156
|
-
applyObservedProjectHeadsAfterInboundWorkspace(observedProjectHeads2, reset.activeMountIds, true);
|
|
4229
|
+
await applyObservedProjectHeadsAfterInboundWorkspace(observedProjectHeads2, reset.activeMountIds, true);
|
|
4157
4230
|
return {
|
|
4158
4231
|
type: "workspace_sync",
|
|
4159
4232
|
attemptId: input.attemptId,
|
|
@@ -4165,7 +4238,7 @@ async function startWorker(options) {
|
|
|
4165
4238
|
...reset.remoteHead ? { publishedHead: reset.remoteHead } : {},
|
|
4166
4239
|
rebaseCount: 0,
|
|
4167
4240
|
diffSizeBytes: 0,
|
|
4168
|
-
gitStatus: workspaceGitStatus(),
|
|
4241
|
+
gitStatus: await workspaceGitStatus(),
|
|
4169
4242
|
affectedProjects: affectedProjects(reset.discardedPaths),
|
|
4170
4243
|
affectedPaths: reset.discardedPaths,
|
|
4171
4244
|
activeMountIds: reset.activeMountIds,
|
|
@@ -4175,13 +4248,14 @@ async function startWorker(options) {
|
|
|
4175
4248
|
};
|
|
4176
4249
|
}
|
|
4177
4250
|
const outerRemediation = input.trigger.type === "remediation" || input.trigger.type === "remediation_confirm";
|
|
4178
|
-
const
|
|
4251
|
+
const mounts = outerRemediation ? workspaceGitMountsForRemediation(configuredMounts) : configuredMounts;
|
|
4252
|
+
const observedProjectHeads = outerRemediation ? [] : await observeProjectHeadsBeforeOuterWorkspace({ allowNonFastForward: false, failClosed: false });
|
|
4179
4253
|
const inboundMoveMountIds = new Set(
|
|
4180
4254
|
observedProjectHeads.flatMap(
|
|
4181
4255
|
({ projectId, observations }) => observations.filter(({ shouldMove }) => shouldMove).map(({ branchName }) => projectMountId(projectId, branchName))
|
|
4182
4256
|
)
|
|
4183
4257
|
);
|
|
4184
|
-
const publicationHeads = outerRemediation ? /* @__PURE__ */ new Map() : captureProjectHeadsForWorkspacePublication();
|
|
4258
|
+
const publicationHeads = outerRemediation ? /* @__PURE__ */ new Map() : await captureProjectHeadsForWorkspacePublication();
|
|
4185
4259
|
const result = await synchronizeWorkspaceGit({
|
|
4186
4260
|
attemptId: input.attemptId,
|
|
4187
4261
|
workerLabel: label,
|
|
@@ -4196,13 +4270,13 @@ async function startWorker(options) {
|
|
|
4196
4270
|
skipMountMirror: outerRemediation,
|
|
4197
4271
|
requiredAncestorHeads: input.requiredAncestorHeads,
|
|
4198
4272
|
assertStillAdmitted: input.assertStillAdmitted,
|
|
4199
|
-
afterWorkspacePublished: outerRemediation ? void 0 : ({ activeMountIds, publishedHead }) => {
|
|
4200
|
-
pushChangedProjectHeads(activeMountIds, publishedHead, publicationHeads, inboundMoveMountIds);
|
|
4273
|
+
afterWorkspacePublished: outerRemediation ? void 0 : async ({ activeMountIds, publishedHead }) => {
|
|
4274
|
+
await pushChangedProjectHeads(activeMountIds, publishedHead, publicationHeads, inboundMoveMountIds);
|
|
4201
4275
|
}
|
|
4202
4276
|
});
|
|
4203
4277
|
input.assertStillAdmitted?.();
|
|
4204
4278
|
if (["no_change", "updated", "pushed"].includes(result.outcome) && !outerRemediation) {
|
|
4205
|
-
applyObservedProjectHeadsAfterInboundWorkspace(observedProjectHeads, result.activeMountIds, false);
|
|
4279
|
+
await applyObservedProjectHeadsAfterInboundWorkspace(observedProjectHeads, result.activeMountIds, false);
|
|
4206
4280
|
}
|
|
4207
4281
|
return mapWorkspaceGitResult(input.attemptId, input.trigger, result);
|
|
4208
4282
|
};
|
|
@@ -4233,7 +4307,7 @@ async function startWorker(options) {
|
|
|
4233
4307
|
};
|
|
4234
4308
|
if (!deferredWorkspaceSyncTriggerIsAllowed(deferredWorkspaceConfiguration, activeWorkspaceIncidentId, input.trigger)) {
|
|
4235
4309
|
const result2 = {
|
|
4236
|
-
...failedWorkspaceSyncResult(
|
|
4310
|
+
...await failedWorkspaceSyncResult(
|
|
4237
4311
|
attemptId,
|
|
4238
4312
|
input.trigger,
|
|
4239
4313
|
new Error(
|
|
@@ -4260,7 +4334,7 @@ async function startWorker(options) {
|
|
|
4260
4334
|
queueEnteredAt = Date.now();
|
|
4261
4335
|
syncStartedAt = Date.now();
|
|
4262
4336
|
if (!deferredWorkspaceSyncTriggerIsAllowed(deferredWorkspaceConfiguration, activeWorkspaceIncidentId, input.trigger)) {
|
|
4263
|
-
return failedWorkspaceSyncResult(
|
|
4337
|
+
return await failedWorkspaceSyncResult(
|
|
4264
4338
|
attemptId,
|
|
4265
4339
|
input.trigger,
|
|
4266
4340
|
new Error(
|
|
@@ -4299,7 +4373,7 @@ async function startWorker(options) {
|
|
|
4299
4373
|
},
|
|
4300
4374
|
exitCode: 1
|
|
4301
4375
|
});
|
|
4302
|
-
return failedWorkspaceSyncResult(attemptId, input.trigger, error);
|
|
4376
|
+
return await failedWorkspaceSyncResult(attemptId, input.trigger, error);
|
|
4303
4377
|
}
|
|
4304
4378
|
});
|
|
4305
4379
|
} finally {
|
|
@@ -4326,7 +4400,7 @@ async function startWorker(options) {
|
|
|
4326
4400
|
pendingCreatedBranchPublicationNotBefore
|
|
4327
4401
|
);
|
|
4328
4402
|
const initialDeferral = pendingBranchDeferral();
|
|
4329
|
-
if (!
|
|
4403
|
+
if (!automaticWorkspaceSyncIsCurrentlyAdmitted() || currentWorkerSocket !== ws || ws.readyState !== WebSocket.OPEN || automaticSyncInFlight || initialDeferral?.kind === "active_target") {
|
|
4330
4404
|
return;
|
|
4331
4405
|
}
|
|
4332
4406
|
if (workspaceAutomaticTimer) clearTimeout(workspaceAutomaticTimer);
|
|
@@ -4334,8 +4408,7 @@ async function startWorker(options) {
|
|
|
4334
4408
|
() => {
|
|
4335
4409
|
workspaceAutomaticTimer = void 0;
|
|
4336
4410
|
const scheduledTrigger = pendingAutomaticTrigger;
|
|
4337
|
-
if (!scheduledTrigger || !
|
|
4338
|
-
return;
|
|
4411
|
+
if (!scheduledTrigger || !automaticWorkspaceSyncIsCurrentlyAdmitted() || currentWorkerSocket !== ws) return;
|
|
4339
4412
|
const currentDeferral = pendingBranchDeferral();
|
|
4340
4413
|
if (currentDeferral?.kind === "active_target") return;
|
|
4341
4414
|
if (currentDeferral?.kind === "creation_grace") {
|
|
@@ -4357,7 +4430,7 @@ async function startWorker(options) {
|
|
|
4357
4430
|
}).finally(() => {
|
|
4358
4431
|
automaticSyncInFlight = false;
|
|
4359
4432
|
heartbeatBusyGrace = grantWorkerHeartbeatBusyGrace(lastServerHeartbeatAt, heartbeatBusyGrace);
|
|
4360
|
-
if (pendingAutomaticTrigger &&
|
|
4433
|
+
if (pendingAutomaticTrigger && automaticWorkspaceSyncIsCurrentlyAdmitted()) {
|
|
4361
4434
|
scheduleAutomaticWorkspaceSync(pendingAutomaticTrigger, WORKSPACE_GIT_QUIET_MS);
|
|
4362
4435
|
}
|
|
4363
4436
|
});
|
|
@@ -4399,7 +4472,7 @@ async function startWorker(options) {
|
|
|
4399
4472
|
if (incidentDeferral.error) {
|
|
4400
4473
|
workspaceConfigured = false;
|
|
4401
4474
|
return {
|
|
4402
|
-
result: failedWorkspaceSyncResult(crypto.randomUUID(), { type: "connect" }, incidentDeferral.error),
|
|
4475
|
+
result: await failedWorkspaceSyncResult(crypto.randomUUID(), { type: "connect" }, incidentDeferral.error),
|
|
4403
4476
|
pending: incidentDeferredProjectCheckouts(message.projects),
|
|
4404
4477
|
aheadOfOriginBranches: []
|
|
4405
4478
|
};
|
|
@@ -4427,7 +4500,7 @@ async function startWorker(options) {
|
|
|
4427
4500
|
canonicalRemediationActive: canonicalWorkspaceMutationIsActive(activeWorkspaceMutationTargets())
|
|
4428
4501
|
})) {
|
|
4429
4502
|
return {
|
|
4430
|
-
result: failedWorkspaceSyncResult(
|
|
4503
|
+
result: await failedWorkspaceSyncResult(
|
|
4431
4504
|
crypto.randomUUID(),
|
|
4432
4505
|
{ type: "connect" },
|
|
4433
4506
|
new Error("Workspace credential rotation is deferred until the active canonical remediation command finishes")
|
|
@@ -4486,7 +4559,7 @@ async function startWorker(options) {
|
|
|
4486
4559
|
} catch (error) {
|
|
4487
4560
|
const wrapped = error instanceof RegistryAuthConfigurationError ? error : new RegistryAuthConfigurationError(error);
|
|
4488
4561
|
return {
|
|
4489
|
-
result: failedWorkspaceSyncResult(crypto.randomUUID(), { type: "connect" }, wrapped),
|
|
4562
|
+
result: await failedWorkspaceSyncResult(crypto.randomUUID(), { type: "connect" }, wrapped),
|
|
4490
4563
|
pending: [],
|
|
4491
4564
|
aheadOfOriginBranches: []
|
|
4492
4565
|
};
|
|
@@ -4663,7 +4736,7 @@ async function startWorker(options) {
|
|
|
4663
4736
|
}));
|
|
4664
4737
|
const nextProjectConfigById = new Map(effectiveProjects.map((project) => [project.projectId, project]));
|
|
4665
4738
|
if (incidentDeferral.incidentId) {
|
|
4666
|
-
configureExistingWorkspaceGitForRemediation({
|
|
4739
|
+
await configureExistingWorkspaceGitForRemediation({
|
|
4667
4740
|
workspacePath: workspaceShadowRoot,
|
|
4668
4741
|
remoteUrl: message.workspaceRemoteUrl,
|
|
4669
4742
|
credentialHelper: nextWorkspaceCredentialHelper,
|
|
@@ -4682,7 +4755,7 @@ async function startWorker(options) {
|
|
|
4682
4755
|
result: deferredIncidentWorkspaceConfigurationResult({
|
|
4683
4756
|
attemptId: crypto.randomUUID(),
|
|
4684
4757
|
workerLabel: label,
|
|
4685
|
-
head: workspaceLocalHead(),
|
|
4758
|
+
head: await workspaceLocalHead(),
|
|
4686
4759
|
skippedMountIds: buildWorkspaceMounts().map(({ id }) => id)
|
|
4687
4760
|
}),
|
|
4688
4761
|
pending: pending2,
|
|
@@ -4690,7 +4763,7 @@ async function startWorker(options) {
|
|
|
4690
4763
|
deferredWorkspaceSyncForIncidentId: incidentDeferral.incidentId
|
|
4691
4764
|
};
|
|
4692
4765
|
}
|
|
4693
|
-
ensureWorkspaceGitClone({
|
|
4766
|
+
await ensureWorkspaceGitClone({
|
|
4694
4767
|
workspacePath: workspaceShadowRoot,
|
|
4695
4768
|
remoteUrl: message.workspaceRemoteUrl,
|
|
4696
4769
|
credentialHelper: nextWorkspaceCredentialHelper,
|
|
@@ -4710,7 +4783,7 @@ async function startWorker(options) {
|
|
|
4710
4783
|
sourcePath: recoverySourceOverrides.get(mount.id) ?? mount.sourcePath,
|
|
4711
4784
|
busy: mount.busyForRecovery ?? mount.busy
|
|
4712
4785
|
}));
|
|
4713
|
-
recoverWorkspaceGitHydration(workspaceShadowRoot, recoveryMounts, { preserveStaleBases: true });
|
|
4786
|
+
await recoverWorkspaceGitHydration(workspaceShadowRoot, recoveryMounts, { preserveStaleBases: true });
|
|
4714
4787
|
for (const project of message.projects) {
|
|
4715
4788
|
for (const { branchName } of project.preserveOnlyBranches) {
|
|
4716
4789
|
if (stillPendingCreatedBranches.has(pendingCreatedBranchKey(project.projectId, branchName))) {
|
|
@@ -4747,7 +4820,7 @@ async function startWorker(options) {
|
|
|
4747
4820
|
}
|
|
4748
4821
|
stageDurableWorkspaceDeletions();
|
|
4749
4822
|
const mountsBeforeGit = buildWorkspaceMounts();
|
|
4750
|
-
hydrateWorkspaceGitMounts(
|
|
4823
|
+
await hydrateWorkspaceGitMounts(
|
|
4751
4824
|
workspaceShadowRoot,
|
|
4752
4825
|
mountsBeforeGit.filter((mount) => !mount.deleteWhenSourceMissing && !fs.existsSync(mount.sourcePath) && mount.busy?.() !== true),
|
|
4753
4826
|
// These mounts are intentionally hydrated before their project Git
|
|
@@ -4756,7 +4829,7 @@ async function startWorker(options) {
|
|
|
4756
4829
|
// checkout initialization from erasing synchronized dirt.
|
|
4757
4830
|
{ ignoreBusy: true }
|
|
4758
4831
|
);
|
|
4759
|
-
ensureConfiguredProjects();
|
|
4832
|
+
await ensureConfiguredProjects();
|
|
4760
4833
|
const configurationSyncAdmissionGeneration = workerAdmissionGeneration;
|
|
4761
4834
|
const assertConfigurationSyncStillAdmitted = () => {
|
|
4762
4835
|
if (receiptGeneration !== workspaceConfigurationReceiptGeneration || configurationSyncAdmissionGeneration !== workerAdmissionGeneration || !workspaceConfigurationIncidentSnapshotIsCurrent(incidentDeferral.incidentId, activeWorkspaceIncidentId) || currentWorkerSocket !== ws || ws.readyState !== WebSocket.OPEN) {
|
|
@@ -4766,6 +4839,7 @@ async function startWorker(options) {
|
|
|
4766
4839
|
const result = await performWorkspaceSync({
|
|
4767
4840
|
attemptId: crypto.randomUUID(),
|
|
4768
4841
|
trigger: { type: "connect" },
|
|
4842
|
+
resetToCanonical: workspaceConfigurationResetToCanonicalIsAllowed(message.resetToCanonical, incidentDeferral.incidentId),
|
|
4769
4843
|
assertStillAdmitted: assertConfigurationSyncStillAdmitted
|
|
4770
4844
|
});
|
|
4771
4845
|
assertConfigurationSyncStillAdmitted();
|
|
@@ -4800,12 +4874,12 @@ async function startWorker(options) {
|
|
|
4800
4874
|
const pending = [...pendingCheckouts.values()].sort(
|
|
4801
4875
|
(left, right) => left.projectId.localeCompare(right.projectId) || left.branchName.localeCompare(right.branchName)
|
|
4802
4876
|
);
|
|
4803
|
-
return { result, pending, aheadOfOriginBranches: collectAheadOfOriginBranches() };
|
|
4877
|
+
return { result, pending, aheadOfOriginBranches: await collectAheadOfOriginBranches() };
|
|
4804
4878
|
});
|
|
4805
4879
|
} catch (error) {
|
|
4806
4880
|
if (receiptGeneration !== workspaceConfigurationReceiptGeneration) {
|
|
4807
4881
|
return {
|
|
4808
|
-
result: failedWorkspaceSyncResult(crypto.randomUUID(), { type: "connect" }, error),
|
|
4882
|
+
result: await failedWorkspaceSyncResult(crypto.randomUUID(), { type: "connect" }, error),
|
|
4809
4883
|
pending: incidentDeferredProjectCheckouts(message.projects),
|
|
4810
4884
|
aheadOfOriginBranches: []
|
|
4811
4885
|
};
|
|
@@ -4837,7 +4911,7 @@ async function startWorker(options) {
|
|
|
4837
4911
|
pendingCheckouts.set(projectBranchKey(pending.projectId, pending.branchName), pending);
|
|
4838
4912
|
}
|
|
4839
4913
|
return {
|
|
4840
|
-
result: failedWorkspaceSyncResult(crypto.randomUUID(), { type: "connect" }, error),
|
|
4914
|
+
result: await failedWorkspaceSyncResult(crypto.randomUUID(), { type: "connect" }, error),
|
|
4841
4915
|
pending: [...pendingCheckouts.values()].sort(
|
|
4842
4916
|
(left, right) => left.projectId.localeCompare(right.projectId) || left.branchName.localeCompare(right.branchName)
|
|
4843
4917
|
),
|
|
@@ -4864,7 +4938,7 @@ async function startWorker(options) {
|
|
|
4864
4938
|
workspaceAutomaticTimer = void 0;
|
|
4865
4939
|
}
|
|
4866
4940
|
void (async () => {
|
|
4867
|
-
if (
|
|
4941
|
+
if (automaticWorkspaceSyncIsCurrentlyAdmitted()) {
|
|
4868
4942
|
await runWorkspaceSync({
|
|
4869
4943
|
trigger: { type: "manual", detail: "graceful worker shutdown" }
|
|
4870
4944
|
});
|
|
@@ -4915,7 +4989,8 @@ async function startWorker(options) {
|
|
|
4915
4989
|
execStdinV1: true,
|
|
4916
4990
|
ptyEnvFilesV1: true,
|
|
4917
4991
|
workspaceRemediationAncestorGuardV1: true,
|
|
4918
|
-
workspaceIncidentConfigDeferralV1: true
|
|
4992
|
+
workspaceIncidentConfigDeferralV1: true,
|
|
4993
|
+
workspaceConfigResetToCanonicalV1: true
|
|
4919
4994
|
},
|
|
4920
4995
|
projectRoot: projectsRoot,
|
|
4921
4996
|
artifactRoot,
|
|
@@ -4979,7 +5054,7 @@ async function startWorker(options) {
|
|
|
4979
5054
|
}, WORKSPACE_GIT_PERIODIC_MS);
|
|
4980
5055
|
workspacePeriodicTimer.unref();
|
|
4981
5056
|
}
|
|
4982
|
-
if (pendingAutomaticTrigger &&
|
|
5057
|
+
if (pendingAutomaticTrigger && automaticWorkspaceSyncIsCurrentlyAdmitted()) {
|
|
4983
5058
|
scheduleAutomaticWorkspaceSync(pendingAutomaticTrigger, 0);
|
|
4984
5059
|
}
|
|
4985
5060
|
return;
|
|
@@ -5219,35 +5294,33 @@ async function startWorker(options) {
|
|
|
5219
5294
|
if (nextIncidentId !== previousIncidentId) advanceWorkerAdmissionGeneration();
|
|
5220
5295
|
activeWorkspaceIncidentId = nextIncidentId;
|
|
5221
5296
|
if (previousIncidentId && !activeWorkspaceIncidentId && (message.status === "resolved" || message.status === "confirmed" || message.status === "reset")) {
|
|
5222
|
-
const
|
|
5297
|
+
const refresh = workspaceIncidentTerminalRefreshFence({
|
|
5223
5298
|
deferredConfiguration: deferredWorkspaceConfiguration,
|
|
5224
5299
|
clearedIncidentId: previousIncidentId
|
|
5225
5300
|
});
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
}
|
|
5248
|
-
return;
|
|
5301
|
+
deferredWorkspaceConfiguration = refresh.deferredConfiguration;
|
|
5302
|
+
pendingAutomaticTrigger ??= { type: "periodic", detail: "resume after workspace incident" };
|
|
5303
|
+
workspaceConfigured = false;
|
|
5304
|
+
advanceWorkerAdmissionGeneration();
|
|
5305
|
+
if (refresh.disposition === "reconnect_for_refresh") {
|
|
5306
|
+
ws.close(1012, "Refreshing deferred workspace configuration");
|
|
5307
|
+
} else {
|
|
5308
|
+
if (deferredWorkspaceConfigurationRefreshTimer) clearTimeout(deferredWorkspaceConfigurationRefreshTimer);
|
|
5309
|
+
const deferredIncidentId = deferredWorkspaceConfiguration.incidentId;
|
|
5310
|
+
deferredWorkspaceConfigurationRefreshTimer = setTimeout(() => {
|
|
5311
|
+
deferredWorkspaceConfigurationRefreshTimer = void 0;
|
|
5312
|
+
if (!deferredWorkspaceRefreshWatchdogIsCurrent({
|
|
5313
|
+
capturedIncidentId: deferredIncidentId,
|
|
5314
|
+
deferredConfiguration: deferredWorkspaceConfiguration,
|
|
5315
|
+
activeIncidentId: activeWorkspaceIncidentId
|
|
5316
|
+
}) || currentWorkerSocket !== ws || ws.readyState !== WebSocket.OPEN) {
|
|
5317
|
+
return;
|
|
5318
|
+
}
|
|
5319
|
+
ws.close(1012, "Timed out waiting for deferred workspace configuration refresh");
|
|
5320
|
+
}, WORKSPACE_INCIDENT_CONFIG_REFRESH_TIMEOUT_MS);
|
|
5321
|
+
deferredWorkspaceConfigurationRefreshTimer.unref();
|
|
5249
5322
|
}
|
|
5250
|
-
|
|
5323
|
+
return;
|
|
5251
5324
|
}
|
|
5252
5325
|
return;
|
|
5253
5326
|
}
|
|
@@ -5620,7 +5693,12 @@ async function startWorker(options) {
|
|
|
5620
5693
|
if (targetMayMutateVisibleWorkspace(message.target)) recordVisibleWorkspaceMutation(message.target);
|
|
5621
5694
|
});
|
|
5622
5695
|
}
|
|
5623
|
-
await
|
|
5696
|
+
await runReservedWorkspaceCommand(message.target, workspaceSyncSingleFlight, runCommand, () => {
|
|
5697
|
+
if (targetReserved) {
|
|
5698
|
+
workspaceSyncPriorityProcessTargets.delete(message.runId);
|
|
5699
|
+
targetReserved = false;
|
|
5700
|
+
}
|
|
5701
|
+
});
|
|
5624
5702
|
} finally {
|
|
5625
5703
|
if (targetReserved) workspaceSyncPriorityProcessTargets.delete(message.runId);
|
|
5626
5704
|
}
|
|
@@ -5694,7 +5772,7 @@ async function startWorker(options) {
|
|
|
5694
5772
|
} finally {
|
|
5695
5773
|
if (reservesVisibleWorkspace) {
|
|
5696
5774
|
workspaceSyncPriorityOperationTargets.delete(message.requestId);
|
|
5697
|
-
if (pendingAutomaticTrigger &&
|
|
5775
|
+
if (pendingAutomaticTrigger && automaticWorkspaceSyncIsCurrentlyAdmitted()) {
|
|
5698
5776
|
scheduleAutomaticWorkspaceSync(pendingAutomaticTrigger, dirtyTrigger ? WORKSPACE_GIT_QUIET_MS : 0);
|
|
5699
5777
|
}
|
|
5700
5778
|
}
|