Skip to content

Commit 3569933

Browse files
authored
Eventengine/effects abstraction (#184)
* wip: effects abstraction overhaul * fix: added comments
1 parent 57f4fb2 commit 3569933

File tree

5 files changed

+158
-74
lines changed

5 files changed

+158
-74
lines changed

src/Api/PubnubApi/EventEngine/Core/EventEngineInterfaces.cs

+138-52
Original file line numberDiff line numberDiff line change
@@ -2,56 +2,142 @@
22
using System.Threading.Tasks;
33
using System.Collections.Generic;
44

5-
namespace PubnubApi.EventEngine.Core {
6-
7-
/// <summary>
8-
/// Generic effect handler.
9-
/// </summary>
10-
public interface IEffectHandler {
11-
Task Cancel();
12-
}
13-
14-
/// <summary>
15-
/// Handler (implementation) for a given invocation. The invocation represents the input arguments of a handler.
16-
/// </summary>
17-
/// <typeparam name="T">Associated invocation</typeparam>
18-
public interface IEffectHandler<in T> : IEffectHandler where T : IEffectInvocation {
19-
Task Run(T invocation);
20-
bool IsBackground(T invocation);
21-
}
22-
23-
/// <summary>
24-
/// An effect invocation. It represents calling <c>Run()</c> on a registered effect handler - calling it is orchestrated by the dispatcher.
25-
/// </summary>
26-
public interface IEffectInvocation { }
27-
28-
/// <summary>
29-
/// A cancel effect invocation. It represents calling <c>Cancel()</c> on a registered effect handler - calling it is orchestrated by the dispatcher.
30-
/// </summary>
31-
public interface IEffectCancelInvocation : IEffectInvocation { }
32-
33-
public interface IEvent { };
34-
35-
public abstract class State
36-
{
37-
public virtual IEnumerable<IEffectInvocation> OnEntry { get; } = null;
38-
public virtual IEnumerable<IEffectInvocation> OnExit { get; } = null;
39-
40-
/// <summary>
41-
/// The EE transition pure function.
42-
/// </summary>
43-
/// <param name="e">Input event</param>
44-
/// <returns>Target state and invocation list, or null for no-transition</returns>
45-
public abstract TransitionResult Transition(IEvent e);
46-
47-
public TransitionResult With(params IEffectInvocation[] invocations)
48-
{
49-
return new TransitionResult(this, invocations);
50-
}
51-
52-
public static implicit operator TransitionResult(State s)
53-
{
54-
return new TransitionResult(s);
55-
}
56-
}
5+
namespace PubnubApi.EventEngine.Core
6+
{
7+
/// <summary>
8+
/// Generic effect handler.
9+
/// </summary>
10+
public interface IEffectHandler
11+
{
12+
Task Cancel();
13+
Task Run(IEffectInvocation invocation);
14+
bool IsBackground(IEffectInvocation invocation);
15+
}
16+
17+
/// <summary>
18+
/// Handler (implementation) for a given invocation. The invocation represents the input arguments of a handler.
19+
/// </summary>
20+
/// <typeparam name="T">Associated invocation</typeparam>
21+
public interface IEffectHandler<T> : IEffectHandler where T : IEffectInvocation
22+
{
23+
Task Run(T invocation);
24+
bool IsBackground(T invocation);
25+
}
26+
27+
public abstract class EffectHandler<T> : IEffectHandler<T>
28+
where T : class, IEffectInvocation
29+
{
30+
public abstract Task Cancel();
31+
32+
public Task Run(IEffectInvocation invocation) => Run(invocation as T);
33+
34+
public bool IsBackground(IEffectInvocation invocation) => IsBackground(invocation as T);
35+
36+
public abstract Task Run(T invocation);
37+
38+
public abstract bool IsBackground(T invocation);
39+
}
40+
41+
/// <summary>
42+
/// Implement a handler a cancellable invocation.
43+
/// </summary>
44+
/// <typeparam name="T1">Connect type invocation</typeparam>
45+
/// <typeparam name="T2">Cancel running invocation</typeparam>
46+
public abstract class EffectCancellableHandler<T1, T2> : EffectHandler<T1>, IEffectHandler<T2>
47+
where T1 : class, IEffectInvocation
48+
where T2 : class, IEffectCancelInvocation
49+
{
50+
// run is not implemented in cancel.
51+
public Task Run(T2 invocation)
52+
{
53+
throw new NotImplementedException();
54+
}
55+
56+
public bool IsBackground(T2 invocation) => false;
57+
}
58+
59+
60+
/// <summary>
61+
/// Implement a handler for two invocations (meant for connect-reconnect pairs). Use EffectDoubleCancellableHandler to implement cancellable handler.
62+
/// </summary>
63+
/// <typeparam name="T1">Run type invocation</typeparam>
64+
/// <typeparam name="T2">Retry type invocation</typeparam>
65+
public abstract class EffectDoubleHandler<T1, T2> : EffectHandler<T1>, IEffectHandler<T2>
66+
where T1 : class, IEffectInvocation
67+
where T2 : class, IEffectInvocation
68+
{
69+
70+
public new Task Run(IEffectInvocation invocation) =>
71+
invocation is T1 ? (this as EffectHandler<T1>).Run(invocation) : Run(invocation as T2);
72+
73+
public new bool IsBackground(IEffectInvocation invocation) =>
74+
invocation is T1 ? (this as EffectHandler<T1>).IsBackground(invocation) : IsBackground(invocation as T2);
75+
76+
public abstract Task Run(T2 invocation);
77+
78+
public abstract bool IsBackground(T2 invocation);
79+
}
80+
81+
82+
/// <summary>
83+
/// Implement a handler for two invocations (meant for connect-reconnect pairs) with a cancel invocation
84+
/// </summary>
85+
/// <typeparam name="T1">Run type invocation</typeparam>
86+
/// <typeparam name="T2">Retry type invocation</typeparam>
87+
/// <typeparam name="T3">Cancel connecting invocation</typeparam>
88+
public abstract class EffectDoubleCancellableHandler<T1, T2, T3> : EffectDoubleHandler<T1, T2>, IEffectHandler<T3>
89+
where T1 : class, IEffectInvocation
90+
where T2 : class, IEffectInvocation
91+
where T3 : class, IEffectCancelInvocation
92+
{
93+
// Run is not implemented in cancel.
94+
public Task Run(T3 invocation)
95+
{
96+
throw new NotImplementedException();
97+
}
98+
99+
public bool IsBackground(T3 invocation) => false;
100+
}
101+
102+
103+
/// <summary>
104+
/// An effect invocation. It represents calling <c>Run()</c> on a registered effect handler - calling it is orchestrated by the dispatcher.
105+
/// </summary>
106+
public interface IEffectInvocation
107+
{
108+
}
109+
110+
/// <summary>
111+
/// A cancel effect invocation. It represents calling <c>Cancel()</c> on a registered effect handler - calling it is orchestrated by the dispatcher.
112+
/// </summary>
113+
public interface IEffectCancelInvocation : IEffectInvocation
114+
{
115+
}
116+
117+
public interface IEvent
118+
{
119+
};
120+
121+
public abstract class State
122+
{
123+
public virtual IEnumerable<IEffectInvocation> OnEntry { get; } = null;
124+
public virtual IEnumerable<IEffectInvocation> OnExit { get; } = null;
125+
126+
/// <summary>
127+
/// The EE transition pure function.
128+
/// </summary>
129+
/// <param name="e">Input event</param>
130+
/// <returns>Target state and invocation list, or null for no-transition</returns>
131+
public abstract TransitionResult Transition(IEvent e);
132+
133+
public TransitionResult With(params IEffectInvocation[] invocations)
134+
{
135+
return new TransitionResult(this, invocations);
136+
}
137+
138+
public static implicit operator TransitionResult(State s)
139+
{
140+
return new TransitionResult(s);
141+
}
142+
}
57143
}

src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace PubnubApi.EventEngine.Subscribe.Effects
99
{
10-
public class EmitMessagesHandler : IEffectHandler<Invocations.EmitMessagesInvocation>
10+
public class EmitMessagesHandler : EffectHandler<Invocations.EmitMessagesInvocation>
1111
{
1212
private readonly System.Action<Pubnub, PNMessageResult<object>> messageEmitterFunction;
1313
private readonly Pubnub pubnubInstance;
@@ -19,7 +19,7 @@ public EmitMessagesHandler(Pubnub pubnubInstance,
1919
this.pubnubInstance = pubnubInstance;
2020
}
2121

22-
public async Task Run(EmitMessagesInvocation invocation)
22+
public async override Task Run(EmitMessagesInvocation invocation)
2323
{
2424
var processedMessages = invocation.Messages.Messages.Select(m => new PNMessageResult<object>()
2525
{
@@ -37,9 +37,9 @@ public async Task Run(EmitMessagesInvocation invocation)
3737
}
3838
}
3939

40-
public bool IsBackground(EmitMessagesInvocation invocation) => false;
40+
public override bool IsBackground(EmitMessagesInvocation invocation) => false;
4141

42-
public Task Cancel()
42+
public override Task Cancel()
4343
{
4444
throw new NotImplementedException();
4545
}

src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitStatusEffectHandler.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace PubnubApi.EventEngine.Subscribe.Effects
77
{
8-
public class EmitStatusEffectHandler: IEffectHandler<EmitStatusInvocation>
8+
public class EmitStatusEffectHandler: EffectHandler<EmitStatusInvocation>
99
{
1010
private readonly Action<Pubnub, PNStatus> statusEmitterFunction;
1111
private readonly Pubnub pubnubInstance;
@@ -16,11 +16,11 @@ public EmitStatusEffectHandler(Pubnub pn, Action<Pubnub, PNStatus> statusEmitter
1616
this.pubnubInstance = pn;
1717
}
1818

19-
public Task Cancel() => Utils.EmptyTask;
19+
public override Task Cancel() => Utils.EmptyTask;
2020

21-
public bool IsBackground(EmitStatusInvocation invocation) => false;
21+
public override bool IsBackground(EmitStatusInvocation invocation) => false;
2222

23-
public async Task Run(EmitStatusInvocation invocation)
23+
public override async Task Run(EmitStatusInvocation invocation)
2424
{
2525
this.statusEmitterFunction(this.pubnubInstance, invocation.Status);
2626
}

src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs

+6-7
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
namespace PubnubApi.EventEngine.Subscribe.Effects
1616
{
1717
public class HandshakeEffectHandler :
18-
Core.IEffectHandler<HandshakeInvocation>,
19-
Core.IEffectHandler<HandshakeReconnectInvocation>
18+
EffectDoubleCancellableHandler<HandshakeInvocation, HandshakeReconnectInvocation, CancelHandshakeInvocation>
2019
{
2120
private SubscribeManager2 manager;
2221
private EventQueue eventQueue;
@@ -29,7 +28,7 @@ internal HandshakeEffectHandler(SubscribeManager2 manager, EventQueue eventQueue
2928
this.eventQueue = eventQueue;
3029
}
3130

32-
public async Task Run(HandshakeReconnectInvocation invocation)
31+
public override async Task Run(HandshakeReconnectInvocation invocation)
3332
{
3433
if (!ReconnectionDelayUtil.shouldRetry(invocation.ReconnectionConfiguration, invocation.AttemptedRetries))
3534
{
@@ -44,12 +43,12 @@ public async Task Run(HandshakeReconnectInvocation invocation)
4443
}
4544
}
4645

47-
public bool IsBackground(HandshakeReconnectInvocation invocation)
46+
public override bool IsBackground(HandshakeReconnectInvocation invocation)
4847
{
4948
return true;
5049
}
5150

52-
public async Task Run(HandshakeInvocation invocation)
51+
public override async Task Run(HandshakeInvocation invocation)
5352
{
5453
var response = await MakeHandshakeRequest(invocation);
5554

@@ -71,7 +70,7 @@ public async Task Run(HandshakeInvocation invocation)
7170
}
7271
}
7372

74-
public bool IsBackground(HandshakeInvocation invocation)
73+
public override bool IsBackground(HandshakeInvocation invocation)
7574
{
7675
return false;
7776
}
@@ -105,7 +104,7 @@ public bool IsBackground(HandshakeInvocation invocation)
105104
}
106105
}
107106

108-
public async Task Cancel()
107+
public override async Task Cancel()
109108
{
110109
if (!retryDelay.Cancelled)
111110
{

src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs

+6-7
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
namespace PubnubApi.EventEngine.Subscribe.Effects
1616
{
1717
public class ReceivingEffectHandler:
18-
Core.IEffectHandler<ReceiveMessagesInvocation>,
19-
Core.IEffectHandler<ReceiveReconnectInvocation>
18+
EffectDoubleCancellableHandler<ReceiveMessagesInvocation, ReceiveReconnectInvocation, CancelReceiveMessagesInvocation>
2019
{
2120
private SubscribeManager2 manager;
2221
private EventQueue eventQueue;
@@ -29,7 +28,7 @@ internal ReceivingEffectHandler(SubscribeManager2 manager, EventQueue eventQueue
2928
this.eventQueue = eventQueue;
3029
}
3130

32-
public Task Run(ReceiveReconnectInvocation invocation)
31+
public override Task Run(ReceiveReconnectInvocation invocation)
3332
{
3433
if (!ReconnectionDelayUtil.shouldRetry(invocation.ReconnectionConfiguration, invocation.AttemptedRetries))
3534
{
@@ -45,12 +44,12 @@ public Task Run(ReceiveReconnectInvocation invocation)
4544
return Utils.EmptyTask;
4645
}
4746

48-
public bool IsBackground(ReceiveReconnectInvocation invocation)
47+
public override bool IsBackground(ReceiveReconnectInvocation invocation)
4948
{
5049
return true;
5150
}
5251

53-
public async Task Run(ReceiveMessagesInvocation invocation)
52+
public override async Task Run(ReceiveMessagesInvocation invocation)
5453
{
5554
var response = await MakeReceiveMessagesRequest(invocation);
5655
var cursor = new SubscriptionCursor()
@@ -76,7 +75,7 @@ public async Task Run(ReceiveMessagesInvocation invocation)
7675
}
7776
}
7877

79-
public bool IsBackground(ReceiveMessagesInvocation invocation)
78+
public override bool IsBackground(ReceiveMessagesInvocation invocation)
8079
{
8180
return true;
8281
}
@@ -105,7 +104,7 @@ public bool IsBackground(ReceiveMessagesInvocation invocation)
105104
}
106105
}
107106

108-
public async Task Cancel()
107+
public override async Task Cancel()
109108
{
110109
if (!retryDelay.Cancelled)
111110
{

0 commit comments

Comments
 (0)