From 1bf42a7febc2a21c87f010b51f0d96fe663c5740 Mon Sep 17 00:00:00 2001 From: Alex Blank Date: Mon, 1 Jun 2026 23:52:18 +0200 Subject: [PATCH] fix: workspace delete MissingGreenlet + nginx cache-busting - Convert WorkspaceHasInstancesError to store plain dicts instead of SQLAlchemy ORM objects, preventing lazy-load failures outside async session context (MissingGreenlet) - Update both delete endpoints (top-level and nested) to use exc.instances directly since they're already plain dicts - Add no-cache headers for index.html in nginx.conf so browsers always fetch new hashed JS/CSS bundles on deploy --- apps/api/src/api/workspaces.py | 4 ++-- apps/api/src/services/workspace_manager.py | 6 ++++-- apps/web/nginx.conf | 6 ++++++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/apps/api/src/api/workspaces.py b/apps/api/src/api/workspaces.py index 0614475..a5526a8 100644 --- a/apps/api/src/api/workspaces.py +++ b/apps/api/src/api/workspaces.py @@ -91,7 +91,7 @@ async def delete_workspace_top_level( status_code=409, detail={ "message": "Workspace has running tool instances", - "instances": [{"id": str(i.id), "name": i.name} for i in exc.instances], + "instances": exc.instances, }, ) from exc except Exception as exc: @@ -358,7 +358,7 @@ async def delete_workspace( status_code=409, detail={ "message": "Workspace has running tool instances", - "instances": [{"id": str(i.id), "name": i.name} for i in exc.instances], + "instances": exc.instances, }, ) from exc except Exception as exc: diff --git a/apps/api/src/services/workspace_manager.py b/apps/api/src/services/workspace_manager.py index f6ee94b..a9c5532 100644 --- a/apps/api/src/services/workspace_manager.py +++ b/apps/api/src/services/workspace_manager.py @@ -37,7 +37,7 @@ class SyncResult: class WorkspaceHasInstancesError(Exception): """Raised when attempting to delete a workspace with running instances.""" - def __init__(self, instances: list[ToolInstance]) -> None: + def __init__(self, instances: list[dict]) -> None: self.instances = instances super().__init__(f"Workspace has {len(instances)} running tool instance(s)") @@ -139,7 +139,9 @@ class WorkspaceManager: instances = await self._get_instances(workspace, session) if instances and not force: - raise WorkspaceHasInstancesError(instances) + raise WorkspaceHasInstancesError( + [{"id": str(i.id), "name": i.name} for i in instances] + ) # Stop and delete all instances for instance in instances: diff --git a/apps/web/nginx.conf b/apps/web/nginx.conf index 9f6c007..cfc213f 100644 --- a/apps/web/nginx.conf +++ b/apps/web/nginx.conf @@ -15,6 +15,12 @@ server { try_files $uri $uri/ /index.html; } + # Never cache index.html so browsers always fetch new hashed JS/CSS + location = /index.html { + add_header Cache-Control "no-cache, no-store, must-revalidate"; + add_header Pragma "no-cache"; + } + # Cache static assets location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ { expires 1y;