perf(main): drop localhost label routes when a worktree is removed (#7557)
Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
parent
7237c8e592
commit
ec52db6d20
|
|
@ -103,6 +103,7 @@ type CreateWorktreeArgsWithSystemProvenance = CreateWorktreeArgs & {
|
|||
}
|
||||
import { classifyWorkspaceCreateError } from './workspace-create-error-classifier'
|
||||
import { advertisedUrlWatcher } from '../ports/advertised-url-watcher'
|
||||
import { localhostWorktreeLabelProxy } from '../localhost-worktree-label-proxy'
|
||||
import {
|
||||
assertWorktreeDoesNotContainRegisteredWorktree,
|
||||
canCleanupUnregisteredOrcaLeftoverDirectory,
|
||||
|
|
@ -161,6 +162,9 @@ function removeWorktreeMetadataAndTransientState(store: Store, worktreeId: strin
|
|||
// drop process-local caches before the same ID can point at a new workspace.
|
||||
store.removeWorktreeMeta(worktreeId)
|
||||
advertisedUrlWatcher.forgetWorktree(worktreeId)
|
||||
// Why: drop this worktree's localhost label routes so they don't accumulate
|
||||
// in the proxy's route maps for the rest of the session.
|
||||
localhostWorktreeLabelProxy.unregisterWorktree(worktreeId)
|
||||
deleteWorktreeHistoryDir(worktreeId)
|
||||
// Why: release the removed worktree's PR-refresh aliases so coalesced queue
|
||||
// entries do not retain it for the rest of the session (memory creep).
|
||||
|
|
|
|||
|
|
@ -124,4 +124,33 @@ describe('localhost worktree label proxy', () => {
|
|||
|
||||
expect(result.status).toBe(404)
|
||||
})
|
||||
|
||||
it('drops a worktree label routes on unregisterWorktree, leaving others intact', async () => {
|
||||
const port = await startUpstream((_request, response) => {
|
||||
response.writeHead(200, { 'content-type': 'text/plain' })
|
||||
response.end('ok')
|
||||
})
|
||||
const proxy = new LocalhostWorktreeLabelProxy()
|
||||
const a = await proxy.registerRoute({
|
||||
targetUrl: `http://localhost:${port}/`,
|
||||
projectName: 'Snap Studio',
|
||||
worktreeName: 'feature-a',
|
||||
worktreeId: 'wt-a'
|
||||
})
|
||||
const b = await proxy.registerRoute({
|
||||
targetUrl: `http://localhost:${port}/`,
|
||||
projectName: 'Snap Studio',
|
||||
worktreeName: 'feature-b',
|
||||
worktreeId: 'wt-b'
|
||||
})
|
||||
|
||||
expect((await fetchThroughProxy(a.url)).status).toBe(200)
|
||||
expect((await fetchThroughProxy(b.url)).status).toBe(200)
|
||||
|
||||
proxy.unregisterWorktree('wt-a')
|
||||
|
||||
// The removed worktree's label no longer routes; the other worktree is unaffected.
|
||||
expect((await fetchThroughProxy(a.url)).status).toBe(404)
|
||||
expect((await fetchThroughProxy(b.url)).status).toBe(200)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -49,6 +49,18 @@ export class LocalhostWorktreeLabelProxy {
|
|||
}
|
||||
}
|
||||
|
||||
// Why: routes are added per (worktreeId, targetUrl) but were never removed, so
|
||||
// labels for deleted worktrees accumulated in both maps for the whole session.
|
||||
// Drop them when the worktree is torn down. The shared http.Server stays up.
|
||||
unregisterWorktree(worktreeId: string): void {
|
||||
for (const [label, route] of this.routes) {
|
||||
if (route.worktreeId === worktreeId) {
|
||||
this.routes.delete(label)
|
||||
this.routeKeys.delete(route.routeKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async ensureServer(): Promise<void> {
|
||||
if (this.server && this.listenPort !== null) {
|
||||
return
|
||||
|
|
|
|||
Loading…
Reference in New Issue