Harden live material polling state
This commit is contained in:
@@ -7,8 +7,9 @@ production-order context, and calculation state.
|
||||
|
||||
## Status
|
||||
|
||||
This repository includes a read-only ENLYZE API exploration CLI. It contains
|
||||
no verified ENLYZE operation wrappers, database migrations, or HTTP endpoints.
|
||||
This repository includes an ENLYZE exploration CLI, a production-run/timeseries
|
||||
gateway, and single-cycle live material polling with JSON state persistence.
|
||||
Database migrations, a continuous polling runner, and HTTP endpoints remain pending.
|
||||
|
||||
## Intended flow
|
||||
|
||||
@@ -76,7 +77,7 @@ Call `process(sample)` or `process_many(samples)` on the same instance for live
|
||||
input, replay, or successive chunks. Both use the same calculation. The immutable
|
||||
`state` snapshot exposes cumulative kg, integrated running seconds, last timestamp
|
||||
(UTC), last rate, last gate, and whether the latest gate is active. State restoration
|
||||
and persistence are not implemented yet. Naive timestamps and non-finite values
|
||||
and JSON persistence are supported. Naive timestamps and non-finite values
|
||||
are rejected; backwards timestamps raise without changing state. Duplicate
|
||||
timestamps add no consumption but replace the baseline in arrival order.
|
||||
Finite negative material rates are currently accepted and decrease cumulative
|
||||
@@ -94,7 +95,25 @@ is gated by `Geschwindigkeit Gesamtanlage > 0.5 m/min`. With the explicit
|
||||
2,672 common samples yield **5.205555556 h** and **5,180.127150811 kg** for run
|
||||
00842, matching the previous manual calculation's rounded results. Synthetic
|
||||
tests verify equivalence to manual interval integration without local captures
|
||||
or live ENLYZE access. Production polling, Grafana, and Bento 1 are not implemented.
|
||||
or live ENLYZE access. Grafana and Bento 1 remain pending.
|
||||
|
||||
`MaterialPollingService.poll_once(now=...)` starts at the open run's start or
|
||||
resumes inclusively at its last processed timestamp. Duplicate boundary samples
|
||||
add no time. A new run UUID for the same order retains cumulative kg and running
|
||||
seconds but resets the temporal baseline; different orders and machines have
|
||||
separate state. Empty responses add no consumption. Naive `now` is rejected;
|
||||
no open run or a window beginning after `now` returns `None` without saving.
|
||||
|
||||
`JsonMaterialStateStore` uses deterministic SHA-256 filenames derived from the
|
||||
machine/order pair, preventing path traversal and sanitized-name collisions.
|
||||
It flushes and fsyncs a temporary file in the state directory before atomic
|
||||
replacement; a failed write leaves the previous primary file intact. Missing
|
||||
state returns `None`; malformed JSON or state raises `ValueError` with file
|
||||
context. Use an ignored runtime directory and one polling writer per state key;
|
||||
atomic replacement does not coordinate concurrent read-modify-write cycles.
|
||||
Files from the earlier uncommitted sanitized-filename prototype are not loaded
|
||||
under the new names. The gateway rejects ambiguous open runs, naive windows,
|
||||
and missing columns or malformed records instead of silently skipping them.
|
||||
|
||||
## Peak-cycle detection
|
||||
|
||||
|
||||
Reference in New Issue
Block a user