This repository has been archived by the owner on Aug 15, 2022. It is now read-only.
Implement TAP-based request-response flow on top of RPCs #399
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
This introduces requests with responses, which are just RPCs that can send back a value. Requests are also just layered on top of RPCs and don't introduce any new special treatment, they are just some convenience sugar on top of RPCs where you want to send back a response.
Sending a request will return a
Task
already known from TAP [1], so you can easilyawait
the response to your request from the receiver. It works similar to HTTP requests.Context
I needed a way to send back information from one party to another after sending an RPC, and the only way to do that seemed to be two RPCs: one to send the request, and an RPC on the sender that the receiver can in turn invoke to send the response back. This approach resulted in rather entangled code where I would have two handler classes, one for each RPC, that needed to do bookkeeping about what was sent and what response went with what request.
This moves that bookkeeping into Forge, so senders can just
await
the response and don't have to worry about anything else.Examples
Limitations
SendSayHelloRequest
is automatically generated in the scenario above and you cannot (yet) avoid specifying the return type inSendRequest
(nor enforce the request data type).ISerializable
class or struct and pass that. Likewise, you can only return one response.ISerializable
after Forge Alloy's new approach, so porting is easier.Receivers
work for requests: you either send a request to a single party, or to multiple specific parties (and you will get an array of responses when all of them have come back); you cannot send a request to "all" parties without specifying them explicitly, currently, as the sender must know for how many responses to wait before it resolves the promise, and must in turn know how many parties are going to handle the request.NOTE: This doesn't necessarily need to be merged, but I wanted to upstream it anyway, to contribute back to the Forge community. Similar support for TAP may also be interesting to port over to Alloy as it's just one message going out and another coming back, so this could act as a reference implementation.
[1] https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap