Files
tuliprox/shared
DarkBreakpoint 154112de52 feat(dvr)!: persist the recording queue in a recoverable B+Tree
The queue was a single JSON document rewritten in full on every mutation.
That cannot survive a torn write, and a change to the record shape had no
upgrade path other than refusing to load — load_from_disk fails closed on
an unknown schema_version, which would have stranded every operator on a
version bump.

Replace it with RecordingRepository: one record per task in a B+Tree, with
every write routed through BPlusTreeRecoveryJournal. A deleted or corrupt
database is now rebuilt from the recovery history instead of being lost,
and a future record-shape change becomes a migration step rather than a
refusal to start.

- backend/repository/src/recording_repository.rs owns the persisted shape
  and RecordingRecoverySchema V1. It knows nothing about execution: the DVR
  decides what a task means and hands over a set to commit atomically.
- commit() diffs the candidate against what is stored, so the recovery
  journal stays proportional to what actually changed rather than to the
  size of the queue.
- The partition (queued/scheduled/active/finished) is stored explicitly.
  Deriving it from the state would be wrong: `active` is a distinct slot
  and two tasks in the same state can sit in different partitions.
- Repository calls run on spawn_blocking; it fsyncs both the journal and
  the B+Tree, so it must not run on a runtime worker thread.

RecordingTaskState moves to shared, along with the label() helper and the
TransferStatusDto conversion that were inherent impls in the DVR. The
repository crate cannot depend on the DVR, and the state is part of the
persisted contract either way.

Recovery generations are written under backup_dir, so they survive the loss
of the storage volume.

There is no migration from recordings_state.json: an existing queue is
discarded on upgrade.
2026-09-01 07:52:22 -05:00
..
2026-08-28 19:17:39 +02:00
2026-08-27 15:36:23 +02:00