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