diff --git a/src/Api/PubnubApi/EventEngine/Core/EventEngineInterfaces.cs b/src/Api/PubnubApi/EventEngine/Core/EventEngineInterfaces.cs index 2d5aad22f..53c5ccee5 100644 --- a/src/Api/PubnubApi/EventEngine/Core/EventEngineInterfaces.cs +++ b/src/Api/PubnubApi/EventEngine/Core/EventEngineInterfaces.cs @@ -2,56 +2,142 @@ using System.Threading.Tasks; using System.Collections.Generic; -namespace PubnubApi.EventEngine.Core { - - /// - /// Generic effect handler. - /// - public interface IEffectHandler { - Task Cancel(); - } - - /// - /// Handler (implementation) for a given invocation. The invocation represents the input arguments of a handler. - /// - /// Associated invocation - public interface IEffectHandler : IEffectHandler where T : IEffectInvocation { - Task Run(T invocation); - bool IsBackground(T invocation); - } - - /// - /// An effect invocation. It represents calling Run() on a registered effect handler - calling it is orchestrated by the dispatcher. - /// - public interface IEffectInvocation { } - - /// - /// A cancel effect invocation. It represents calling Cancel() on a registered effect handler - calling it is orchestrated by the dispatcher. - /// - public interface IEffectCancelInvocation : IEffectInvocation { } - - public interface IEvent { }; - - public abstract class State - { - public virtual IEnumerable OnEntry { get; } = null; - public virtual IEnumerable OnExit { get; } = null; - - /// - /// The EE transition pure function. - /// - /// Input event - /// Target state and invocation list, or null for no-transition - public abstract TransitionResult Transition(IEvent e); - - public TransitionResult With(params IEffectInvocation[] invocations) - { - return new TransitionResult(this, invocations); - } - - public static implicit operator TransitionResult(State s) - { - return new TransitionResult(s); - } - } +namespace PubnubApi.EventEngine.Core +{ + /// + /// Generic effect handler. + /// + public interface IEffectHandler + { + Task Cancel(); + Task Run(IEffectInvocation invocation); + bool IsBackground(IEffectInvocation invocation); + } + + /// + /// Handler (implementation) for a given invocation. The invocation represents the input arguments of a handler. + /// + /// Associated invocation + public interface IEffectHandler : IEffectHandler where T : IEffectInvocation + { + Task Run(T invocation); + bool IsBackground(T invocation); + } + + public abstract class EffectHandler : IEffectHandler + where T : class, IEffectInvocation + { + public abstract Task Cancel(); + + public Task Run(IEffectInvocation invocation) => Run(invocation as T); + + public bool IsBackground(IEffectInvocation invocation) => IsBackground(invocation as T); + + public abstract Task Run(T invocation); + + public abstract bool IsBackground(T invocation); + } + + /// + /// Implement a handler a cancellable invocation. + /// + /// Connect type invocation + /// Cancel running invocation + public abstract class EffectCancellableHandler : EffectHandler, IEffectHandler + where T1 : class, IEffectInvocation + where T2 : class, IEffectCancelInvocation + { + // run is not implemented in cancel. + public Task Run(T2 invocation) + { + throw new NotImplementedException(); + } + + public bool IsBackground(T2 invocation) => false; + } + + + /// + /// Implement a handler for two invocations (meant for connect-reconnect pairs). Use EffectDoubleCancellableHandler to implement cancellable handler. + /// + /// Run type invocation + /// Retry type invocation + public abstract class EffectDoubleHandler : EffectHandler, IEffectHandler + where T1 : class, IEffectInvocation + where T2 : class, IEffectInvocation + { + + public new Task Run(IEffectInvocation invocation) => + invocation is T1 ? (this as EffectHandler).Run(invocation) : Run(invocation as T2); + + public new bool IsBackground(IEffectInvocation invocation) => + invocation is T1 ? (this as EffectHandler).IsBackground(invocation) : IsBackground(invocation as T2); + + public abstract Task Run(T2 invocation); + + public abstract bool IsBackground(T2 invocation); + } + + + /// + /// Implement a handler for two invocations (meant for connect-reconnect pairs) with a cancel invocation + /// + /// Run type invocation + /// Retry type invocation + /// Cancel connecting invocation + public abstract class EffectDoubleCancellableHandler : EffectDoubleHandler, IEffectHandler + where T1 : class, IEffectInvocation + where T2 : class, IEffectInvocation + where T3 : class, IEffectCancelInvocation + { + // Run is not implemented in cancel. + public Task Run(T3 invocation) + { + throw new NotImplementedException(); + } + + public bool IsBackground(T3 invocation) => false; + } + + + /// + /// An effect invocation. It represents calling Run() on a registered effect handler - calling it is orchestrated by the dispatcher. + /// + public interface IEffectInvocation + { + } + + /// + /// A cancel effect invocation. It represents calling Cancel() on a registered effect handler - calling it is orchestrated by the dispatcher. + /// + public interface IEffectCancelInvocation : IEffectInvocation + { + } + + public interface IEvent + { + }; + + public abstract class State + { + public virtual IEnumerable OnEntry { get; } = null; + public virtual IEnumerable OnExit { get; } = null; + + /// + /// The EE transition pure function. + /// + /// Input event + /// Target state and invocation list, or null for no-transition + public abstract TransitionResult Transition(IEvent e); + + public TransitionResult With(params IEffectInvocation[] invocations) + { + return new TransitionResult(this, invocations); + } + + public static implicit operator TransitionResult(State s) + { + return new TransitionResult(s); + } + } } \ No newline at end of file diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs index 9ace826a1..af2d1f10f 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs @@ -7,7 +7,7 @@ namespace PubnubApi.EventEngine.Subscribe.Effects { - public class EmitMessagesHandler : IEffectHandler + public class EmitMessagesHandler : EffectHandler { private readonly System.Action> messageEmitterFunction; private readonly Pubnub pubnubInstance; @@ -19,7 +19,7 @@ public EmitMessagesHandler(Pubnub pubnubInstance, this.pubnubInstance = pubnubInstance; } - public async Task Run(EmitMessagesInvocation invocation) + public async override Task Run(EmitMessagesInvocation invocation) { var processedMessages = invocation.Messages.Messages.Select(m => new PNMessageResult() { @@ -37,9 +37,9 @@ public async Task Run(EmitMessagesInvocation invocation) } } - public bool IsBackground(EmitMessagesInvocation invocation) => false; + public override bool IsBackground(EmitMessagesInvocation invocation) => false; - public Task Cancel() + public override Task Cancel() { throw new NotImplementedException(); } diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitStatusEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitStatusEffectHandler.cs index 366730ed5..1f207894d 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitStatusEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitStatusEffectHandler.cs @@ -5,7 +5,7 @@ namespace PubnubApi.EventEngine.Subscribe.Effects { - public class EmitStatusEffectHandler: IEffectHandler + public class EmitStatusEffectHandler: EffectHandler { private readonly Action statusEmitterFunction; private readonly Pubnub pubnubInstance; @@ -16,11 +16,11 @@ public EmitStatusEffectHandler(Pubnub pn, Action statusEmitter this.pubnubInstance = pn; } - public Task Cancel() => Utils.EmptyTask; + public override Task Cancel() => Utils.EmptyTask; - public bool IsBackground(EmitStatusInvocation invocation) => false; + public override bool IsBackground(EmitStatusInvocation invocation) => false; - public async Task Run(EmitStatusInvocation invocation) + public override async Task Run(EmitStatusInvocation invocation) { this.statusEmitterFunction(this.pubnubInstance, invocation.Status); } diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs index 1c214c5f3..d0fc32aaf 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs @@ -15,8 +15,7 @@ namespace PubnubApi.EventEngine.Subscribe.Effects { public class HandshakeEffectHandler : - Core.IEffectHandler, - Core.IEffectHandler + EffectDoubleCancellableHandler { private SubscribeManager2 manager; private EventQueue eventQueue; @@ -29,7 +28,7 @@ internal HandshakeEffectHandler(SubscribeManager2 manager, EventQueue eventQueue this.eventQueue = eventQueue; } - public async Task Run(HandshakeReconnectInvocation invocation) + public override async Task Run(HandshakeReconnectInvocation invocation) { if (!ReconnectionDelayUtil.shouldRetry(invocation.ReconnectionConfiguration, invocation.AttemptedRetries)) { @@ -44,12 +43,12 @@ public async Task Run(HandshakeReconnectInvocation invocation) } } - public bool IsBackground(HandshakeReconnectInvocation invocation) + public override bool IsBackground(HandshakeReconnectInvocation invocation) { return true; } - public async Task Run(HandshakeInvocation invocation) + public override async Task Run(HandshakeInvocation invocation) { var response = await MakeHandshakeRequest(invocation); @@ -71,7 +70,7 @@ public async Task Run(HandshakeInvocation invocation) } } - public bool IsBackground(HandshakeInvocation invocation) + public override bool IsBackground(HandshakeInvocation invocation) { return false; } @@ -105,7 +104,7 @@ public bool IsBackground(HandshakeInvocation invocation) } } - public async Task Cancel() + public override async Task Cancel() { if (!retryDelay.Cancelled) { diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs index 98e2582d4..ab02868d3 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs @@ -15,8 +15,7 @@ namespace PubnubApi.EventEngine.Subscribe.Effects { public class ReceivingEffectHandler: - Core.IEffectHandler, - Core.IEffectHandler + EffectDoubleCancellableHandler { private SubscribeManager2 manager; private EventQueue eventQueue; @@ -29,7 +28,7 @@ internal ReceivingEffectHandler(SubscribeManager2 manager, EventQueue eventQueue this.eventQueue = eventQueue; } - public Task Run(ReceiveReconnectInvocation invocation) + public override Task Run(ReceiveReconnectInvocation invocation) { if (!ReconnectionDelayUtil.shouldRetry(invocation.ReconnectionConfiguration, invocation.AttemptedRetries)) { @@ -45,12 +44,12 @@ public Task Run(ReceiveReconnectInvocation invocation) return Utils.EmptyTask; } - public bool IsBackground(ReceiveReconnectInvocation invocation) + public override bool IsBackground(ReceiveReconnectInvocation invocation) { return true; } - public async Task Run(ReceiveMessagesInvocation invocation) + public override async Task Run(ReceiveMessagesInvocation invocation) { var response = await MakeReceiveMessagesRequest(invocation); var cursor = new SubscriptionCursor() @@ -76,7 +75,7 @@ public async Task Run(ReceiveMessagesInvocation invocation) } } - public bool IsBackground(ReceiveMessagesInvocation invocation) + public override bool IsBackground(ReceiveMessagesInvocation invocation) { return true; } @@ -105,7 +104,7 @@ public bool IsBackground(ReceiveMessagesInvocation invocation) } } - public async Task Cancel() + public override async Task Cancel() { if (!retryDelay.Cancelled) {