Skip to content

Fix reply correlation and failure reporting - #32

Open
glopesdev wants to merge 1 commit into
mainfrom
fix-device-dispatch
Open

Fix reply correlation and failure reporting#32
glopesdev wants to merge 1 commit into
mainfrom
fix-device-dispatch

Conversation

@glopesdev

Copy link
Copy Markdown
Contributor

A reply could satisfy the wrong request. Pending requests were keyed by address alone, so a Read and a Write on one register would answer each other. This needs no concurrency, since a write that times out followed by a read returns the late write reply as the read result, with nothing raised.

Three changes follow from that, all inside Device. The public surface gains one name, DeviceError, and nothing else moves, since REPLY_TIMEOUT, raise_on_error, the ITransport contract and TransportError are untouched. Eight tests drive all of it through a scripted transport that replies from inside write, so a reply is never dispatched before its waiter exists and no test depends on timing.

Correlating a reply with its request

Requests are keyed by address and message type, and each key holds every waiter. Bonsai.Harp has always done this, filtering on message.IsMatch(command.Address, command.MessageType) and subscribing before it writes.

The wire carries no request identifier, so two identical requests in flight stay indistinguishable in the reply. The only difference is that both waiters are now satisfied by one reply instead of one being stranded on a replaced waiter.

Reporting a failure instead of losing it

A TransportError raised inside the reader thread was re-raised there and lost, since the thread is a daemon with nobody watching, so a removed port presented as a device that had gone quiet and every later call blamed a timeout. It is now reported to every waiting request and recorded, so a later request fails with the actual cause. The C# read loop calls OnError on its response subject for the same reason.

An error reply raised RuntimeError with the frame formatted into the message string and then discarded. It now raises DeviceError, which keeps the reply as reply, so a caller can inspect what the device actually sent. A conformance check needs exactly that to assert which error a device gave.

A pending request is keyed by address and message type rather than
address alone, and each key holds every waiter, so a reply satisfies
only requests of its own type. Before, a write reply would satisfy a
read on the same register.

A transport failure in the reader thread is reported to every waiting
request and to any that follow, in place of being re-raised inside a
daemon thread where it was lost, so a removed port no longer presents as
a device that went quiet. An error reply raises DeviceError, which keeps
the reply, in place of a RuntimeError that formatted the frame into its
message and discarded it.
@glopesdev
glopesdev requested a review from bruno-f-cruz August 21, 2026 07:50
@glopesdev glopesdev added the fix Pull request that fixes an issue label Aug 21, 2026

@bruno-f-cruz bruno-f-cruz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may be misunderstanding this and I can try later, but can we add a test that checks whether a single reply satisfies multiple requests?

For instance
Read(44)
Read(44)

Reply(44) <consumes both

Which shouldn't happen

@bruno-f-cruz

Copy link
Copy Markdown
Member

I may be misunderstanding this and I can try later, but can we add a test that checks whether a single reply satisfies multiple requests?

For instance
Read(44)
Read(44)

Reply(44) <consumes both

Which shouldn't happen

Actually nvm. The current api is blocking so this should not happen. Maybe something to worry about if we go asyn

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix Pull request that fixes an issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants