fix(schedules): locking schedules to prevent double runs#1854
Merged
icecrasher321 merged 3 commits intostagingfrom Nov 8, 2025
Merged
fix(schedules): locking schedules to prevent double runs#1854icecrasher321 merged 3 commits intostagingfrom
icecrasher321 merged 3 commits intostagingfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
There was a problem hiding this comment.
Greptile Overview
Greptile Summary
This PR implements optimistic locking for schedule execution to prevent double runs. The approach uses a new lastQueuedAt timestamp column that gets set when schedules are queued (line 30 in route.ts), and the query condition ensures only schedules where lastQueuedAt < nextRunAt or lastQueuedAt IS NULL are selected (lines 38-40).
Critical Issue Found:
- The lock (
lastQueuedAt) is never released after execution completes, which will cause all schedules to stop running after their first execution - Missing
lastQueuedAt: nullin three places: successful execution (line 650), failed execution (line 682), and error catch block (line 727)
Positive Changes:
- Major code refactoring improves maintainability with well-named helper functions
- Proper use of UPDATE...RETURNING pattern provides atomic locking at database level
- Schema change is clean and appropriate
Confidence Score: 0/5
- Critical bug will break all schedule functionality after first execution
- The locking mechanism is incomplete -
lastQueuedAtis set during queuing but never cleared after execution completes. This means every schedule will run exactly once and then become permanently locked, breaking the entire scheduling system. This is a production-breaking bug that must be fixed before merge. - apps/sim/background/schedule-execution.ts requires immediate attention - three missing
lastQueuedAt: nullupdates will break all schedules
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| apps/sim/app/api/schedules/execute/route.ts | 3/5 | Implements optimistic locking via UPDATE with RETURNING for schedule queueing, but has a critical issue where lock is never released in execution phase |
| apps/sim/background/schedule-execution.ts | 2/5 | Major refactor adds helper functions and lock release logic, but missing lock release on successful execution path creates deadlock potential |
| packages/db/schema.ts | 5/5 | Added lastQueuedAt column to support optimistic locking mechanism for schedule execution |
Sequence Diagram
sequenceDiagram
participant Cron
participant RouteAPI as Execute Route
participant DB as Database
participant Executor as Schedule Executor
Cron->>RouteAPI: GET /api/schedules/execute
RouteAPI->>DB: UPDATE workflow_schedule<br/>SET lastQueuedAt = now<br/>WHERE nextRunAt <= now<br/>AND (lastQueuedAt IS NULL OR lastQueuedAt < nextRunAt)<br/>RETURNING *
DB-->>RouteAPI: Return locked schedules
Note over RouteAPI,DB: Optimistic locking:<br/>Only schedules not already queued
loop For each schedule
RouteAPI->>Executor: Queue execution job
Executor->>Executor: Check rate limits & usage
Executor->>Executor: Load workflow & execute
alt Success
Executor->>DB: UPDATE schedule<br/>SET lastRanAt = now,<br/>nextRunAt = calculated,<br/>failedCount = 0<br/>❌ MISSING: lastQueuedAt = null
Note over Executor,DB: BUG: Lock never released!
else Failure
Executor->>DB: UPDATE schedule<br/>SET failedCount++,<br/>nextRunAt = calculated<br/>❌ MISSING: lastQueuedAt = null
else Error
Executor->>DB: UPDATE schedule<br/>SET failedCount++<br/>❌ MISSING: lastQueuedAt = null
end
end
RouteAPI-->>Cron: Return success
3 files reviewed, 3 comments
waleedlatif1
pushed a commit
that referenced
this pull request
Nov 9, 2025
* fix(schedules): locking schedules to prevent double runs * add migration file * fix
waleedlatif1
pushed a commit
that referenced
this pull request
Nov 12, 2025
* fix(schedules): locking schedules to prevent double runs * add migration file * fix
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Schedules queuing and execution should be in a locked section.
Type of Change
Testing
Tested manually by running cron
Checklist