fix(archive): preserve prepared sessions across restarts

This commit is contained in:
DCCONSTRUCTIONS
2026-07-18 11:08:27 +03:00
parent aa3680948f
commit 574a494759
13 changed files with 398 additions and 132 deletions
+32 -23
View File
@@ -57,22 +57,26 @@ not mutate playback state, so changing accumulation, size, color or visibility
does not pause the active replay or replace its camera view.
Completed and recovered sessions are discovered on startup and by the catalog
reconciler, then deduplicated into one bounded, single-worker preparation queue.
The worker validates the native source, exports point/pose data, verifies source
stability and both SHA-256 digests, finalizes once, and atomically publishes the
reconciler. The first scan is only a historical baseline: it never enqueues the
existing archive. A session that becomes finalized after that baseline is
deduplicated into the bounded, single-worker preparation queue. The worker
validates the native source, exports point/pose data, verifies source stability
and both SHA-256 digests, finalizes once, and atomically publishes the
digest-bound derived RRD plus its cache sidecar. Before the same job becomes
`ready`, it also parses and validates every archived camera index and retains
the immutable manifest generation in memory. The catalog exposes preparation
state and progress while this runs; a recording URL and camera descriptors are
returned only after the complete launch generation has passed validation.
`ready`, it also parses and validates every archived camera index and publishes
the immutable media-manifest sidecar. The catalog exposes preparation state and
progress while this runs; a recording URL and camera descriptors are returned
only after the complete launch generation has passed validation.
Preparation is a backend lifecycle, not a viewer action: sealing or recovering
a native session makes it eligible for the reconciler, which builds the derived
RRD once in the background. Reopening, seeking or changing the workspace reads
that prepared artifact and never reruns conversion. A cold process may validate
an existing cache and rebuild its in-memory camera manifest in the worker, but
no replay, status, RRD or manifest request hashes native evidence or parses a
camera index synchronously.
Preparation is a backend lifecycle, not a viewer computation. Reopening,
seeking, refreshing the catalog or changing the workspace never reruns a
published conversion. After a process restart, a catalog/replay read restores a
complete compatible RRD and camera package from its durable sidecars using
bounded schema and stat-identity checks; it does not hash native evidence, parse
camera indexes or invoke the exporter. A historical session whose package is
missing, stale or from an incompatible cache schema remains cold. Only an
explicit replay/RRD request schedules that one session for preparation; listing
the catalog and finalizing another session do not schedule it.
The session menu uses three operator indicators:
@@ -80,6 +84,7 @@ The session menu uses three operator indicators:
| --- | --- | --- |
| Solid green + `Готово` | `ready` | Verified RRD is available. |
| Pulsing green + `Обработка` | `queued`, `validating`, `exporting`, `finalizing` | Background preparation is active. |
| Solid gray + `Подготовить` | replayable session with no compatible published package | No work is running; choosing the row schedules this session only. |
| Dim gray + `Ошибка` | failed, cancelled, non-replayable or invalid session | No launchable recording; inspect the message or retry. |
Saved-session status never uses yellow or red. Switching sessions aborts only
@@ -93,7 +98,8 @@ Later openings reuse a verified, digest-bound cache. Derived RRD cache v9 is
intentionally incompatible with v8 and older generations. In addition to plugin
and ordered-artifact identity, it binds the durable clock origin and active
envelope and materializes real `session_time = 0` origin and sealed completion
rows. Older generations are rebuilt once in the background.
rows. Older generations remain cold after startup and are rebuilt only when an
operator explicitly opens that session.
The browser may use the strict `source_url` with `If-Match`, while the embedded
Rerun loader uses the canonical `viewer_source_url` whose lowercase SHA-256
`generation` query is bound to the same launch descriptor. A missing or stale
@@ -194,11 +200,13 @@ Native `.k1mqtt` bytes with aligned metadata, the capture-clock artifacts and
canonical camera fMP4 archives are the evidence source of truth. The derived RRD
contains every decodable point and pose frame plus every valid `ModelingReport`
distance/speed/scan-time sample from that source, but remains a rebuildable view
rather than an evidence master. A cache entry is rebuilt only when native source
identity/digests change or an incompatible derived-data export revision is
introduced. A UI blueprint or workspace-layout revision never invalidates or
rewrites the data RRD. Cache v8 and older payloads are not reusable as v9 because
they do not bind both real capture-envelope endpoints.
rather than an evidence master. A cache entry is eligible for rebuild only when
native source identity/digests change or an incompatible derived-data export
revision is introduced. Historical entries are not rebuilt during startup or
because another session is finalized; an explicit open schedules the affected
entry. A UI blueprint or workspace-layout revision never invalidates or rewrites
the data RRD. Cache v8 and older payloads are not reusable as v9 because they do
not bind both real capture-envelope endpoints.
`ModelingReport` time is the device's `ScanTime` counter at two ticks per second;
distance and speed are the reported `MoveDistance`/`MoveSpeed` values. Live state
@@ -318,9 +326,10 @@ written under the private derived cache with a schema, generation and checksum.
Publication uses a private temporary file, file and directory `fsync`, and atomic
rename; startup scavenges crash-left temporary files. A restart reuses this
sidecar after confined O(n) stat validation, without rereading, hashing or parsing
media. A missing, corrupt or stale sidecar is rebuilt only by the background
worker. No replay, status, manifest or payload request performs conversion or
recalculates these intervals.
media. A missing, corrupt or stale sidecar remains cold until an explicit open
schedules the complete session package in the background worker. No catalog,
status, manifest or payload request itself performs conversion or recalculates
these intervals.
Every derived RRD contains a real `session_time = 0` row at the internal
`/__mission_core/session_origin` entity. The anchor is deliberately outside