Repository navigation
v0.2.3 — retry a dropped connection, and the coverage behind it
A correctness fix for streaming/submit resilience, plus the test coverage that led to it. Additive, no breaking changes; upgrading from 0.2.x needs nothing.
Fixed
A gRPC stream or submit did not retry a connection that died in flight. tonic surfaces a dropped connection mid-call as a Status with code Unknown ("transport error" / "h2 protocol error"), not as a transport::Error — that variant is only for connection establishment. So Error::is_retriable() treated the most ordinary failure there is as terminal: updates_resumable gave up on the first blip and run_with_retry never fired.
Data integrity was never at risk — a real drop came back as an error, never as silent loss or a double commit, and the change-ID recovery still recovered the truth — but the resilience did not engage. The fix distinguishes the two Unknowns by their source chain: a client-side transport failure carries a source (tonic built the status from the underlying error), a genuine server Unknown decoded from response trailers does not. So Unknown/Internal with a source is a dropped connection and retriable; the same code bare stays terminal.
Found by killing a real TCP connection every few seconds through a chaos proxy — in-process mocks always emitted Status::unavailable, which is why it did not show earlier. Verified live: a resumable stream survived 15 real kills and observed all 20 submitted updates, offsets strictly ascending. The WebSocket resumable lane was already correct.
Also: Template::from_json_created_event rejected the events-by-contract-id response, which nests the created event as {"created": {"createdEvent": …}}; it now unwraps both layers.
Tests
A mutation-testing pass over canton-core surfaced retry-pipeline behaviours the tests did not actually prove — backoff doubling (every test had pinned initial == max), the max-attempts stop (broken only surfaced as a hang), and the day/microsecond/nanosecond retry-delay units. Not defects; gaps. All now covered.