re-acquire global lock for transactions from scheduled fns - #114
Conversation
commit: |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: get-convex/coderabbit/.coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis PR replaces DatabaseFake’s listener-based scheduled-function completion with a per-test Scheduler that tracks fired scheduled-callback promises. setTimeout callbacks now run outside nested-transaction ALS via nestedTxStorage.exit and register their execution promises; scheduled-function state transitions are performed inline. finishInProgressScheduledFunctions and finishAllScheduledFunctions now drain the Scheduler while coordinating timer advancement. Added scheduler test helpers in convex/scheduler.ts and refactored scheduler tests to centralize fake/real timer lifecycle. Sequence Diagram(s)sequenceDiagram
participant Test as Test Code
participant Timer as setTimeout
participant ALS as nestedTxStorage
participant Scheduler as Scheduler
participant DB as _scheduled_functions
participant UDF as Scheduled UDF
Test->>DB: schedule job (pending)
DB->>Timer: setTimeout fires
Timer->>ALS: exit() then invoke callback
ALS->>Scheduler: add(executionPromise)
Scheduler->>DB: read job row and patch pending->inProgress
Scheduler->>UDF: invoke scheduled UDF
UDF->>DB: patch inProgress->success | inProgress->failed
UDF-->>Scheduler: executionPromise settles
Scheduler->>Scheduler: remove(executionPromise)
Test->>Scheduler: finishInProgressScheduledFunctions() awaits drain
Possibly Related PRs
Suggested Reviewers
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |

Currently a scheduled function uses setTimeout, which can fire mid-way through a transaction if real timers are used.
And scheduling multiple functions can also race. This is because they detect the current global transaction lock and infer they're a nested transaction call.
This PR waits until the nested transaction has finished before starting the next scheduled function, allowing it to use the global transaction lock to serialize scheduled mutations, regardless of where they're scheduled from or whether real timers are used or not.
Fixes #112
Closes #82