summaryrefslogtreecommitdiffhomepage
path: root/packages/transport-http/src/app.ts
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-28 14:35:08 +0900
committerAdam Malczewski <[email protected]>2026-06-28 14:35:08 +0900
commit076edf7d1dfc4dc818f173f751dcb1e57b5baaeb (patch)
tree6c6372f58cfff94412f1c16d5c97fdb90ccd22c1 /packages/transport-http/src/app.ts
parenta610b93acb6c3f8f07a4fea9d0cd298fa3159589 (diff)
downloaddispatch-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.ts32
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);