Request and Response - xylamic/lightrail-pubsub-integration-framework GitHub Wiki
Requesting
To be able to send a request message and receive a response, a Terminal with a Requester standpoint must be registered as seen in the previous explanation.
Once a Terminal is registered, a request can then be sent from it. A delivery is created as it was in the Publish/Subscribe section and sent in a similar way.
Example C++
// create a delivery
IDelivery* message = Lightrail::NewDelivery();
message->SetMessageString(L"This is a request string message that will be encoded as UTF-8");
// send a request and wait for the response
const IDetailedDelivery* response = client->Request(L"ReqTerminal", message, 30000);
Example C#
// create a delivery
Delivery message = new Delivery("This is a request string message that will be encoded as UTF-8");
// send a request and wait for the response
DetailedDelivery response = client.Request("ReqTerminal", message, 30000);
The request message is sent to a responder whose Terminal string matches. The timeout defines how long to wait for a response. If there are no responders set to receive the request, then an exception will be quickly thrown without waiting for the expiration of the timeout. If there is at least one responder, then a responder will be selected to receive the request and it will be forwarded.
Responder Selection
In order to select a responder, the responder must first be a listener for the specified request. Once the list of responders is generated, the responders are checked for being "active." Being "active" means that they have been discovered and did not fail on the last message that was to be delivered to them. If there is at least one active responder, then a responder will be randomly selected from the list of active responders. If there are no active responders, then a responder will be selected from all discovered, inactive responders. This process of using random selection and the activity of the responder provides both fault tolerance and limited load balancing when multiple responders are listening to the same request.
v1.10 Note: The number of responders can now be specified in a request instead of a always selecting a single responder. This can allow for 100% uptime by duplicating requests in the case that a responder goes down.
Responding
In order to respond to a request, the process is similar to a subscription. The event callback must first be defined and a Terminal then registered for Responder. The instance can then receive requests. When a request is received on the event callback, the request message is delivered and a delivery is expected to be returned as a response. If an exception is thrown or an empty response is given, then an exception will be thrown to the requester.
Example C++
// set up the callback using your class instance
client->OnRequestReceived.SetCallback(new XEventCallback<YourClassName, ITerminalReturnDelivery&>(
this, &YourClassName::RequestReceived));
// set up the method for receipt
void RequestReceived(ITerminalReturnDelivery& delivery)
{
std::wstring request_msg = delivery.DetailedDelivery()->MessageString();
delivery.ReturnedDelivery()->SetMessageString(L"Response string.");
}
Example C#
// set up the callback
client.OnRequestReceived += new RequestReceived(client_OnRequestReceived);
// set up the method for receipt
Delivery client_OnRequestReceived(DetailedDelivery delivery)
{
string message = delivery.MessageString();
Delivery response = new Delivery("Response string.");
}
If you are responding to requested via multiple Terminals, then the receipt Terminal property which gives the Terminal name can be used to differentiate which Terminal received the request.
For any given Lightrail instance, requests are received synchronously and guaranteed to be in order.