Repository navigation
fix(cbio): refuse and surface a restarted sensor counter - #215
shroominic wants to merge 1 commit into
Conversation
The archive keyed records by index and treated an index it already held as a retransmission, whatever counter that record carried. A sensor whose numbering restarts re-uses those indexes for a different stretch of time, so the new cycle was absorbed as a duplicate -- silently, because a full overlap reported duplicate and set no flag -- while any positions above the old newest index would have been stapled onto the old numbering. The sensor stamps each position once, when it produces that record, and the three captured sessions agree on the stamp for every shared index (index 1 is the same counter in all of them). A position that returns carrying a different counter therefore cannot be a retransmission. Ingest now refuses that batch, keeps the record it already held, stays non-contiguous for the rest of the session, and reports the counterRestart status with the lowest index involved. The session publishes it as a warning, so a restarted counter reads as a restarted counter instead of a sensor that stopped producing records. The anchor was already fail-closed here: it covers only the unbroken 60 s run back from the anchored position, so a restarted stretch is never timestamped. Still open and deliberately not changed: the app resumes history above the newest index it holds, so a restart is only observed when an overlapping batch arrives. Probing for it costs a read on every connection and belongs in its own change.
|
Carried into #209 (head Claims verified against the branch, not taken from the description. I ran a temporary probe against the pre-fix tree and then against the fix, on the same worktree (
The refusal path returns before any mutation of One precision note, recorded rather than changed: Closing as carried. Carrying PR: #209. |
Why
The fresh GS1 capture read raw index
1..32where the earlier one read1..10969, which looked like the sensor's archive counter restarting. It did not: every capture stamps the same index with the same counter.Index 7537 sits exactly 7536 minutes after index 1 on the same 60 s-per-index line, so the counter is monotonic and the sensor was neither replaced nor reset. The depth difference is the harness:
_runSessionsends one06 08and waits a fixedCBIO_STREAM_SECONDSwindow, so 10,969 records or 32 records arrive depending on throughput, and both reportcompleted.The archive, however, could not have told the difference.
CbioHistoryArchive.ingestkeyed on index alone:duplicatewith no flag, so a genuinely new cycle would be dropped silently;contiguousstayed true in both cases.What changed
cbio_history_archive.dart: ingest compares an incoming record's own counter against the record already held for that index. The sensor stamps a position once when it produces it, and the captures show that stamp is stable across sessions, so a differing counter is a restart rather than a retransmission. The batch is refused (nothing merged, nothing overwritten),contiguousclears, and the archive reportsCbioArchiveIngestStatus.counterRestartwithsawCounterRestartandcounterRestartIndex.cbio_glucose_session.dart: publishescbio.raw.counter-restart index=<n> records=<n> contiguous=falseas a warning and refreshes sync state, so a restart is visible instead of looking like a sensor that stopped producing records.The anchor needed no change:
deriveCbioIndexTimeAnchoralready covers only the unbroken 60 s run back from the anchored position (cbio_index_time_anchor_test.dart, "covers only the unbroken counter step back from the anchor"), so a restarted stretch is never timestamped.RED to GREEN
Library reverted with the new tests kept:
With the change: archive tests 16/16 including the three new ones, and the session test asserts the history stays
[1, 2, 3]with the original values while acounter-restartwarning is published.Gates
make format-check(0 changed),make lint(no issues),make test-unit(app 541 passed,cgm_cbio133 passed / 2 skipped), plusdart analyzeclean inpackages/cgm_cbio. Nothing merges tomain; units stayunverified; no vendor bytes or addresses anywhere.Not in this change
The app resumes history at
resumeOffset + 1, so a restart is observed only when an overlapping batch actually arrives. Probing for it on every connection costs an extra read and can pull the whole archive back, so it deserves its own change rather than riding along here.Closes #214.