Search code examples
c#servicestackserver-sent-events

How to consume ServiceStack's ServerEventsClient OnMessage asynchronously


I'm looking for a way for this part of the code to be asynchronous.

var sse = new ServerEventsClient(apiUrl)
{
  OnMessage = HandleResponse
};

I've looked at "Using C# Async/Await friendly API’s" here https://docs.servicestack.net/csharp-server-events-client#using-c-asyncawait-friendly-apis and I'm not sure if the code provided only works for one future message or every message that will come. I'll be sending a lot of requests in which I expect server responses via SSE so I'd like every response to be handled.


Solution

  • OnMessage is a synchronous event which fires as soon as it receives a message, it doesn't have an async alternative callback.

    If you want to handle the messages asynchronously you can decouple the producer from its consumers which can do using a BlockingCollection where you can the SSE Client capturing messages as soon as they're sent, e.g:

    using var bc = new BlockingCollection<ServerEventMessage>();
    using var sse = new ServerEventsClient(apiUrl) {
      OnMessage = bc.Add
    };
    await sse.Connect();
    //...
    

    Then you can have multiple sync & async consumers handling messages at their own pace independent of how fast they're being received with Take, TryTake or GetConsumingEnumerable APIs, e.g:

    await Task.Run(async () => {
        foreach (var msg in bc.GetConsumingEnumerable())
        {
            // handle msg
            await Task.Delay(100);
        }
    });
    

    When you want to stop handling messages (e.g. when disposing ServerEventsClient) you can notify and short-circuit consumers with:

    bc.CompleteAdding();