diff options
| author | Adam Malczewski <[email protected]> | 2026-06-28 14:35:08 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-28 14:35:08 +0900 |
| commit | 076edf7d1dfc4dc818f173f751dcb1e57b5baaeb (patch) | |
| tree | 6c6372f58cfff94412f1c16d5c97fdb90ccd22c1 /packages/transport-http/src/app.ts | |
| parent | a610b93acb6c3f8f07a4fea9d0cd298fa3159589 (diff) | |
| download | dispatch-076edf7d1dfc4dc818f173f751dcb1e57b5baaeb.tar.gz dispatch-076edf7d1dfc4dc818f173f751dcb1e57b5baaeb.zip | |
fix(workspace-star): clean up starred cache on workspace delete + warn when concurrency service absent
Bug 1 (MEDIUM): In-memory starred cache leaks IDs for deleted workspaces.
The starredWorkspaces Set in the concurrency manager never cleaned up when a
workspace was deleted. FIX: the DELETE /workspaces/:id route now calls
concurrencyService.notifyWorkspaceStarred(id, false) after deleting, so the
deleted workspace ID is removed from the in-memory cache (preventing stale
IDs and preventing a re-created workspace with the same slug from inheriting
the old starred state).
Bug 2 (MEDIUM): Stale in-memory priority when concurrency extension is absent.
If provider-concurrency is not loaded, the star toggle persisted but the
in-memory priority cache was never updated (the optional chaining ?. silently
skipped the call). Already-queued agents kept their old priority until
restart. FIX: the star/unstar routes now check if concurrencyService is
defined and log a warning when it is absent, making the degraded behavior
visible. The starred state still persists correctly — it just does not
affect in-memory scheduling until the extension is loaded.
Tests: +5 (star round-trip with concurrency notification, invalid slug 400,
delete cleans up cache, absent-service warning log). All 1970 tests pass.
Diffstat (limited to 'packages/transport-http/src/app.ts')
| -rw-r--r-- | packages/transport-http/src/app.ts | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/packages/transport-http/src/app.ts b/packages/transport-http/src/app.ts index 0d42e06..ebbf536 100644 --- a/packages/transport-http/src/app.ts +++ b/packages/transport-http/src/app.ts @@ -1480,6 +1480,10 @@ export function createApp(opts: CreateServerOptions): Hono { try { const { closedCount } = await opts.conversationStore.deleteWorkspace(workspaceId); + // Clean up the in-memory starred cache so a deleted workspace's ID + // doesn't linger (and so a future workspace re-created with the same + // slug doesn't inherit the stale starred state). + opts.concurrencyService?.notifyWorkspaceStarred(workspaceId, false); log.info("workspaces: deleted", { workspaceId, closedCount }); const response: DeleteWorkspaceResponse = { workspaceId, closedCount }; return c.json(response, 200); @@ -1509,8 +1513,21 @@ export function createApp(opts: CreateServerOptions): Hono { try { const workspace = await opts.conversationStore.setWorkspaceStarred(workspaceId, true); // Notify the concurrency service's in-memory cache so queued agents - // from this workspace jump ahead immediately. - opts.concurrencyService?.notifyWorkspaceStarred(workspaceId, true); + // from this workspace jump ahead immediately. When the concurrency + // service is absent (extension not loaded), the starred state is + // persisted but the in-memory priority cache is NOT updated — log a + // warning so the degraded behavior is visible (queued agents keep + // their old priority until restart or the extension is loaded). + if (opts.concurrencyService !== undefined) { + opts.concurrencyService.notifyWorkspaceStarred(workspaceId, true); + } else { + log.warn( + "workspaces: starred but concurrency service is not loaded — priority cache not updated", + { + workspaceId, + }, + ); + } log.info("workspaces: starred", { workspaceId }); const response: WorkspaceResponse = workspace; return c.json(response, 200); @@ -1532,7 +1549,16 @@ export function createApp(opts: CreateServerOptions): Hono { } try { const workspace = await opts.conversationStore.setWorkspaceStarred(workspaceId, false); - opts.concurrencyService?.notifyWorkspaceStarred(workspaceId, false); + if (opts.concurrencyService !== undefined) { + opts.concurrencyService.notifyWorkspaceStarred(workspaceId, false); + } else { + log.warn( + "workspaces: unstarred but concurrency service is not loaded — priority cache not updated", + { + workspaceId, + }, + ); + } log.info("workspaces: unstarred", { workspaceId }); const response: WorkspaceResponse = workspace; return c.json(response, 200); |
