mirror of
https://github.com/stablyai/orca.git
synced 2026-10-18 00:03:20 +00:00
* fix(codex): stop re-scanning all Codex session history on every launch (#16251) A launch deleted the backfill completion marker, and a marker could never be written while a Codex pane was open, so every launch re-derived "needs full scan" and walked the entire .codex/sessions tree — on Windows with a large history that read as a hung window. - v4 marker keeps a durable full-history baseline plus a bounded set of pending dates. v3 is read as a baseline, so upgrades pay no full scan. - A launch now marks dates pending instead of deleting the marker, and a full pass certifies the baseline even while a pane is still running; the live pane's own date just stays pending. - Pending dates are persisted, so an abnormal exit or a cross-midnight pane recovers a bounded window instead of a full walk. - A date-limited pass can only extend an existing baseline, never create one, so it can no longer certify history it never looked at. - Marker and index-heal target roots compare through normalizeRuntimePathForComparison, so Windows spellings of one directory stop invalidating each other. - Both append-only ledgers stream instead of readFileSync + whole-file JSON.parse, keeping the main thread responsive on large histories. * fix(codex): keep the backfill marker's full-scan demand durable Review follow-ups on the v4 backfill marker: - markCodexSessionBackfillMarkerPending no longer erases a persisted needsFullScan; the demand survives until a generation-current full walk retires it, and the function now reports it so the launch path folds it into its own in-memory flag (as @rumoii's #16252 does). - A full pass settles the whole pending set instead of subtracting the empty set, so a date a full walk provably covered stops forcing an extra bounded pass on every startup. - isCodexSessionBackfillDate does a real calendar check, so a corrupted marker cannot carry 2026/99/99. No age or future bound: the same guard gates rollout publication and a clock-skewed directory holds real sessions. - 'scans only the current date once a baseline exists' now has a second date directory, so it fails on a full walk instead of passing either way.
52 lines
1.7 KiB
TypeScript
52 lines
1.7 KiB
TypeScript
import { join, relative, sep } from 'node:path'
|
|
import { isCodexSessionBackfillDate } from './codex-session-backfill-scan-dates'
|
|
import { listCodexSessionJsonlFilesIncrementally } from './codex-session-file-listing'
|
|
import type {
|
|
CodexSessionBackfillDate,
|
|
CodexSessionBackfillOptions
|
|
} from './codex-session-backfill-types'
|
|
|
|
export function isCodexSessionRolloutPath(sessionsRoot: string, filePath: string): boolean {
|
|
const pathParts = relative(sessionsRoot, filePath).split(sep)
|
|
if (pathParts.length !== 4) {
|
|
return false
|
|
}
|
|
const [year, month, day, fileName] = pathParts
|
|
return isCodexSessionBackfillDate([year, month, day]) && /^rollout-.+\.jsonl$/.test(fileName)
|
|
}
|
|
|
|
export async function* listCodexSessionBackfillFilesForDates(
|
|
sessionsRoot: string,
|
|
options: CodexSessionBackfillOptions,
|
|
onDirectoryError: (directoryPath: string, error: unknown) => void | Promise<void>
|
|
): AsyncGenerator<string> {
|
|
const scanRoots = resolveCodexSessionBackfillDateRoots(sessionsRoot, options.scanDates)
|
|
for (const scanRoot of scanRoots) {
|
|
yield* listCodexSessionJsonlFilesIncrementally(
|
|
scanRoot,
|
|
options,
|
|
async (directoryPath, error) => {
|
|
if (directoryPath !== scanRoot || !isNotFoundError(error)) {
|
|
await onDirectoryError(directoryPath, error)
|
|
}
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
function resolveCodexSessionBackfillDateRoots(
|
|
sessionsRoot: string,
|
|
scanDates: readonly CodexSessionBackfillDate[] | undefined
|
|
): string[] {
|
|
if (!scanDates?.length) {
|
|
return [sessionsRoot]
|
|
}
|
|
return scanDates
|
|
.filter(isCodexSessionBackfillDate)
|
|
.map(([year, month, day]) => join(sessionsRoot, year, month, day))
|
|
}
|
|
|
|
function isNotFoundError(error: unknown): boolean {
|
|
return (error as NodeJS.ErrnoException | null)?.code === 'ENOENT'
|
|
}
|