fix(cassettes): order ATM state events, and reconcile the bay set #44
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/cassette-state-reconcile"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #43
Phase 2 of the cassette synchronization audit, agreed with the bitspire side. No wire format change, so it ships independently of aiolabs/bitspire#104.
Ordering. The consumer's gate compared the incoming event id against the id on a single arbitrary row (SELECT ... LIMIT 1, no ORDER BY) — a one-event memory, so a re-delivered A, B, A applied three times. created_at was parsed, written to state_at and never compared, so an event arriving late overwrote newer state. Events are now applied only when strictly newer than the oldest stamp on file, compared as unix floats because SQLite returns integers, Postgres returns timestamps and the incoming value is tz-aware.
Reconciliation. Positions absent from the payload are now deleted. A machine whose bay count shrank used to leave a stale row, which made every later operator publish fail position-set validation with no remedy but DELETE FROM by hand.
On atomicity: the plan called for one transaction, but Connection.execute in the LNbits data layer commits per call, so that is not available here without reaching into internals. The gate compares against the oldest stamp instead, so a crash mid-apply is re-applied on the next event rather than mistaken for a complete one, and the ATM's heartbeat makes it converge.
Also renames apply_bootstrap_state to apply_reported_state and corrects the module comments: there has never been a once-per-machine guard, so calling it a one-shot bootstrap consumer described something the code did not do.
238 tests pass; ruff clean. The branch leaves the repo's pre-existing formatting state untouched.