ably-dotnet icon indicating copy to clipboard operation
ably-dotnet copied to clipboard

Add a "SubscribeAsync()" method to the IRealtimeChannel interface

Open danr-stadion opened this issue 1 year ago • 4 comments

Hi,

Would it be possible to add a SubscribeAsync() method to the IRealtimeChannel interface? It's currently impossible to make a call to async code in the message handler.

Want to be able to do something like this:

var ablyChannel = ablyRealtime.Channels.Get("channelName");

ablyChannel.SubscribeAsync(async message => { await myObject.MyAsyncMethod(message); });'

The Subscribe method only accepts Action<Message> so you can't pass in a delegate which can be awaited.

Thanks, Dan.

┆Issue is synchronized with this Jira Task by Unito

danr-stadion avatar Jun 24 '24 13:06 danr-stadion

Hi @danr-stadion,

Thank you for reporting this issue. Implementing this feature is not straightforward, and we are currently discussing the implementation details internally, as well as deliberating whether we should proceed with it. Additionally, we aim to maintain a consistent public API across all SDKs, necessitating careful consideration of implementation details for other languages as well. In the meantime, you can address this use case by doing something like the following:

var subject = new SequentialSimpleAsyncSubject<Message>();
await subject.Synchronize().SubscribeAsync(async message =>
{
    Console.WriteLine($"DoSomeWorkAsync BEGIN for '{message.Id}'");
    await Task.Delay(5000);
    Console.WriteLine($"DoSomeWorkAsync END for '{message.Id}'");
});
channel.Subscribe(message => subject.OnNextAsync(message));

If you have any difficulties in implementing the workaround, please do not hesitate to reach out to us. We are more than willing to provide assistance.

ttypic avatar Jun 25 '24 13:06 ttypic

Hi @ttypic ,

I tried to implement your workaround but it looks like it depends on an "alpha" Nuget package: https://www.nuget.org/packages/System.Reactive.Async

Unfortunately I'm not comfortable using alpha code in production, so I will just stick with my workaround using task factories.

Thanks, Dan.

danr-stadion avatar Jun 26 '24 09:06 danr-stadion

@danr-stadion, initially, we didn't add an async version to discourage people from doing a lot of extra work in the subscribe actions as the next one can't be called until the current one has finished to ensure the correct order of messages.

I know there are workarounds, but probably the best option is to use something like a blocking queue or the Channel APIs in .net. Ably uses the Channel<T> API to process messages internally, and it works really well.

If you are using it as part of asp.net you can spin up a BackgroundService to process the messages and can queue them in the subscribe action. I found this guide that might help you get started https://medium.com/@niteshsinghal85/using-channels-for-asynchronous-queuing-in-c-ed96c51d4576 and maybe @ttypic might even do an example 😉

marto83 avatar Jun 26 '24 16:06 marto83

Thanks @marto83, this looks quite straightforward, we're already using background workers in the application anyway.

@ttypic we can probably close this issue now.

Cheers, Dan.

danr-stadion avatar Jun 27 '24 10:06 danr-stadion