Skip to content

Commit 9fafa21

Browse files
honor2030clawsweeper[bot]
authored andcommitted
fix: retry config snapshot after rejection
1 parent 1f794d2 commit 9fafa21

2 files changed

Lines changed: 34 additions & 1 deletion

File tree

src/cli/program/config-guard.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,31 @@ describe("ensureConfigReady", () => {
130130
);
131131
});
132132

133+
it("retries the cached config snapshot after a read rejection", async () => {
134+
const originalVitest = process.env.VITEST;
135+
process.env.VITEST = "false";
136+
const transientError = new Error("temporary config read failure");
137+
const recoveredSnapshot = makeSnapshot();
138+
readConfigFileSnapshotMock
139+
.mockRejectedValueOnce(transientError)
140+
.mockResolvedValueOnce(recoveredSnapshot);
141+
142+
try {
143+
await expect(runEnsureConfigReady(["status"])).rejects.toThrow(transientError);
144+
await expect(runEnsureConfigReady(["status"])).resolves.toBeDefined();
145+
await expect(runEnsureConfigReady(["status"])).resolves.toBeDefined();
146+
} finally {
147+
if (originalVitest === undefined) {
148+
delete process.env.VITEST;
149+
} else {
150+
process.env.VITEST = originalVitest;
151+
}
152+
}
153+
154+
expect(readConfigFileSnapshotMock).toHaveBeenCalledTimes(2);
155+
expect(setRuntimeConfigSnapshotMock).toHaveBeenCalledWith(undefined, undefined);
156+
});
157+
133158
it("exits for invalid config on non-allowlisted commands", async () => {
134159
setInvalidSnapshot();
135160
const runtime = await runEnsureConfigReady(["message"]);

src/cli/program/config-guard.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,15 @@ async function getConfigSnapshot() {
3030
if (process.env.VITEST === "true") {
3131
return readConfigFileSnapshot();
3232
}
33-
configSnapshotPromise ??= readConfigFileSnapshot();
33+
if (!configSnapshotPromise) {
34+
const pendingSnapshot = readConfigFileSnapshot();
35+
configSnapshotPromise = pendingSnapshot;
36+
pendingSnapshot.catch(() => {
37+
if (configSnapshotPromise === pendingSnapshot) {
38+
configSnapshotPromise = null;
39+
}
40+
});
41+
}
3442
return configSnapshotPromise;
3543
}
3644

0 commit comments

Comments
 (0)