graphql-platform
graphql-platform copied to clipboard
Support subscribing to multiple topics on ITopicEventReceiver
Is your feature request related to a problem?
There are times where a subscription may want to subscribe to multiple topics. For instance:
var userId = contextAccessor.HttpContext.User.GetUserId();
return receiver.SubscribeMultipleAsync<string, NotificationInfo>($"user_notifications_${userId}", "global_notifications");
In this case, I may write to a topic of a global notification, but also write to a specific user notification topic. It doesn't make sense to require the client to subscribe twice, and it's returning the same data. Right now, there is no easy way to implement this. See #2914
The solution you'd like
Add a method to ITopicEventReceiver: .SubscribeMultipleAsync(). There are many use cases where subscribing to multiple topics, without clunky workarounds.
My solution required another class:
private class MultipleStreams<TMessage> : ISourceStream<TMessage>
{
private readonly List<ISourceStream<TMessage>> _sources;
public MultipleStreams(IEnumerable<ISourceStream<TMessage>> streams)
{
_sources = streams.ToList();
}
public async ValueTask DisposeAsync()
{
foreach (var source in _sources)
await source.DisposeAsync();
}
public IAsyncEnumerable<TMessage> ReadEventsAsync() => _sources.Select(s => s.ReadEventsAsync()).ToArray().Merge();
async IAsyncEnumerable<object> ISourceStream.ReadEventsAsync() => _sources.Select(s => ((ISourceStream)s).ReadEventsAsync()).ToArray().Merge();
}
Also .Merge() is ugly in AsyncEnumerableEx library. I had to copy one implementation out, which required a ton of extra code bloat. I'd like to see a nice way implemented directly in hot chocolate.
Product
Hot Chocolate