improvement(deployment): solve multiple client side races, and deployed state management issues#4502
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryHigh Risk Overview Shifts chat/form deployment routes to use Hardens background processing: scheduled execution claims are now transactional with Improves reliability of long-running workers by expanding outbox processing to include workflow deployment handlers, adding runtime budget controls, and changing handler timeouts to keep leases (avoiding overlapping retries) plus a new Reviewed by Cursor Bugbot for commit f542637. Configure here. |
Greptile SummaryThis PR makes deployment state server-canonical and race-safe by moving all external side-effects (webhook setup, schedule creation, MCP tool sync) out of long-running transactions and into a durable transactional outbox. Deploy, redeploy, undeploy, and version-activate now write an outbox event atomically with the state change, process it immediately after commit, and fall back to the background cron worker if the inline attempt fails.
Confidence Score: 5/5Safe to merge — the outbox approach is well-structured and the inline-then-cron fallback makes side-effects durable even if immediate processing is preempted. The core deploy/undeploy/activate flows now write state and queue side-effects atomically, eliminating the main class of races. Both findings are minor: an ignored lock return value that only matters for concurrently deleted workflows, and an unreferenced counter in the operation queue store. Neither affects correctness on the happy path. apps/sim/lib/workflows/persistence/utils.ts — saveWorkflowToNormalizedTables acquires but ignores the lockWorkflowForUpdate result. Important Files Changed
Sequence DiagramsequenceDiagram
participant Client
participant DeployAPI as Deploy API
participant DB as Database (Tx)
participant Outbox as Outbox Service
participant CronWorker as Cron Worker
participant Providers as Webhooks/Schedules/MCP
Client->>DeployAPI: POST /deploy
DeployAPI->>DB: BEGIN TRANSACTION
DB->>DB: lockWorkflowForUpdate (FOR UPDATE)
DB->>DB: validate schedules + webhooks
DB->>DB: INSERT workflowDeploymentVersion
DB->>DB: "UPDATE workflow.isDeployed = true"
DB->>DB: INSERT outbox_event (SYNC_ACTIVE_SIDE_EFFECTS)
DB->>DB: COMMIT
DeployAPI->>Outbox: processOutboxEventById (inline, FOR UPDATE SKIP LOCKED)
alt Inline processing succeeds
Outbox->>Providers: saveTriggerWebhooks + createSchedules + syncMcpTools
Outbox->>DB: INSERT outbox_event (CLEANUP_INACTIVE_SIDE_EFFECTS)
DeployAPI->>Client: 200 OK
else Lease held by cron or timeout
DeployAPI->>Client: 200 OK (with warning)
CronWorker->>Outbox: process pending outbox events
Outbox->>Providers: saveTriggerWebhooks + createSchedules + syncMcpTools
end
Note over Outbox,Providers: Each step re-checks isActive before proceeding
Reviews (2): Last reviewed commit: "address comments" | Re-trigger Greptile |
|
@greptile |
|
bugbot run |
|
bugbot run |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit f542637. Configure here.

Summary
Makes deployment state server-canonical and race-safe: deploy/redeploy/undeploy now reconcile against persisted workflow state, use last-write-wins semantics, and move external provider side effects through an outbox instead of holding long DB transactions. It hardens background execution across multiple app tasks with durable outbox leases, idempotent schedule enqueueing for both database and Trigger.dev backends, version-pinned scheduled workflow execution, and safer webhook cleanup/retry behavior.
Type of Change
Testing
Tested manually
Checklist