feat(cassettes): persist the machine's counts-uncertain marker
The machine has been publishing counts_uncertain_since since v1 of the state document and spirekeeper has been parsing it into a field nobody read. That defeats the point of the marker: it exists so a human opens the bay and recounts. A dispenser can throw, or time out, after notes have physically moved. The machine cannot know how many left, so rather than decrement a number it would be guessing at, it stamps the moment (bitspire ADR-004, decision 3). m014 gives that stamp a home on dca_machines, and the consumer mirrors it on every state event. Stored on the machine rather than the bay because the uncertainty is about the dispense as a whole; a multi-bay dispense that fails midway gives no reliable way to attribute it to one position. Written through even when the machine reports None. The machine clearing the marker is as important as setting it — the operator recounted, the bay is trustworthy again — and a banner that never goes away is a banner nobody reads.
This commit is contained in:
parent
2ac3e2064e
commit
c76a1bb125
5 changed files with 112 additions and 1 deletions
|
|
@ -317,3 +317,40 @@ class TestRecordOpAcknowledgements:
|
|||
"m1", state_payload(applied_ops=["late-ack"]), mark
|
||||
)
|
||||
assert seen == ["late-ack"]
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# _record_counts_uncertainty — the machine saying "don't trust these counts"
|
||||
# =============================================================================
|
||||
|
||||
|
||||
class TestRecordCountsUncertainty:
|
||||
@pytest.mark.asyncio
|
||||
async def test_stores_the_reported_moment_as_utc(self):
|
||||
calls = []
|
||||
|
||||
async def setter(machine_id, since):
|
||||
calls.append((machine_id, since))
|
||||
|
||||
await tasks._record_counts_uncertainty(
|
||||
"m1", state_payload(counts_uncertain_since=1790110546), setter
|
||||
)
|
||||
assert len(calls) == 1
|
||||
machine_id, since = calls[0]
|
||||
assert machine_id == "m1"
|
||||
assert since is not None
|
||||
assert since.tzinfo is not None
|
||||
assert int(since.timestamp()) == 1790110546
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_clears_the_marker_when_the_machine_is_confident_again(self):
|
||||
"""A banner that never goes away is a banner nobody reads. The
|
||||
machine dropping the field is how the operator learns the recount
|
||||
took, so None must be written through rather than skipped."""
|
||||
calls = []
|
||||
|
||||
async def setter(machine_id, since):
|
||||
calls.append((machine_id, since))
|
||||
|
||||
await tasks._record_counts_uncertainty("m1", state_payload(), setter)
|
||||
assert calls == [("m1", None)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue