| β¦ | β¦ | @@ -744,33 +830,132 @@ export const layer = Layer.effect( | |
| 837 | + | // edits each keep their own columns. | |
| 838 | + | const update: ScheduledTaskService["Service"]["update"] = (input) => | |
| 839 | + | Effect.gen(function* () { | |
| 840 | + | const task = yield* sql | |
π High scheduledTasks/ScheduledTaskService.ts:840
A scheduled task can still be dispatched after update commits enabled: false or a future next_run_at: runTask performs its enabled/due check before markRunning, so a poll that already passed that check marks the task running and dispatches it despite the user's pause or reschedule. Revalidate the current row atomically with markRunning (and only dispatch when that conditional update succeeds).
No longer relevant as of 56f7accab8ae2600abd42e6fd337dc28ecd9e042
Fixed in 56f7accab8: the due/enabled revalidation and markRunning now share one sql.withTransaction, so a pause, postpone, or delete committed between the poll-read and the mark wins β the stale dispatch can no longer fire.