Commit d6c5428
committed
Fix recurring task double-enqueue caused by wall-clock race condition
When a recurring task's ScheduledTask fires, it computes the next
occurrence by calling `task.next_time`, which uses `Time.current` as the
reference point. If the timer fires slightly early (e.g. 2ms before the
minute boundary), or if there's any sub-second timing drift, `next_time`
can return the *current* slot instead of the next one — causing a
duplicate enqueue and a near-immediate re-fire.
Example with "every minute" schedule:
ScheduledTask fires at 11:59:59.998
1. Enqueues job for 12:00:00 ✓
2. Calls next_time → Time.current is 11:59:59.998
→ fugit returns 12:00:00 (the slot we just enqueued)
→ Schedules new ScheduledTask with ~2ms delay
3. New task fires, enqueues duplicate job for 12:00:00 ✗
Fix: compute the next occurrence from the known run_at of the slot that
just fired, rather than from wall clock time. `next_time_after(run_at)`
passes the time to fugit's `next_time(from)` parameter, so
`next_time_after(12:00:00)` always returns 12:01:00 regardless of what
the wall clock says.1 parent 50defe2 commit d6c5428
4 files changed
Lines changed: 45 additions & 5 deletions
File tree
- app/models/solid_queue
- lib/solid_queue/scheduler
- test
- models/solid_queue
- unit
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
51 | 51 | | |
52 | 52 | | |
53 | 53 | | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
54 | 58 | | |
55 | 59 | | |
56 | 60 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
29 | | - | |
30 | | - | |
| 29 | + | |
| 30 | + | |
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| |||
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
52 | | - | |
53 | | - | |
54 | | - | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
55 | 57 | | |
56 | 58 | | |
57 | 59 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
203 | 203 | | |
204 | 204 | | |
205 | 205 | | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
206 | 218 | | |
207 | 219 | | |
208 | 220 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
20 | 42 | | |
21 | 43 | | |
22 | 44 | | |
| |||
0 commit comments