mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 00:57:45 +00:00
* [comment audit] Shorten daemon, hook, and emulator comments [skip ci] * [comment audit] Shorten VM, conversation, SQLite, and theme-import comments [skip ci] * [comment audit] Tighten Git execution and source-control comment contracts [skip ci] * [comment audit] Clarify repository probes and maintenance comments [skip ci] * [comment audit] Shorten status, diff-cache, and checkout comments [skip ci] * [comment audit] Clarify worktree lifecycle and WSL routing comments [skip ci] * [comment audit] Shorten forge identity and review-refresh comments [skip ci] * [comment audit] Tighten hosted-review client comment contracts [skip ci] * [comment audit] Clarify GitLab compatibility and review comments [skip ci] * [comment audit] Tighten hook ownership and watchdog rationale [skip ci] * [comment audit] Condense host and integration compatibility comments [skip ci] * [comment audit] Clarify IPC authority and remote-routing rationale [skip ci] * [comment audit] Finalize file-import and containment comment cleanup * [comment audit] Fix stale Jira type imports blocking full CI --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
129 lines
5.3 KiB
TypeScript
129 lines
5.3 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
const { gitExecFileAsyncMock } = vi.hoisted(() => ({
|
|
gitExecFileAsyncMock: vi.fn()
|
|
}))
|
|
|
|
vi.mock('./runner', () => ({ gitExecFileAsync: gitExecFileAsyncMock }))
|
|
|
|
import { PROBE_COALESCE_STALE_MS } from './coalesced-probe'
|
|
import { createRemoteRefProbeCache, NEGATIVE_ENTRY_TTL_MS } from './remote-ref-probe-cache'
|
|
|
|
/** Stands in for a forge's parser: claims one host, rejects everything else. */
|
|
function parseExampleRef(remoteUrl: string): { repo: string } | null {
|
|
const match = remoteUrl.trim().match(/^git@example\.com:(.+?)(?:\.git)?$/)
|
|
return match ? { repo: match[1] } : null
|
|
}
|
|
|
|
function deferred<T>(): { promise: Promise<T>; resolve: (value: T) => void } {
|
|
let resolve: (value: T) => void = () => {}
|
|
const promise = new Promise<T>((settle) => {
|
|
resolve = settle
|
|
})
|
|
return { promise, resolve }
|
|
}
|
|
|
|
describe('remote ref probe cache (P1-D)', () => {
|
|
beforeEach(() => {
|
|
gitExecFileAsyncMock.mockReset()
|
|
vi.useFakeTimers()
|
|
vi.setSystemTime(1_000_000)
|
|
})
|
|
|
|
afterEach(() => {
|
|
vi.useRealTimers()
|
|
})
|
|
|
|
it('answers concurrent lookups for one repo with a single probe', async () => {
|
|
const cache = createRemoteRefProbeCache(parseExampleRef)
|
|
gitExecFileAsyncMock.mockResolvedValue({ stdout: 'git@example.com:team/repo.git\n' })
|
|
|
|
const answers = await Promise.all([
|
|
cache.get('/repo', 'origin'),
|
|
cache.get('/repo', 'origin'),
|
|
cache.get('/repo', 'origin')
|
|
])
|
|
|
|
expect(answers).toEqual([{ repo: 'team/repo' }, { repo: 'team/repo' }, { repo: 'team/repo' }])
|
|
expect(gitExecFileAsyncMock).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it('re-probes a repo whose remotes could have changed since the miss', async () => {
|
|
const cache = createRemoteRefProbeCache(parseExampleRef)
|
|
gitExecFileAsyncMock.mockRejectedValueOnce(new Error("fatal: No such remote 'origin'"))
|
|
|
|
await expect(cache.get('/repo', 'origin')).resolves.toBeNull()
|
|
await expect(cache.get('/repo', 'origin')).resolves.toBeNull()
|
|
expect(gitExecFileAsyncMock).toHaveBeenCalledTimes(1)
|
|
|
|
// Expiring negatives reveal new remotes without filesystem watchers on SSH/WSL.
|
|
gitExecFileAsyncMock.mockResolvedValue({ stdout: 'git@example.com:team/repo.git\n' })
|
|
vi.setSystemTime(1_000_000 + NEGATIVE_ENTRY_TTL_MS + 1)
|
|
|
|
await expect(cache.get('/repo', 'origin')).resolves.toEqual({ repo: 'team/repo' })
|
|
expect(gitExecFileAsyncMock).toHaveBeenCalledTimes(2)
|
|
})
|
|
|
|
it('keeps a resolved ref without re-probing', async () => {
|
|
const cache = createRemoteRefProbeCache(parseExampleRef)
|
|
gitExecFileAsyncMock.mockResolvedValue({ stdout: 'git@example.com:team/repo.git\n' })
|
|
|
|
await expect(cache.get('/repo', 'origin')).resolves.toEqual({ repo: 'team/repo' })
|
|
vi.setSystemTime(1_000_000 + NEGATIVE_ENTRY_TTL_MS * 10)
|
|
await expect(cache.get('/repo', 'origin')).resolves.toEqual({ repo: 'team/repo' })
|
|
|
|
expect(gitExecFileAsyncMock).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it('does not let a probe abandoned as stale overwrite its successor answer', async () => {
|
|
const cache = createRemoteRefProbeCache(parseExampleRef)
|
|
const stalled = deferred<{ stdout: string }>()
|
|
gitExecFileAsyncMock
|
|
.mockImplementationOnce(async () => await stalled.promise)
|
|
.mockResolvedValue({ stdout: 'git@example.com:team/repo.git\n' })
|
|
|
|
const abandoned = cache.get('/repo', 'origin')
|
|
vi.setSystemTime(1_000_000 + PROBE_COALESCE_STALE_MS + 1)
|
|
await expect(cache.get('/repo', 'origin')).resolves.toEqual({ repo: 'team/repo' })
|
|
|
|
// Abandoned probes still answer their caller but must not overwrite newer cached state.
|
|
stalled.resolve({ stdout: 'git@elsewhere.example:team/repo.git\n' })
|
|
await expect(abandoned).resolves.toBeNull()
|
|
|
|
await expect(cache.get('/repo', 'origin')).resolves.toEqual({ repo: 'team/repo' })
|
|
expect(gitExecFileAsyncMock).toHaveBeenCalledTimes(2)
|
|
})
|
|
|
|
it('holds a parsed-as-not-mine remote for the negative interval, then re-asks', async () => {
|
|
const cache = createRemoteRefProbeCache(parseExampleRef)
|
|
gitExecFileAsyncMock.mockResolvedValue({ stdout: 'git@elsewhere.example:team/repo.git\n' })
|
|
|
|
await expect(cache.get('/repo', 'origin')).resolves.toBeNull()
|
|
await expect(cache.get('/repo', 'origin')).resolves.toBeNull()
|
|
expect(gitExecFileAsyncMock).toHaveBeenCalledTimes(1)
|
|
|
|
vi.setSystemTime(1_000_000 + NEGATIVE_ENTRY_TTL_MS + 1)
|
|
await expect(cache.get('/repo', 'origin')).resolves.toBeNull()
|
|
expect(gitExecFileAsyncMock).toHaveBeenCalledTimes(2)
|
|
})
|
|
|
|
it('answers an SSH repo with null without running git on this machine', async () => {
|
|
const cache = createRemoteRefProbeCache(parseExampleRef)
|
|
|
|
await expect(cache.get('/repo', 'origin', 'conn-1')).resolves.toBeNull()
|
|
await expect(cache.get('/repo', 'origin', 'conn-1')).resolves.toBeNull()
|
|
expect(gitExecFileAsyncMock).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('does not cache a probe killed on its deadline as a definitive miss', async () => {
|
|
const cache = createRemoteRefProbeCache(parseExampleRef)
|
|
gitExecFileAsyncMock
|
|
.mockRejectedValueOnce(new Error('git timed out.'))
|
|
.mockResolvedValueOnce({ stdout: 'git@example.com:team/repo.git\n' })
|
|
|
|
await expect(cache.get('/repo', 'origin')).resolves.toBeNull()
|
|
await expect(cache.get('/repo', 'origin')).resolves.toEqual({ repo: 'team/repo' })
|
|
expect(gitExecFileAsyncMock).toHaveBeenCalledTimes(2)
|
|
})
|
|
})
|