diff --git a/src/Ellie/Services/Impl/PubSub/RedisPubSub.cs b/src/Ellie/Services/Impl/PubSub/RedisPubSub.cs new file mode 100644 index 0000000..497bedb --- /dev/null +++ b/src/Ellie/Services/Impl/PubSub/RedisPubSub.cs @@ -0,0 +1,52 @@ +using StackExchange.Redis; + +namespace Ellie.Common; + +public sealed class RedisPubSub : IPubSub +{ + private readonly IBotCredentials _creds; + private readonly ConnectionMultiplexer _multi; + private readonly ISeria _serializer; + + public RedisPubSub(ConnectionMultiplexer multi, ISeria serializer, IBotCredentials creds) + { + _multi = multi; + _serializer = serializer; + _creds = creds; + } + + public Task Pub(in TypedKey key, TData data) + where TData : notnull + { + var serialized = _serializer.Serialize(data); + return _multi.GetSubscriber() + .PublishAsync($"{_creds.RedisKey()}:{key.Key}", serialized, CommandFlags.FireAndForget); + } + + public Task Sub(in TypedKey key, Func action) + where TData : notnull + { + var eventName = key.Key; + + async void OnSubscribeHandler(RedisChannel _, RedisValue data) + { + try + { + var dataObj = _serializer.Deserialize(data); + if (dataObj is not null) + await action(dataObj); + else + { + Log.Warning("Publishing event {EventName} with a null value. This is not allowed", + eventName); + } + } + catch (Exception ex) + { + Log.Error("Error handling the event {EventName}: {ErrorMessage}", eventName, ex.Message); + } + } + + return _multi.GetSubscriber().SubscribeAsync($"{_creds.RedisKey()}:{eventName}", OnSubscribeHandler); + } +} \ No newline at end of file