Files
mxaccess/rust/crates/mxaccess-asb
Joseph Doherty 9063f10b1b
rust / build / test / clippy / fmt (push) Has been cancelled
[M5] mxaccess-asb: register_items retry on InvalidConnectionId — LIVE PATH WORKS
End-to-end live path now functional: Connect → AuthenticateMe →
RegisterItems → Read → Disconnect. The example reads back the live
TestChildObject.TestInt value (99) over the wire on the first run.

Root-cause of the previous "InvalidConnectionId" mystery: it was
never an HMAC verification failure. `AuthenticateMe` is one-way
(`AsbContracts.cs:18`) and the server commits auth state
asynchronously after the request lands. A Register that follows too
quickly sees the connection in pre-authenticated state and returns
`AsbErrorCode.InvalidConnectionId` (= 1).

.NET's `MxAsbDataClient.RegisterMany` (`cs:191-204`) handles this
explicitly with a retry loop:

  for (int attempt = 1; attempt < 5
       && response.Result.ErrorCode == InvalidConnectionId; attempt++)
  {
      Thread.Sleep(TimeSpan.FromMilliseconds(100 * attempt));
      response = RegisterOnce(items);
  }

We now mirror the same pattern in `AsbClient::register_items_once`
followed by a retry loop in `register_items` — up to 5 attempts with
`100 * attempt` ms backoff.

Supporting changes:
- `RegisterItemsResponse` gains `result_code: Option<u32>` +
  `success: Option<bool>` so callers can read `Result.resultCodeField`
  + `successField` from the response. `decode_register_items_response`
  now tolerates an empty `<ASBIData />` Status array (server returns
  empty when the operation fails server-side) instead of erroring
  with `MissingField`. New helper `find_text_in_named_element` walks
  the body token stream.
- New public constant `RESULT_CODE_INVALID_CONNECTION_ID = 1` for
  callers that want to detect this status outside the retry path.
- The previously-failing test `decode_register_items_response_returns_
  missing_field_when_status_absent` was renamed and rewritten as
  `decode_register_items_response_returns_empty_status_when_absent`
  to match the new tolerant decode contract.

F31 closed. F30 (read-side dict-id resolution, landed in `eb6c689`)
was the unblocker — without it we couldn't see the
`<resultCodeField>1</>` element in the response and the failure mode
looked like a HMAC mismatch instead of a transient retryable error.

Workspace: 711 unit tests pass. Clippy clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 21:02:38 -04:00
..