fix: release codex lease on readonly prep failure
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -39,6 +39,7 @@ tmp/
|
||||
backups/
|
||||
dist-backups/
|
||||
.deploy-backups/
|
||||
recovery/
|
||||
cache/
|
||||
runners/*/node_modules/
|
||||
runners/codex-runner-backups/
|
||||
|
||||
@@ -474,6 +474,55 @@ describe('agent-runner timeout behavior', () => {
|
||||
expect(spawnEnv?.CODEX_HOME).toBe('/tmp/host-reviewer-session/.codex');
|
||||
});
|
||||
|
||||
it('releases the initial Codex auth lease when read-only session preparation fails', async () => {
|
||||
vi.useRealTimers();
|
||||
fakeProc = createFakeProcess();
|
||||
|
||||
const releaseLease = vi.fn();
|
||||
const prepareGroupEnvironmentSpy = mockCodexLeaseEnvironment(releaseLease);
|
||||
const readonlyError = new Error('Codex rotation pool unavailable');
|
||||
const prepareReadonlySessionEnvironmentSpy = vi
|
||||
.spyOn(agentRunnerEnvironment, 'prepareReadonlySessionEnvironment')
|
||||
.mockImplementationOnce(() => {
|
||||
throw readonlyError;
|
||||
});
|
||||
const codexGroup: RegisteredGroup = {
|
||||
...testGroup,
|
||||
agentType: 'codex',
|
||||
};
|
||||
|
||||
try {
|
||||
await expect(
|
||||
runAgentProcess(
|
||||
codexGroup,
|
||||
{
|
||||
...testInput,
|
||||
roomRoleContext: {
|
||||
serviceId: 'codex-review',
|
||||
role: 'reviewer',
|
||||
ownerServiceId: 'codex-main',
|
||||
reviewerServiceId: 'codex-review',
|
||||
failoverOwner: false,
|
||||
},
|
||||
},
|
||||
() => {},
|
||||
async () => {},
|
||||
{
|
||||
EJCLAW_UNSAFE_HOST_PAIRED_MODE: '1',
|
||||
CLAUDE_CONFIG_DIR: '/tmp/host-reviewer-session',
|
||||
EJCLAW_WORK_DIR: '/tmp/paired/task-1/reviewer',
|
||||
},
|
||||
),
|
||||
).rejects.toThrow(readonlyError);
|
||||
|
||||
expect(prepareReadonlySessionEnvironmentSpy).toHaveBeenCalledTimes(1);
|
||||
expect(releaseLease).toHaveBeenCalledTimes(1);
|
||||
} finally {
|
||||
prepareReadonlySessionEnvironmentSpy.mockRestore();
|
||||
prepareGroupEnvironmentSpy.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
it('serializes roomRoleContext into the runner stdin payload', async () => {
|
||||
vi.useRealTimers();
|
||||
fakeProc = createFakeProcess();
|
||||
|
||||
@@ -157,7 +157,11 @@ export async function runAgentProcess(
|
||||
(input.roomRoleContext?.role === 'reviewer' ||
|
||||
input.roomRoleContext?.role === 'arbiter')
|
||||
) {
|
||||
const readonlySession = prepareReadonlySessionEnvironment({
|
||||
const isCodexGroup = (group.agentType || 'claude-code') === 'codex';
|
||||
const previousCodexSessionAuth = codexSessionAuth;
|
||||
let readonlySession: ReturnType<typeof prepareReadonlySessionEnvironment>;
|
||||
try {
|
||||
readonlySession = prepareReadonlySessionEnvironment({
|
||||
sessionDir: envOverrides.CLAUDE_CONFIG_DIR,
|
||||
chatJid: input.chatJid,
|
||||
isMain: input.isMain,
|
||||
@@ -170,8 +174,14 @@ export async function runAgentProcess(
|
||||
workDir: envOverrides[EJCLAW_ENV.workDir] || env[EJCLAW_ENV.workDir],
|
||||
skillOverrides,
|
||||
});
|
||||
if ((group.agentType || 'claude-code') === 'codex') {
|
||||
releaseCodexAuthSession(codexSessionAuth);
|
||||
} catch (err) {
|
||||
if (isCodexGroup) {
|
||||
releaseCodexAuthSession(previousCodexSessionAuth);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
if (isCodexGroup) {
|
||||
releaseCodexAuthSession(previousCodexSessionAuth);
|
||||
codexSessionAuth = readonlySession.codexSessionAuth;
|
||||
env.CODEX_HOME = path.join(envOverrides.CLAUDE_CONFIG_DIR, '.codex');
|
||||
if (readonlySession.codexHomeDir) {
|
||||
|
||||
Reference in New Issue
Block a user