feat(daemon): GetVariables + read_sync — the standard mutable-read pattern
EquipmentRuntime::read_sync establishes THE pattern for reading mutable engine state from gRPC/binding threads (Phase 0 item 6): post the read onto the io thread (the model's single owner), wait on a future with a deadline, nullopt => UNAVAILABLE at the RPC edge. Always truthful, no cache to invalidate; milliseconds are irrelevant at SECS rates. GetVariables: name resolution against the service snapshot (empty query = all; unknown name => INVALID_ARGUMENT naming the offender), values read via read_sync, converted by the new from_item reverse conversion (single-element numeric arrays => scalars, multi-element => List; Boolean/Binary/text per format; C2-as-integer and U8>2^63 wrap documented as TODOs). Tests run the engine in run_async — the daemon's PRODUCTION threading mode, previously untested — and round-trip through both conversions: SetVariables (declared-format write) then GetVariables (read) over a real in-process channel. Daemon suite 41 -> 61 assertions. daemon_interop.py gains a live GetVariables round-trip check vs the running daemon (verified green). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -153,6 +153,12 @@ def run(grpc_addr: str, hsms_host: str, hsms_port: int, session_id: int,
|
||||
check("gRPC SetVariables(ChamberPressure=2.5) -> ACCEPT",
|
||||
ack.code == pb.Ack.ACCEPT, pb.Ack.Code.Name(ack.code))
|
||||
|
||||
# Read back through the API: SetVariables -> engine -> GetVariables.
|
||||
snap = stub.GetVariables(pb.VariableQuery(names=["ChamberPressure"]))
|
||||
got = snap.values["ChamberPressure"].real
|
||||
check("gRPC GetVariables round-trips ChamberPressure=2.5",
|
||||
abs(got - 2.5) < 0.01, f"got {got}")
|
||||
|
||||
ack = stub.FireEvent(pb.Event(name="ProcessStarted"))
|
||||
check("gRPC FireEvent(ProcessStarted) -> ACCEPT",
|
||||
ack.code == pb.Ack.ACCEPT, pb.Ack.Code.Name(ack.code))
|
||||
|
||||
Reference in New Issue
Block a user