mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-03 02:21:44 +00:00
* fix(storage): guard stale file-lock reclamation * fix(storage): close lock recovery failure paths * Address PR review feedback (#3234) - Flush the lock-child stderr diagnostic before process.exit - Treat explicit NaN timeouts as the default ceiling - Document non-retryable guard timeouts on the worker IPC contract Co-authored-by: Cursor <cursoragent@cursor.com> * fix(storage): stop mislabeling live lock waits as orphan recovery A brief peer inspect must not attach guardPath or send operators to RUNBOOK delete steps. Refuse lock-free embeddings sync, stop --watch only on a true guard timeout, and drop an unreadable self-created guard before failing closed. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(autofix): apply prettier + eslint fixes via /autofix command * Address PR review feedback (#3234) - Verify lock/guard absence before degrading a denied main-lock create - Launch the third contender from unlinkSync, not the dead rename path - Document group-lock timeouts for unrecoverable guard leftovers Co-authored-by: Cursor <cursoragent@cursor.com> * style: prettier index-lock reclaim guard tests Co-authored-by: Cursor <cursoragent@cursor.com> * fix(storage): treat O_EXCL as the lock-file presence check CodeQL flagged existsSync-then-wx on analyze.lock. Create with wx first and only reclaim unreadable leftovers after grace, so a successor is never unlinked from a lost race. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
70 lines
2.2 KiB
TypeScript
70 lines
2.2 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const analyzeFailureMayHaveMutatedLiveIndex = vi.hoisted(() => vi.fn());
|
|
|
|
vi.mock('../../src/core/run-analyze.js', () => ({
|
|
analyzeFailureMayHaveMutatedLiveIndex,
|
|
runFullAnalysis: vi.fn(),
|
|
}));
|
|
|
|
import { shouldStopAfterWatchRefreshFailure } from '../../src/cli/analyze-watch.js';
|
|
import { IndexLockTimeoutError } from '../../src/storage/index-lock.js';
|
|
|
|
describe('watch refresh failure policy', () => {
|
|
beforeEach(() => analyzeFailureMayHaveMutatedLiveIndex.mockReset());
|
|
|
|
it('retries a queued pre-write failure even when incremental writes are in-place', () => {
|
|
const error = new Error('failed before live graph mutation');
|
|
analyzeFailureMayHaveMutatedLiveIndex.mockReturnValue(false);
|
|
|
|
expect(shouldStopAfterWatchRefreshFailure(error, ['src/a.ts'])).toBe(false);
|
|
});
|
|
|
|
it('stops only when a queued failure may have mutated the live graph', () => {
|
|
const error = new Error('failed during live graph mutation');
|
|
analyzeFailureMayHaveMutatedLiveIndex.mockReturnValue(true);
|
|
|
|
expect(shouldStopAfterWatchRefreshFailure(error, ['src/a.ts'])).toBe(true);
|
|
expect(shouldStopAfterWatchRefreshFailure(error, [])).toBe(false);
|
|
});
|
|
|
|
it('stops on an orphan-guard timeout even when the live index was not mutated', () => {
|
|
analyzeFailureMayHaveMutatedLiveIndex.mockReturnValue(false);
|
|
const error = new IndexLockTimeoutError(
|
|
{
|
|
v: 1,
|
|
pid: -1,
|
|
hostname: 'h',
|
|
startTime: null,
|
|
token: '',
|
|
invocationId: '<unreadable>',
|
|
acquiredAt: '',
|
|
},
|
|
30_000,
|
|
false,
|
|
'/tmp/analyze.lock.guard',
|
|
);
|
|
|
|
expect(shouldStopAfterWatchRefreshFailure(error, ['src/a.ts'])).toBe(true);
|
|
expect(shouldStopAfterWatchRefreshFailure(error, [])).toBe(true);
|
|
});
|
|
|
|
it('retries a live-holder lock timeout', () => {
|
|
analyzeFailureMayHaveMutatedLiveIndex.mockReturnValue(false);
|
|
const error = new IndexLockTimeoutError(
|
|
{
|
|
v: 1,
|
|
pid: 42,
|
|
hostname: 'h',
|
|
startTime: null,
|
|
token: 't',
|
|
invocationId: 'i',
|
|
acquiredAt: '',
|
|
},
|
|
5_000,
|
|
true,
|
|
);
|
|
|
|
expect(shouldStopAfterWatchRefreshFailure(error, ['src/a.ts'])).toBe(false);
|
|
});
|
|
});
|