category: Application fundamentals

When developing applications,one way messaging is often not enough. That's why we provide a reliable RPC system in Stormancer implemented using the standard one way messaging features of the framework. This system enables simple remote call scenarios, in which a peer sends a request to an another remote peer and receives back a response asynchronously.

To make a request from a client to a scene host, call the Rpc method on the scene object.

Parameter p = ...; 
Result result = await scene.Rpc<TParameter,TResult>("remote-route",p);

Note that the server peer does not need not to be a Stormancer server. A client can play the role of the server peer (calling the AddProcedure method to add a clientside procedure), and the Stormancer server the role of the client peer (by calling the Rpc method on the client peer object, or any of its variants).

The request pipeline is designed to allow multiple response per request. This makes possible the implementation of operation progress notification or subscription to topics.

 Client peer                 Server peer
   |         request            |
   |--------------------------->|
   |                            |
   |         response           |
   |<---------------------------|
   |                            |
   |<---------------------------|
   |<---------------------------|
   |                            |
   |       request complete     |
   |<---------------------------|

To use partial responses, subscribe to the IObservable<TResult> object returned by the SendRequest method. Please note that the request won't be sent until you Subscribe to the observable.

scene.Rpc<Parameter,string>("sample-route",p).
    Subscribe(OnNext, OnComplete, OnError);

On the server peer, request handlers are added through the AddProcedure(string route, Func<RequestContext,Task> handler, bool ordered) extension method.

The handler takes a RequestContext instance as a parameter and returns a task. The request will automatically complete with this task.

scene.AddProcedure("sample-route", async ctx=>{

  await Task.Delay(1000); //Wait 1 second 
  ctx.Send("Hello, it's "+DateTime.UTCNow); //Send the current time to the client.

});

Using RPC from server to client

If you want to do a serverside RPC, use the Rpc method on any IScenePeerClient instance.

// We send a RPC on the 'rpc' route to the peer that sent the packet.
var response = await packet.Connection.Rpc<string, string>("rpc", "mon message");

Request Cancellation

You may need to cancel a pending request. To do that, you have to call Dispose on the IDisposable object returned by the call to IObservable.Subscribe.

Doing that will close the request on the client and send a cancelation notification to the server peer. This will in turn cancel the CancellationToken instance available on the request context object.

scene.AddProcedure("sample-route", async ctx=>{

  while(!ctx.CancellationToken.IsCancelled)//Loop while the request is not cancelled.
  {
      await Task.Delay(1000); //Wait 1 second 
      ctx.Send("Hello, it's "+DateTime.UTCNow); //Send the current time to the client.
  }

});

Javascript

The JavaScript syntax is very similar to the .NET syntax.