2.0 KiB
status, priority, issue_id, tags, dependencies
| status | priority | issue_id | tags | dependencies | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| pending | p2 | 184 |
|
Upstash /pipeline is not transactional - partial failure leaves inconsistent snapshot state
Problem Statement
scripts/regional-snapshot/persist-snapshot.mjs:56-73 issues 6 commands via /pipeline (SET timestamp, SET by-id, SET latest, ZADD index, ZREMRANGEBYSCORE, DEL live). Pipeline executes sequentially but not atomically. Partial failure leaves inconsistent state (latest pointer to a snapshot not in the index, or vice versa). Phase 1 may rely on the index to enumerate accessible snapshots and trip on the inconsistency.
Findings
/pipelineis batched but not transactional on Upstash- 6 writes cover 3 state shapes: timestamp view, id view, latest pointer, index
- Partial failure surfaces as silent drift between pointer and index
- No repair job exists
Proposed Solutions
Option 1: Use /multi-exec for atomic persistence
Upstash supports MULTI/EXEC transactions via /multi-exec endpoint.
Pros: All-or-nothing guarantee; no inconsistent state Cons: Slightly more expensive; needs a small client change Effort: Medium Risk: Low
Option 2: Document partial-persist contract + repair job
Accept non-atomicity; write a repair job that reconciles latest/index on next run.
Pros: Keeps existing pipeline code Cons: Runtime readers still see drift until repair fires; more complex Effort: Medium Risk: Low
Recommended Action
Technical Details
File: scripts/regional-snapshot/persist-snapshot.mjs:56-73
Commands in the current pipeline:
- SET snapshot:ts:{region}:{ts}
- SET snapshot🆔{region}:{id}
- SET snapshot:latest:{region}
- ZADD snapshot:index:{region}
- ZREMRANGEBYSCORE snapshot:index:{region}
- DEL snapshot:live:{region}
Acceptance Criteria
- Use /multi-exec for atomic persistence OR
- Document the partial-persist contract and add a repair job
Work Log
Resources
- PR #2940
- PR #2942