Dispose worktree change refresh queues (#6040)
Co-authored-by: Neil <neil@stably.ai>
This commit is contained in:
parent
2e03b14cc3
commit
c1e071870b
|
|
@ -810,6 +810,7 @@ export function useIpcEvents(): void {
|
|||
}
|
||||
}
|
||||
const worktreeChangeRefreshQueue = createWorktreeChangeRefreshQueue(handleWorktreesChanged)
|
||||
unsubs.push(worktreeChangeRefreshQueue.dispose)
|
||||
|
||||
const activateNotifiedWorktree = async (
|
||||
{
|
||||
|
|
|
|||
|
|
@ -139,4 +139,30 @@ describe('createWorktreeChangeRefreshQueue', () => {
|
|||
expect(handler).toHaveBeenNthCalledWith(2, 'repo-1', renamed)
|
||||
expect(handler).toHaveBeenNthCalledWith(3, 'repo-1', undefined)
|
||||
})
|
||||
|
||||
it('drops queued trailing refreshes after disposal', async () => {
|
||||
const firstRefresh = deferred()
|
||||
const handler = vi.fn().mockReturnValueOnce(firstRefresh.promise).mockResolvedValue(undefined)
|
||||
const queue = createWorktreeChangeRefreshQueue(handler)
|
||||
|
||||
queue.enqueue({ repoId: 'repo-1' })
|
||||
queue.enqueue({ repoId: 'repo-1' })
|
||||
queue.dispose()
|
||||
|
||||
firstRefresh.resolve()
|
||||
await flushPromises()
|
||||
|
||||
expect(handler).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('ignores new events after disposal', async () => {
|
||||
const handler = vi.fn(() => Promise.resolve())
|
||||
const queue = createWorktreeChangeRefreshQueue(handler)
|
||||
|
||||
queue.dispose()
|
||||
queue.enqueue({ repoId: 'repo-1' })
|
||||
await flushPromises()
|
||||
|
||||
expect(handler).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ type RepoRefreshState = {
|
|||
}
|
||||
|
||||
export type WorktreeChangeRefreshQueue = {
|
||||
dispose: () => void
|
||||
enqueue: (event: WorktreeChangeEvent) => void
|
||||
}
|
||||
|
||||
|
|
@ -27,11 +28,12 @@ export function createWorktreeChangeRefreshQueue(
|
|||
handler: WorktreeChangeRefreshHandler
|
||||
): WorktreeChangeRefreshQueue {
|
||||
const states = new Map<string, RepoRefreshState>()
|
||||
let disposed = false
|
||||
|
||||
const drain = async (repoId: string, state: RepoRefreshState): Promise<void> => {
|
||||
state.running = true
|
||||
try {
|
||||
while (state.queue.length > 0) {
|
||||
while (!disposed && state.queue.length > 0) {
|
||||
const next = state.queue.shift()
|
||||
try {
|
||||
await handler(repoId, next?.renamed)
|
||||
|
|
@ -41,7 +43,7 @@ export function createWorktreeChangeRefreshQueue(
|
|||
}
|
||||
} finally {
|
||||
state.running = false
|
||||
if (state.queue.length === 0) {
|
||||
if (disposed || state.queue.length === 0) {
|
||||
states.delete(repoId)
|
||||
} else {
|
||||
void drain(repoId, state)
|
||||
|
|
@ -50,7 +52,15 @@ export function createWorktreeChangeRefreshQueue(
|
|||
}
|
||||
|
||||
return {
|
||||
dispose() {
|
||||
disposed = true
|
||||
states.clear()
|
||||
},
|
||||
|
||||
enqueue(event) {
|
||||
if (disposed) {
|
||||
return
|
||||
}
|
||||
let state = states.get(event.repoId)
|
||||
if (!state) {
|
||||
state = { running: false, queue: [] }
|
||||
|
|
|
|||
Loading…
Reference in New Issue