Commit Graph

4 Commits

Author SHA1 Message Date
Joseph Doherty e03f343f14 fix(mtconnect): read-path restart publishes the new cursor; document the review trade-offs (review m6, m1, m4, m5, m8)
- m6: a /current read that sees a new Agent instanceId now also publishes the new
  process's cursor (generation-checked, captured with the read's session), so a
  later subscription does not open at the dead instance's sequence and flicker
  through a clear + re-baseline. Pinned in the T-2 test.
- Documented (code + docs/drivers/MTConnect.md): m1 the bounded stale-read window of
  a stream stalled without failing; m4 a refused multi-pair PUT's retry may re-send
  an already-applied pair (harmless); m5 a non-Agent 200 now reads reachable to the
  ping; m8 a refused raised count takes one transient blip before the step-back.
- m10 confirmed: no host key is persisted (DriverHostStatus dropped, #521) - the
  redacted HostName only changes an in-memory /hosts key for a query-bearing URI.

Refs #743

Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
2026-10-22 16:33:14 -04:00
Joseph Doherty b2c064bec3 fix(mtconnect): an unanswered write degrades; one success writer for reads and writes (review I-3, m7)
Coordinator ruling on F3: a write with no reply (transport failure / deadline)
sets Degraded with the stamp preserved and a type-only LastError, through a new
_writeDegraded flag folded into PublishHealthy. One success writer is shared:
RecordReadAnswered (a /current answer, an Agent refusal, a live-index read)
clears the read AND write degradations; RecordWriteAnswered clears the write
one; neither clears the other path's stream degradation. Tests both directions
(answered write clears it, good read clears it) plus the converse (an answered
write does not clear a failed read); red with each half removed.
m7: a good /current resets the refusal-dedup latch, so a refusal recurring after a
recovery is logged again (tested).

Refs #743

Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
2026-10-22 16:31:26 -04:00
Joseph Doherty ac01c88c0e fix(mtconnect): an Agent refusal of /current is a reply, not a comms fault
Health contract: an MTConnectError document (NO_DEVICE, INVALID_REQUEST, ...) is the
Agent answering. The parsers now mark such an InvalidDataException
(MTConnectXml.IsAgentRefusal - the type is sealed, so a Data marker, every other
handler unchanged); ReadAsync reports the batch Bad but does not degrade the read
path, advances LastSuccessfulRead, clears a prior read degradation and warns once
per distinct refusal. An unparseable answer stays a comms fault.

Refs #743

Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
2026-10-22 16:03:38 -04:00
Joseph Doherty b548cc46e6 perf(mtconnect): read through the live pump index; instance-id check on the /current fallback (R06:T-4, T-2)
- T-4: every ReadAsync batch fetched and parsed the whole device /current and
  built a fresh index even while the /sample pump held a live one. A read is now
  answered from the pump's index (read only - the pump stays its single writer)
  while the current-generation pump is running, has delivered since it started and
  is not degraded; /current stays the fallback, and its per-batch index is built
  over a tag map frozen once per binding instead of per call. A served read clears
  the read-path degradation a failed /current left.
- T-2: the /current fallback checks the answer's instanceId; a change (an Agent
  restart seen by a browse-only driver) drops the cached /probe model and raises
  rediscovery once per distinct id, only while the read's session is still installed.
- The pump also acts on no verdict (Degrade / latch) once its session generation
  is gone, so an abandoned pump cannot write health over the new session (T-1 follow-through).

Refs #743

Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
2026-10-22 15:39:58 -04:00