feat(workspaces): store snapshot build facts in SQL - #1580
Conversation
Record how long each Sandbox snapshot build takes in the Redis cache and surface it on the Workspace details page. Co-Authored-By: David Cramer <david@sentry.io>
Record buildDurationMs on every cached snapshot and show it on the Workspace details page. Bump the Redis cache key so old entries miss cleanly instead of carrying a nullable fallback. Co-Authored-By: David Cramer <david@sentry.io>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Dashboard visual evidenceMode: path-selected Triggered by:
Conversations · desktopConversations · mobileConversation detail · desktopConversation detail · mobileSystem · desktopFull-page screenshots from the mock dashboard. Not a pixel-diff gate. |
Record snapshot id, generation time, build duration, and profile hash on the Workspace row after a successful prepare. Serve the dashboard details page from SQL so Redis TTL misses do not erase operator facts. Clear the recorded snapshot when the recipe changes. Co-Authored-By: David Cramer <david@sentry.io>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit fcdbb75. Configure here.
| await replaceWorkspaceRepos(db, id, recipe.repos); | ||
| return rows[0]; |
There was a problem hiding this comment.
Missing rows[0] guard after workspace update allows FK violation on concurrent delete
updateWorkspace does not verify that UPDATE ... RETURNING produced a row before calling replaceWorkspaceRepos. If the workspace is concurrently deleted between the earlier SELECT and the UPDATE, the update affects zero rows. replaceWorkspaceRepos then attempts to insert repo rows for a nonexistent workspace, violating the junior_workspace_repos.workspace_id foreign key and raising a 500 instead of the expected 404.
Evidence
updateWorkspacehas an initialSELECTguard (if (!existing) return undefined) but does not check theUPDATE ... RETURNINGresult before invokingreplaceWorkspaceRepos.- Under PostgreSQL
READ COMMITTED(the executor’s defaultBEGINisolation), a concurrentDELETEthat commits before theUPDATEcauses the update to affect zero rows, leavingrows[0]undefined. replaceWorkspaceReposdeletes existing repos and inserts new ones with the sameworkspaceId; because the workspace no longer exists, the FK fromjunior_workspace_repos.workspace_idtojunior_workspaces.idthrows error23503.- The
PUT /:idroute expectsupdateWorkspaceto returnundefinedwhen the workspace does not exist so it can emit a404; the unhandled FK violation instead propagates as a500.
Identified by Warden · code-review · 2WW-BTH






Record Workspace snapshot operator facts in SQL and show build time on the Workspace details page.
Why
Build duration is durable dashboard data. Redis is the hot snapshot registry and can TTL out, so it is a weak source of truth for the UI.
What
snapshot_id,snapshot_generated_at,snapshot_build_duration_ms, andsnapshot_profile_hashonjunior_workspacesbuildDurationMsthere for the hot pathVerify
tests/integration/api/workspaces/routes.test.tstests/component/sandbox/snapshot/resolve.test.tstests/component/misc/sandbox-executor.test.tstests/unit/sandbox/snapshot/profile.test.tsRequested by David Cramer.
--
View Junior Session [Sentry]