From c84ab1fa98cd0b10a9849685a7776a21309001d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Mon, 7 Aug 2023 14:14:56 +0200 Subject: [PATCH 01/56] wip: deserialization --- .../EndPoint/PubSub/SubscribeOperation2.cs | 2 +- .../Subscribe/Effects/EmitMessagesHandler.cs | 44 ++++++++++++++----- .../Subscribe/SubscribeEventEngine.cs | 20 ++++++++- 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs index 2a4f7282f..90fc8af3e 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs @@ -703,7 +703,7 @@ private void Subscribe(string[] channels, string[] channelGroups, Dictionary(channels, channelGroups); } internal bool Retry(bool reconnect) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs index e946b5c4a..ce51c2805 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs @@ -1,4 +1,6 @@ using System; +using System.Collections; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Newtonsoft.Json; @@ -11,9 +13,11 @@ public class EmitMessagesHandler : EffectHandler> messageEmitterFunction; private readonly Pubnub pubnubInstance; + private readonly Dictionary channelTypeMap; + private readonly Dictionary channelGroupTypeMap; public EmitMessagesHandler(Pubnub pubnubInstance, - System.Action> messageEmitterFunction) + System.Action> messageEmitterFunction, Dictionary channelTypeMap = null, Dictionary channelGroupTypeMap = null) { this.messageEmitterFunction = messageEmitterFunction; this.pubnubInstance = pubnubInstance; @@ -21,18 +25,38 @@ public EmitMessagesHandler(Pubnub pubnubInstance, public async override Task Run(EmitMessagesInvocation invocation) { - var processedMessages = invocation.Messages?.Messages.Select(m => new PNMessageResult() + var processedMessages = invocation.Messages?.Messages.Select(m => { - Channel = m.Channel, - Message = JsonConvert.DeserializeObject(m.Payload), - Subscription = m.SubscriptionMatch, - Timetoken = m.Timetoken.Timestamp, - UserMetadata = m.PublishMetadata, - Publisher = m.IssuingClientId - }); + var msgResult = new PNMessageResult() + { + Channel = m.Channel, + Subscription = m.SubscriptionMatch, + Timetoken = m.Timetoken.Timestamp, + UserMetadata = m.PublishMetadata, + Publisher = m.IssuingClientId + }; + + if (!(channelTypeMap is null) && channelTypeMap.TryGetValue(m.Channel, out var msgType)) + { + msgResult.Message = JsonConvert.DeserializeObject(m.Payload, msgType); + } else if (!(channelGroupTypeMap is null) && channelGroupTypeMap.TryGetValue(m.SubscriptionMatch, out var T)) + { + msgResult.Message = JsonConvert.DeserializeObject(m.Payload, T); + } + else + { + msgResult.Message = m.Payload; + } - processedMessages?.ToList().ForEach(message => messageEmitterFunction(pubnubInstance, message)); + return msgResult; + }); + if (processedMessages is null) return; + + foreach (var message in processedMessages) + { + messageEmitterFunction(pubnubInstance, message); + } } public override bool IsBackground(EmitMessagesInvocation invocation) => false; diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs index da88ecc14..19b20dcb2 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs @@ -5,11 +5,15 @@ using PubnubApi.EventEngine.Subscribe.Effects; using PubnubApi.EventEngine.Subscribe.Invocations; using System; +using System.Collections.Generic; namespace PubnubApi.EventEngine.Subscribe { public class SubscribeEventEngine : Engine { private SubscribeManager2 subscribeManager; + private readonly Dictionary channelTypeMap = new Dictionary(); + private readonly Dictionary channelGroupTypeMap = new Dictionary(); + internal SubscribeEventEngine(Pubnub pubnubInstance, PNConfiguration pubnubConfiguration, SubscribeManager2 subscribeManager, @@ -39,10 +43,24 @@ internal SubscribeEventEngine(Pubnub pubnubInstance, currentState = new UnsubscribedState() { ReconnectionConfiguration = new Context.ReconnectionConfiguration(pubnubConfiguration.ReconnectionPolicy, pubnubConfiguration.ConnectionMaxRetries) }; } - public void Subscribe(string[] channels, string[] channelGroups) + public void Subscribe(string[] channels, string[] channelGroups) { + foreach (var c in channels) + { + channelTypeMap[c] = typeof(T); + } + foreach (var c in channelGroups) + { + channelGroupTypeMap[c] = typeof(T); + } this.EventQueue.Enqueue(new SubscriptionChangedEvent() { Channels = channels, ChannelGroups = channelGroups }); } + + public void Subscribe(string[] channels, string[] channelGroups) + { + Subscribe(channels, channelGroups); + } + public void UnsubscribeAll() { this.EventQueue.Enqueue(new UnsubscribeAllEvent()); From 54f735c6f804004c9e9c4575a95ea08e274cdc16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Mon, 7 Aug 2023 14:16:24 +0200 Subject: [PATCH 02/56] wip: deserialization --- .../EventEngine/Subscribe/Effects/EmitMessagesHandler.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs index ce51c2805..cd0bed6e6 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs @@ -35,13 +35,14 @@ public async override Task Run(EmitMessagesInvocation invocation) UserMetadata = m.PublishMetadata, Publisher = m.IssuingClientId }; - - if (!(channelTypeMap is null) && channelTypeMap.TryGetValue(m.Channel, out var msgType)) + + Type msgType, groupType; + if (!(channelTypeMap is null) && channelTypeMap.TryGetValue(m.Channel, out msgType)) { msgResult.Message = JsonConvert.DeserializeObject(m.Payload, msgType); - } else if (!(channelGroupTypeMap is null) && channelGroupTypeMap.TryGetValue(m.SubscriptionMatch, out var T)) + } else if (!(channelGroupTypeMap is null) && channelGroupTypeMap.TryGetValue(m.SubscriptionMatch, out groupType)) { - msgResult.Message = JsonConvert.DeserializeObject(m.Payload, T); + msgResult.Message = JsonConvert.DeserializeObject(m.Payload, groupType); } else { From 4e388618f7f1965a497dd4f89dd63a9343e68e21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Mon, 7 Aug 2023 14:25:18 +0200 Subject: [PATCH 03/56] fix: passed dependencies to emit messages handler --- src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs index 19b20dcb2..376fb51d1 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs @@ -35,7 +35,7 @@ internal SubscribeEventEngine(Pubnub pubnubInstance, dispatcher.Register(receiveHandler); dispatcher.Register(receiveHandler); - var emitMessageHandler = new Effects.EmitMessagesHandler(pubnubInstance, messageListener); + var emitMessageHandler = new Effects.EmitMessagesHandler(pubnubInstance, messageListener, channelTypeMap, channelGroupTypeMap); dispatcher.Register(emitMessageHandler); var emitStatusHandler = new Effects.EmitStatusEffectHandler(pubnubInstance, statusListener); From 8f913a3154bdf8b53e8af9ad978e670822c67905 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Mon, 7 Aug 2023 17:57:29 +0530 Subject: [PATCH 04/56] fix duplicate p jsonproperty --- src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs | 5 +++-- .../EventEngine/Subscribe/Common/CommonSubscribeTypes.cs | 3 --- .../EventEngine/Subscribe/Effects/EmitMessagesHandler.cs | 2 +- .../Subscribe/Invocations/SubscriptionInvocations.cs | 5 +++-- .../PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs index a84db0422..17d702851 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs @@ -8,6 +8,7 @@ using System.Collections; using System.Text; using PubnubApi.EventEngine.Subscribe.Common; +using Newtonsoft.Json; #if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 using System.Net.Http; using System.Net.Http.Headers; @@ -112,7 +113,7 @@ public async Task> HandshakeRequest(PNOperati if (!string.IsNullOrEmpty(responseTuple.Item1) && responseTuple.Item2 == null) { PNStatus status = new PNStatus(null, PNOperationType.PNSubscribeOperation, PNStatusCategory.PNConnectedCategory, channels, channelGroups); - HandshakeResponse handshakeResponse = jsonLibrary.DeserializeToObject(responseTuple.Item1); + HandshakeResponse handshakeResponse = JsonConvert.DeserializeObject(responseTuple.Item1); return new Tuple(handshakeResponse, status); } @@ -168,7 +169,7 @@ internal async Task, PNStatus>> ReceiveRequest receiveResponse = jsonLibrary.DeserializeToObject>(responseTuple.Item1); + ReceivingResponse receiveResponse = JsonConvert.DeserializeObject>(responseTuple.Item1); return new Tuple, PNStatus>(receiveResponse, status); } return new Tuple, PNStatus>(null, responseTuple.Item2); diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs index c3826ca42..2f7503d6c 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs @@ -80,9 +80,6 @@ public class Message [JsonProperty("s")] public long SequenceNumber { get; set; } - - [JsonProperty("p")] - public Timetoken Timetoken { get; set; } } public abstract class SubscriptionState : Core.State diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs index e946b5c4a..6a3d18636 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs @@ -26,7 +26,7 @@ public async override Task Run(EmitMessagesInvocation invocation) Channel = m.Channel, Message = JsonConvert.DeserializeObject(m.Payload), Subscription = m.SubscriptionMatch, - Timetoken = m.Timetoken.Timestamp, + Timetoken = invocation.Cursor.Timetoken.Value, UserMetadata = m.PublishMetadata, Publisher = m.IssuingClientId }); diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs index c4e4773bc..fe4daad9b 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs @@ -6,9 +6,10 @@ namespace PubnubApi.EventEngine.Subscribe.Invocations { public class EmitMessagesInvocation : Core.IEffectInvocation { public ReceivingResponse Messages; - - public EmitMessagesInvocation(ReceivingResponse messages) + public SubscriptionCursor Cursor; + public EmitMessagesInvocation(SubscriptionCursor cursor, ReceivingResponse messages) { + this.Cursor = cursor; this.Messages = messages; } } diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs index 010541e09..d08ae8abb 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs @@ -32,7 +32,7 @@ public override TransitionResult Transition(IEvent e) Cursor = receiveSuccess.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration }.With( - new EmitMessagesInvocation(receiveSuccess.Messages), + new EmitMessagesInvocation(receiveSuccess.Cursor, receiveSuccess.Messages), new EmitStatusInvocation(receiveSuccess.Status) ), From 4a5b8487058c75ea072f648a0263f1a7836810a0 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Mon, 7 Aug 2023 18:28:24 +0530 Subject: [PATCH 05/56] fix for PNMessageResult --- src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs | 2 +- .../EventEngine/Subscribe/SubscribeEventEngineFactory.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs index 90fc8af3e..fcd427eb6 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs @@ -683,7 +683,7 @@ public void Execute() private void Subscribe(string[] channels, string[] channelGroups, Dictionary externalQueryParam) { Action statusListener = null; - Action> messageListener = null; + Action> messageListener = null; if ((channels == null || channels.Length == 0) && (channelGroups == null || channelGroups.Length == 0)) { throw new ArgumentException("Either Channel Or Channel Group or Both should be provided."); diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngineFactory.cs b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngineFactory.cs index 723fbcb40..c8d48c09c 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngineFactory.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngineFactory.cs @@ -22,14 +22,14 @@ internal SubscribeEventEngine getEventEngine(string instanceId) return subscribeEventEngine; } - internal SubscribeEventEngine initializeEventEngine(string instanceId, + internal SubscribeEventEngine initializeEventEngine(string instanceId, Pubnub pubnubInstance, PNConfiguration pubnubConfiguration, SubscribeManager2 subscribeManager, Action statusListener = null, - Action> messageListener= null) + Action> messageListener= null) { - var subscribeEventEngine = new SubscribeEventEngine(pubnubInstance, pubnubConfiguration: pubnubConfiguration, subscribeManager,statusListener, null); //TODO: replace with message listener + var subscribeEventEngine = new SubscribeEventEngine(pubnubInstance, pubnubConfiguration: pubnubConfiguration, subscribeManager,statusListener, messageListener); if (engineinstances.TryAdd(instanceId, subscribeEventEngine)) { return subscribeEventEngine; } From 0acc10e9c3932ca8ae0cd53ab22dbc9529ebd2d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Mon, 7 Aug 2023 15:05:38 +0200 Subject: [PATCH 06/56] fix: emitter references --- .../EndPoint/PubSub/SubscribeOperation2.cs | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs index fcd427eb6..a1c0074e0 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs @@ -682,9 +682,7 @@ public void Execute() private void Subscribe(string[] channels, string[] channelGroups, Dictionary externalQueryParam) { - Action statusListener = null; - Action> messageListener = null; - if ((channels == null || channels.Length == 0) && (channelGroups == null || channelGroups.Length == 0)) + if ((channels == null || channels.Length == 0) && (channelGroups == null || channelGroups.Length == 0)) { throw new ArgumentException("Either Channel Or Channel Group or Both should be provided."); } @@ -695,12 +693,8 @@ private void Subscribe(string[] channels, string[] channelGroups, Dictionary 0) { - messageListener = MessageEmitter; - statusListener = StatusEmitter; - } var subscribeManager = new SubscribeManager2(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, pubnubTokenMgr, PubnubInstance); - subscribeEventEngine = subscribeEventEngineFactory.initializeEventEngine(instanceId, PubnubInstance, config, subscribeManager, statusListener, messageListener); + subscribeEventEngine = subscribeEventEngineFactory.initializeEventEngine(instanceId, PubnubInstance, config, subscribeManager, StatusEmitter, MessageEmitter); } subscribeEventEngine.Subscribe(channels, channelGroups); @@ -748,22 +742,19 @@ internal void CurrentPubnubInstance(Pubnub instance) } private void MessageEmitter(Pubnub pubnubInstance, PNMessageResult messageResult) { - foreach (var listener in SubscribeListenerList) { - listener.Message(pubnubInstance, messageResult); + foreach (var listener in SubscribeListenerList) + { + listener?.Message(pubnubInstance, messageResult); } } private void StatusEmitter(Pubnub pubnubInstance, PNStatus status) - { - for(int i=0; i < SubscribeListenerList.Count; i++) + { + foreach (var listener in SubscribeListenerList) { - SubscribeCallback listener = SubscribeListenerList[i]; - if (listener != null) - { - listener.Status(pubnubInstance, status); - } + listener?.Status(pubnubInstance, status); } - } + } } } From f74b743e2bac2daaa08f33b93baeb7bb478d9c11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Mon, 7 Aug 2023 15:42:55 +0200 Subject: [PATCH 07/56] wip: error handling --- .../Subscribe/Effects/EmitMessagesHandler.cs | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs index 63b7e2ad0..19bb7c5fa 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs @@ -36,17 +36,15 @@ public async override Task Run(EmitMessagesInvocation invocation) Publisher = m.IssuingClientId }; - Type msgType, groupType; - if (!(channelTypeMap is null) && channelTypeMap.TryGetValue(m.Channel, out msgType)) + try { - msgResult.Message = JsonConvert.DeserializeObject(m.Payload, msgType); - } else if (!(channelGroupTypeMap is null) && channelGroupTypeMap.TryGetValue(m.SubscriptionMatch, out groupType)) - { - msgResult.Message = JsonConvert.DeserializeObject(m.Payload, groupType); + DeserializeMessage(channelTypeMap, m.Channel, msgResult, m.Payload); + DeserializeMessage(channelGroupTypeMap, m.Channel, msgResult, m.Payload); } - else + catch (Exception e) { - msgResult.Message = m.Payload; + // TODO pass the exception + throw e; } return msgResult; @@ -60,6 +58,13 @@ public async override Task Run(EmitMessagesInvocation invocation) } } + private void DeserializeMessage(Dictionary dict, string key, PNMessageResult msg, string rawMessage) + { + if (dict is null) return; + Type t; + msg.Message = dict.TryGetValue(key, out t) ? JsonConvert.DeserializeObject(rawMessage, t) : rawMessage; + } + public override bool IsBackground(EmitMessagesInvocation invocation) => false; public override Task Cancel() From c05b00dcdb4bb179d340c93c3a02de825a66d2f0 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Mon, 7 Aug 2023 19:41:14 +0530 Subject: [PATCH 08/56] fix for ReceiveSuccessEvent --- .../EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs index b2aa6b3fe..f695f68cd 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs @@ -70,7 +70,7 @@ public override async Task Run(ReceiveMessagesInvocation invocation) eventQueue.Enqueue(new Events.ReceiveFailureEvent() { Cursor = cursor, Status = response.Item2}); break; case { }: - eventQueue.Enqueue(new Events.ReceiveSuccessEvent() { Cursor = cursor, Messages= response.Item1, Status = response.Item2 }); + eventQueue.Enqueue(new Events.ReceiveSuccessEvent() { Channels = invocation?.Channels, ChannelGroups = invocation?.ChannelGroups, Cursor = cursor, Messages= response.Item1, Status = response.Item2 }); break; } } From 4f94c14781f937354d0e0f2498080ab5fc94d9a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Mon, 7 Aug 2023 16:12:24 +0200 Subject: [PATCH 09/56] fix: deserialization of messages --- .../PubnubApi/EndPoint/PubSub/SubscribeManager2.cs | 12 ++++++------ .../Subscribe/Effects/EmitMessagesHandler.cs | 14 +++++++++----- .../Subscribe/Effects/ReceivingEffectHandler.cs | 4 ++-- .../Subscribe/Events/SubscriptionEvents.cs | 2 +- .../Invocations/SubscriptionInvocations.cs | 4 ++-- 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs index 17d702851..e261aa739 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs @@ -144,9 +144,9 @@ internal void HandshakeRequestCancellation() LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => HandshakeRequestCancellation. No request to cancel.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); } } - internal async Task, PNStatus>> ReceiveRequest(PNOperationType responseType, string[] channels, string[] channelGroups, long? timetoken, int? region, Dictionary initialSubscribeUrlParams, Dictionary externalQueryParam) + internal async Task, PNStatus>> ReceiveRequest(PNOperationType responseType, string[] channels, string[] channelGroups, long? timetoken, int? region, Dictionary initialSubscribeUrlParams, Dictionary externalQueryParam) { - Tuple, PNStatus> resp = new Tuple, PNStatus>(null, null); + Tuple, PNStatus> resp = new Tuple, PNStatus>(null, null); try { @@ -155,7 +155,7 @@ internal async Task, PNStatus>> ReceiveRequest> pubnubRequestState = new RequestState>(); + RequestState> pubnubRequestState = new RequestState>(); pubnubRequestState.Channels = channels; pubnubRequestState.ChannelGroups = channelGroups; pubnubRequestState.ResponseType = responseType; @@ -169,10 +169,10 @@ internal async Task, PNStatus>> ReceiveRequest receiveResponse = JsonConvert.DeserializeObject>(responseTuple.Item1); - return new Tuple, PNStatus>(receiveResponse, status); + ReceivingResponse receiveResponse = JsonConvert.DeserializeObject>(responseTuple.Item1); + return new Tuple, PNStatus>(receiveResponse, status); } - return new Tuple, PNStatus>(null, responseTuple.Item2); + return new Tuple, PNStatus>(null, responseTuple.Item2); } catch(Exception ex) { diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs index 19bb7c5fa..370e5026c 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Threading.Tasks; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Invocations; @@ -15,12 +16,15 @@ public class EmitMessagesHandler : EffectHandler channelTypeMap; private readonly Dictionary channelGroupTypeMap; - + public EmitMessagesHandler(Pubnub pubnubInstance, System.Action> messageEmitterFunction, Dictionary channelTypeMap = null, Dictionary channelGroupTypeMap = null) { this.messageEmitterFunction = messageEmitterFunction; this.pubnubInstance = pubnubInstance; + + this.channelTypeMap = channelTypeMap; + this.channelGroupTypeMap = channelGroupTypeMap; } public async override Task Run(EmitMessagesInvocation invocation) @@ -38,8 +42,8 @@ public async override Task Run(EmitMessagesInvocation invocation) try { - DeserializeMessage(channelTypeMap, m.Channel, msgResult, m.Payload); - DeserializeMessage(channelGroupTypeMap, m.Channel, msgResult, m.Payload); + DeserializeMessage(channelTypeMap, m.Channel, msgResult, m.Payload as JObject); + DeserializeMessage(channelGroupTypeMap, m.Channel, msgResult, m.Payload as JObject); } catch (Exception e) { @@ -58,11 +62,11 @@ public async override Task Run(EmitMessagesInvocation invocation) } } - private void DeserializeMessage(Dictionary dict, string key, PNMessageResult msg, string rawMessage) + private void DeserializeMessage(Dictionary dict, string key, PNMessageResult msg, JObject rawMessage) { if (dict is null) return; Type t; - msg.Message = dict.TryGetValue(key, out t) ? JsonConvert.DeserializeObject(rawMessage, t) : rawMessage; + msg.Message = dict.TryGetValue(key, out t) ? rawMessage.ToObject(t) : rawMessage.ToString(); } public override bool IsBackground(EmitMessagesInvocation invocation) => false; diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs index b2aa6b3fe..f955acbac 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs @@ -80,9 +80,9 @@ public override bool IsBackground(ReceiveMessagesInvocation invocation) return true; } - private async Task, PNStatus>> MakeReceiveMessagesRequest(ReceiveMessagesInvocation invocation) + private async Task, PNStatus>> MakeReceiveMessagesRequest(ReceiveMessagesInvocation invocation) { - return await manager.ReceiveRequest>( + return await manager.ReceiveRequest>( PNOperationType.PNSubscribeOperation, invocation.Channels?.ToArray(), invocation.ChannelGroups?.ToArray(), diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs index c8334f8de..47a715a0a 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs @@ -48,7 +48,7 @@ public class HandshakeReconnectGiveUpEvent : Core.IEvent { public class ReceiveSuccessEvent : Core.IEvent { public IEnumerable Channels; public IEnumerable ChannelGroups; - public ReceivingResponse Messages; + public ReceivingResponse Messages; public SubscriptionCursor Cursor; public PNStatus Status; } diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs index fe4daad9b..365bd465c 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs @@ -5,9 +5,9 @@ namespace PubnubApi.EventEngine.Subscribe.Invocations { public class EmitMessagesInvocation : Core.IEffectInvocation { - public ReceivingResponse Messages; + public ReceivingResponse Messages; public SubscriptionCursor Cursor; - public EmitMessagesInvocation(SubscriptionCursor cursor, ReceivingResponse messages) + public EmitMessagesInvocation(SubscriptionCursor cursor, ReceivingResponse messages) { this.Cursor = cursor; this.Messages = messages; From 1182abbd0796367a257b2b5e987a223e1ee6b08f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Mon, 7 Aug 2023 16:25:44 +0200 Subject: [PATCH 10/56] fix: deserialization --- .../EventEngine/Subscribe/Effects/EmitMessagesHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs index 370e5026c..1575d21cd 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs @@ -66,7 +66,7 @@ private void DeserializeMessage(Dictionary dict, string key, PNMes { if (dict is null) return; Type t; - msg.Message = dict.TryGetValue(key, out t) ? rawMessage.ToObject(t) : rawMessage.ToString(); + msg.Message = dict.TryGetValue(key, out t) && t != typeof(string) ? rawMessage.ToObject(t) : rawMessage.ToString(); } public override bool IsBackground(EmitMessagesInvocation invocation) => false; From feacb985a07fff69dcc5e3e2cec35277ee6938b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Mon, 7 Aug 2023 16:48:46 +0200 Subject: [PATCH 11/56] fix: usermetadata aka timetoken --- .../EventEngine/Subscribe/Effects/EmitMessagesHandler.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs index 1575d21cd..f48e6b129 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs @@ -6,6 +6,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using PubnubApi.EventEngine.Core; +using PubnubApi.EventEngine.Subscribe.Common; using PubnubApi.EventEngine.Subscribe.Invocations; namespace PubnubApi.EventEngine.Subscribe.Effects @@ -36,8 +37,8 @@ public async override Task Run(EmitMessagesInvocation invocation) Channel = m.Channel, Subscription = m.SubscriptionMatch, Timetoken = invocation.Cursor.Timetoken.Value, - UserMetadata = m.PublishMetadata, - Publisher = m.IssuingClientId + UserMetadata = (m.PublishMetadata as JObject)?.ToObject(), + Publisher = m.IssuingClientId, }; try From b90cb9a2569dd5b9d38f5b94861ff5870dbe835b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Mon, 7 Aug 2023 17:05:01 +0200 Subject: [PATCH 12/56] fix: added serializer settings --- .../Subscribe/Effects/EmitMessagesHandler.cs | 10 ++++++++-- .../EventEngine/Subscribe/SubscribeEventEngine.cs | 8 +++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs index f48e6b129..acb2b48a5 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs @@ -17,15 +17,21 @@ public class EmitMessagesHandler : EffectHandler channelTypeMap; private readonly Dictionary channelGroupTypeMap; + private readonly JsonSerializer serializer; public EmitMessagesHandler(Pubnub pubnubInstance, - System.Action> messageEmitterFunction, Dictionary channelTypeMap = null, Dictionary channelGroupTypeMap = null) + System.Action> messageEmitterFunction, + JsonSerializer serializer, + Dictionary channelTypeMap = null, + Dictionary channelGroupTypeMap = null) { this.messageEmitterFunction = messageEmitterFunction; this.pubnubInstance = pubnubInstance; this.channelTypeMap = channelTypeMap; this.channelGroupTypeMap = channelGroupTypeMap; + + this.serializer = serializer; } public async override Task Run(EmitMessagesInvocation invocation) @@ -67,7 +73,7 @@ private void DeserializeMessage(Dictionary dict, string key, PNMes { if (dict is null) return; Type t; - msg.Message = dict.TryGetValue(key, out t) && t != typeof(string) ? rawMessage.ToObject(t) : rawMessage.ToString(); + msg.Message = dict.TryGetValue(key, out t) && t != typeof(string) ? rawMessage.ToObject(t, serializer) : rawMessage.ToString(Formatting.None); } public override bool IsBackground(EmitMessagesInvocation invocation) => false; diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs index 376fb51d1..4b6f5a4d1 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs @@ -4,6 +4,8 @@ using PubnubApi.EventEngine.Subscribe.Events; using PubnubApi.EventEngine.Subscribe.Effects; using PubnubApi.EventEngine.Subscribe.Invocations; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; @@ -13,6 +15,10 @@ public class SubscribeEventEngine : Engine { private readonly Dictionary channelTypeMap = new Dictionary(); private readonly Dictionary channelGroupTypeMap = new Dictionary(); + + private static readonly JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() + { Formatting = Formatting.None, DateParseHandling = DateParseHandling.None }; + private static readonly JsonSerializer Serializer = JsonSerializer.Create(SerializerSettings); internal SubscribeEventEngine(Pubnub pubnubInstance, PNConfiguration pubnubConfiguration, @@ -35,7 +41,7 @@ internal SubscribeEventEngine(Pubnub pubnubInstance, dispatcher.Register(receiveHandler); dispatcher.Register(receiveHandler); - var emitMessageHandler = new Effects.EmitMessagesHandler(pubnubInstance, messageListener, channelTypeMap, channelGroupTypeMap); + var emitMessageHandler = new Effects.EmitMessagesHandler(pubnubInstance, messageListener, Serializer, channelTypeMap, channelGroupTypeMap); dispatcher.Register(emitMessageHandler); var emitStatusHandler = new Effects.EmitStatusEffectHandler(pubnubInstance, statusListener); From 421224e989344dc1d92b9dedf75f2ed7c472000b Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Mon, 7 Aug 2023 21:01:36 +0530 Subject: [PATCH 13/56] unit test fix --- .../PubnubApi.Tests/EventEngine/ReceivingStateTransition.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/UnitTests/PubnubApi.Tests/EventEngine/ReceivingStateTransition.cs b/src/UnitTests/PubnubApi.Tests/EventEngine/ReceivingStateTransition.cs index 50e3fafd5..e908e0087 100644 --- a/src/UnitTests/PubnubApi.Tests/EventEngine/ReceivingStateTransition.cs +++ b/src/UnitTests/PubnubApi.Tests/EventEngine/ReceivingStateTransition.cs @@ -41,7 +41,7 @@ internal class ReceivingStateTransition ChannelGroups = new string[] { "cg1", "cg2" }, Cursor = new SubscriptionCursor() { Region = 1, Timetoken = 1234567890 }, Status = new PNStatus(null, PNOperationType.PNSubscribeOperation, PNStatusCategory.PNConnectedCategory), - Messages = new ReceivingResponse() { Messages = new Message[]{ }, Timetoken = new Timetoken(){ Region = 1, Timestamp = 1234567890 } } + Messages = new ReceivingResponse() { Messages = new Message[]{ }, Timetoken = new Timetoken(){ Region = 1, Timestamp = 1234567890 } } }, new ReceivingState(){ Channels = new string[] { "ch1", "ch2" }, ChannelGroups = new string[] { "cg1", "cg2" }, Cursor = new SubscriptionCursor() { Region = 1, Timetoken = 1234567890 }, ReconnectionConfiguration = new ReconnectionConfiguration(PNReconnectionPolicy.LINEAR, 50) } } From 9b661934b1230dd69ca0737de026c91965bec711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Mon, 7 Aug 2023 18:18:26 +0200 Subject: [PATCH 14/56] fix: fixed string edge-case --- .../Subscribe/Effects/EmitMessagesHandler.cs | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs index acb2b48a5..d17f573ff 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs @@ -49,8 +49,8 @@ public async override Task Run(EmitMessagesInvocation invocation) try { - DeserializeMessage(channelTypeMap, m.Channel, msgResult, m.Payload as JObject); - DeserializeMessage(channelGroupTypeMap, m.Channel, msgResult, m.Payload as JObject); + DeserializeMessage(channelTypeMap, m.Channel, msgResult, m.Payload); + DeserializeMessage(channelGroupTypeMap, m.Channel, msgResult, m.Payload); } catch (Exception e) { @@ -62,18 +62,28 @@ public async override Task Run(EmitMessagesInvocation invocation) }); if (processedMessages is null) return; - + foreach (var message in processedMessages) { messageEmitterFunction(pubnubInstance, message); } } - private void DeserializeMessage(Dictionary dict, string key, PNMessageResult msg, JObject rawMessage) + private void DeserializeMessage(Dictionary dict, string key, PNMessageResult msg, + object rawMessage) { if (dict is null) return; - Type t; - msg.Message = dict.TryGetValue(key, out t) && t != typeof(string) ? rawMessage.ToObject(t, serializer) : rawMessage.ToString(Formatting.None); + if (rawMessage is JObject message) + { + Type t; + msg.Message = dict.TryGetValue(key, out t) && t != typeof(string) + ? message.ToObject(t, serializer) + : message.ToString(Formatting.None); + } + else + { + msg.Message = rawMessage; + } } public override bool IsBackground(EmitMessagesInvocation invocation) => false; From e829c3b7a9e4548a49ee9f87e87a18f6acd1dd32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Tue, 8 Aug 2023 10:46:52 +0200 Subject: [PATCH 15/56] wip: switched user metadata source --- .../EventEngine/Subscribe/Common/CommonSubscribeTypes.cs | 3 +++ .../EventEngine/Subscribe/Effects/EmitMessagesHandler.cs | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs index 2f7503d6c..ff2362cfe 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs @@ -80,6 +80,9 @@ public class Message [JsonProperty("s")] public long SequenceNumber { get; set; } + + [JsonProperty("u")] + public object UserMetadata { get; set; } } public abstract class SubscriptionState : Core.State diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs index d17f573ff..8c4b29432 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs @@ -43,7 +43,9 @@ public async override Task Run(EmitMessagesInvocation invocation) Channel = m.Channel, Subscription = m.SubscriptionMatch, Timetoken = invocation.Cursor.Timetoken.Value, - UserMetadata = (m.PublishMetadata as JObject)?.ToObject(), + UserMetadata = (m.UserMetadata as object), + // TODO Where do we put the publish timetoken metadata? + // UserMetadata = (m.PublishMetadata as JObject)?.ToObject(), Publisher = m.IssuingClientId, }; From cdddbd5dae6c726e5f41c15974f588deb399e140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Tue, 8 Aug 2023 10:53:22 +0200 Subject: [PATCH 16/56] wip: added null check in ReceivingEffectHandler.cs --- .../EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs index edb97f57f..4395933a4 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs @@ -66,6 +66,10 @@ public override async Task Run(ReceiveMessagesInvocation invocation) case Invocations.ReceiveReconnectInvocation reconnectInvocation: eventQueue.Enqueue(new Events.ReceiveReconnectSuccessEvent() { Cursor = cursor, Status = response.Item2 }); break; + // TODO find a case when status (Item2) is null + case { } when response.Item2 is null: + eventQueue.Enqueue(new Events.ReceiveFailureEvent() { Cursor = cursor, Status = new PNStatus() {Category = PNStatusCategory.PNUnexpectedDisconnectCategory, Error = true, ErrorData = new PNErrorData("Status was null", new System.NullReferenceException())}}); + break; case { } when response.Item2.Error: eventQueue.Enqueue(new Events.ReceiveFailureEvent() { Cursor = cursor, Status = response.Item2}); break; From 98e81658cf97f1812ef8596ec924c3da7187f51e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Tue, 8 Aug 2023 10:55:46 +0200 Subject: [PATCH 17/56] wip: null check. --- .../Subscribe/Effects/ReceivingEffectHandler.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs index 4395933a4..b8e03514f 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs @@ -58,6 +58,10 @@ public override async Task Run(ReceiveMessagesInvocation invocation) Timetoken = response.Item1?.Timetoken.Timestamp }; + // Assume that if status is null, the effect was cancelled. + if (response.Item2 is null) + return; + switch (invocation) { case Invocations.ReceiveReconnectInvocation reconnectInvocation when response.Item2.Error: @@ -66,10 +70,6 @@ public override async Task Run(ReceiveMessagesInvocation invocation) case Invocations.ReceiveReconnectInvocation reconnectInvocation: eventQueue.Enqueue(new Events.ReceiveReconnectSuccessEvent() { Cursor = cursor, Status = response.Item2 }); break; - // TODO find a case when status (Item2) is null - case { } when response.Item2 is null: - eventQueue.Enqueue(new Events.ReceiveFailureEvent() { Cursor = cursor, Status = new PNStatus() {Category = PNStatusCategory.PNUnexpectedDisconnectCategory, Error = true, ErrorData = new PNErrorData("Status was null", new System.NullReferenceException())}}); - break; case { } when response.Item2.Error: eventQueue.Enqueue(new Events.ReceiveFailureEvent() { Cursor = cursor, Status = response.Item2}); break; From 0ea9033b70fb96624e789289fd6dcb3c6dda6f17 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Tue, 8 Aug 2023 14:56:48 +0530 Subject: [PATCH 18/56] removed unused files --- .../EndPoint/PubSub/SubscribeOperation2.cs | 37 - .../PubnubApi/EventEngine/EffectDispatcher.cs | 52 -- src/Api/PubnubApi/EventEngine/EventEmitter.cs | 37 - src/Api/PubnubApi/EventEngine/EventEngine.cs | 781 ------------------ .../EventEngine/HandshakeEffectHandler.cs | 185 ----- .../HandshakeFailedEffectHandler.cs | 68 -- .../HandshakeReconnectEffectHandler.cs | 274 ------ .../EventEngine/IEffectInvocationHandler.cs | 37 - .../ReceiveReconnectingEffectHandler.cs | 273 ------ .../EventEngine/ReceivingEffectHandler.cs | 294 ------- src/Api/PubnubApi/EventEngine/State.cs | 58 -- .../PubnubApi/Interface/IPubnubUnitTest.cs | 3 +- src/Api/PubnubApiPCL/PubnubApiPCL.csproj | 10 - src/Api/PubnubApiUWP/PubnubApiUWP.csproj | 10 - 14 files changed, 1 insertion(+), 2118 deletions(-) delete mode 100644 src/Api/PubnubApi/EventEngine/EffectDispatcher.cs delete mode 100644 src/Api/PubnubApi/EventEngine/EventEmitter.cs delete mode 100644 src/Api/PubnubApi/EventEngine/EventEngine.cs delete mode 100644 src/Api/PubnubApi/EventEngine/HandshakeEffectHandler.cs delete mode 100644 src/Api/PubnubApi/EventEngine/HandshakeFailedEffectHandler.cs delete mode 100644 src/Api/PubnubApi/EventEngine/HandshakeReconnectEffectHandler.cs delete mode 100644 src/Api/PubnubApi/EventEngine/IEffectInvocationHandler.cs delete mode 100644 src/Api/PubnubApi/EventEngine/ReceiveReconnectingEffectHandler.cs delete mode 100644 src/Api/PubnubApi/EventEngine/ReceivingEffectHandler.cs delete mode 100644 src/Api/PubnubApi/EventEngine/State.cs diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs index a1c0074e0..9fa53a56b 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs @@ -6,7 +6,6 @@ using System.Threading.Tasks; using System.Net; using System.Globalization; -using PubnubApi.PubnubEventEngine; using PubnubApi.EventEngine.Subscribe; using PubnubApi; @@ -49,42 +48,6 @@ public SubscribeOperation2(PNConfiguration pubnubConfig, IJsonPluggableLibrary j this.subscribeEventEngineFactory = subscribeEventEngineFactory; this.instanceId = instanceId; - var eventEmitter = new EventEmitter(); - eventEmitter.RegisterJsonListener(JsonCallback); - - // pnEventEngine = new EventEngine(effectDispatcher, eventEmitter); - // pnEventEngine.PubnubUnitTest = unit; - // pnEventEngine.Setup(config); - - // if (pnEventEngine.PubnubUnitTest != null) - // { - // pnEventEngine.PubnubUnitTest.EventTypeList = new List>(); - // } - // else - // { - //pnEventEngine.InitialState(new State(StateType.Unsubscribed) { EventType = EventType.SubscriptionChanged }); - // } - } - - private void HandshakeEffect_CancelHandshakeRequested(object sender, CancelHandshakeRequestEventArgs e) - { - manager.HandshakeRequestCancellation(); - } - private void HandshakeReconnectEffect_CancelHandshakeRequested(object sender, CancelHandshakeReconnectRequestEventArgs e) - { - manager.HandshakeRequestCancellation(); - } - private void ReceivingEffect_CancelReceiveRequested(object sender, CancelReceiveRequestEventArgs e) - { - manager.ReceiveRequestCancellation(); - } - private void ReceiveReconnectEffect_CancelReceiveRequested(object sender, CancelReceiveReconnectRequestEventArgs e) - { - manager.ReceiveReconnectRequestCancellation(); - } - - private void JsonCallback(string json, bool zeroTimeTokenRequest, int messageCount) - { } protected void ProcessListenerCallback(List result, bool zeroTimeTokenRequest, int messageCount, string[] channels, string[] channelGroups) diff --git a/src/Api/PubnubApi/EventEngine/EffectDispatcher.cs b/src/Api/PubnubApi/EventEngine/EffectDispatcher.cs deleted file mode 100644 index 0f94f3a99..000000000 --- a/src/Api/PubnubApi/EventEngine/EffectDispatcher.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace PubnubApi.PubnubEventEngine -{ - public class EffectDispatcher - { - public IPubnubUnitTest PubnubUnitTest { get; set; } - - private Dictionary effectInvocationActionMap; - public EffectDispatcher() - { - effectInvocationActionMap = new Dictionary(); - } - - public async void dispatch(EventType eventType,List effectInvocations, ExtendedState stateContext) - { - if (effectInvocations == null || effectInvocations.Count == 0) { return; } - foreach (var invocation in effectInvocations) { - PubnubUnitTest?.EventTypeList?.Add(new KeyValuePair("invocation", invocation.Name)); - System.Diagnostics.Debug.WriteLine("Found effect " + invocation.Effectype); - IEffectInvocationHandler currentEffectInvocationhandler; - if (effectInvocationActionMap.TryGetValue(invocation.Effectype, out currentEffectInvocationhandler)) - { - if (invocation.IsManaged()) - { - await Task.Factory.StartNew(()=> currentEffectInvocationhandler?.Start(stateContext, eventType)).ConfigureAwait(false); - } - else if (invocation.IsCancelling()) - { - await Task.Factory.StartNew(()=> currentEffectInvocationhandler?.Cancel()).ConfigureAwait(false); - } - else - { - currentEffectInvocationhandler.Run(stateContext); - } - } - } - - } - - public void Register(EventType type, IEffectInvocationHandler handler) - { - if (effectInvocationActionMap.ContainsKey(type)) - { - throw new ArgumentException("EventType already exist"); - } - effectInvocationActionMap.Add(type, handler); - } - } -} diff --git a/src/Api/PubnubApi/EventEngine/EventEmitter.cs b/src/Api/PubnubApi/EventEngine/EventEmitter.cs deleted file mode 100644 index 1022e3665..000000000 --- a/src/Api/PubnubApi/EventEngine/EventEmitter.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; - -namespace PubnubApi.PubnubEventEngine -{ - public class EventEmitter - { - private Action? handler; - private Action? jsonListener; - - public void RegisterHandler(Action eventHandler) - { - this.handler = eventHandler; - } - - public void RegisterJsonListener(Action listenerHandler) - { - this.jsonListener = listenerHandler; - } - - public void emit(Event e) - { - if (handler == null) - { - throw new MissingMemberException("eventHandler is missing"); - } - this.handler(e); - } - - public void emit(string json, bool zeroTimetokenRequest, int messageCount) - { - if (jsonListener != null) - { - jsonListener(json, zeroTimetokenRequest, messageCount); - } - } - } -} diff --git a/src/Api/PubnubApi/EventEngine/EventEngine.cs b/src/Api/PubnubApi/EventEngine/EventEngine.cs deleted file mode 100644 index 5614914d9..000000000 --- a/src/Api/PubnubApi/EventEngine/EventEngine.cs +++ /dev/null @@ -1,781 +0,0 @@ -using Newtonsoft.Json; -using PubnubApi.EndPoint; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace PubnubApi.PubnubEventEngine -{ - public class PubnubError : Exception - { - - } - - #region Event - public abstract class Event - { - public virtual string Name { get; set; } - public virtual EventType EventType { get; set; } - public virtual EventPayload EventPayload { get; set; } - public virtual int Attempts { get; set; } - - public Event() - { - EventPayload = new EventPayload(); - } - } - - public class SubscriptionChanged : Event - { - public List Channels { get; set; } - public List ChannelGroups { get; set; } - } - public class Disconnect : Event - { - - } - public class Reconnect : Event - { - - } - public class HandshakeSuccess : Event - { - public SubscriptionCursor SubscriptionCursor { get; set; } - } - public class SubscriptionRestored : Event - { - public List Channels { get; set; } - public List ChannelGroups { get; set; } - public SubscriptionCursor SubscriptionCursor { get; set; } - } - public class HandshakeFailure : Event - { - public PubnubError Reason { get; set; } - } - public class HandshakeReconnectGiveUp : Event - { - public PubnubError Reason { get; set;} - } - public class HandshakeReconnectSuccess : Event - { - public List Channels { get; set; } - public List ChannelGroups { get; set; } - public SubscriptionCursor SubscriptionCursor { get; set; } - } - public class HandshakeReconnectFailure : Event - { - public PubnubError Reason { get; set;} - } - public class ReceiveSuccess : Event - { - public List Messages { get; set; } - public SubscriptionCursor SubscriptionCursor { get; set; } - } - public class ReceiveFailure : Event - { - public PubnubError Reason { get; set;} - } - public class ReceiveReconnectFailure : Event - { - public PubnubError Reason { get; set;} - } - public class ReceiveReconnectGiveUp : Event - { - public PubnubError Reason { get; set;} - } - public class ReceiveReconnectSuccess : Event - { - public List Messages { get; set; } - public SubscriptionCursor SubscriptionCursor { get; set; } - } - public class Fail : Event - { - - } - public class Success : Event - { - - } - #endregion - public class EventPayload - { - public List? Channels { get; set; } - public List? ChannelGroups { get; set; } - public long? Timetoken { get; set; } - public int? Region { get; set; } - - public Exception? exception { get; set; } - } - - - public class SubscriptionCursor - { - public long? Timetoken { get; set; } - public int? Region { get; set; } - } - - #region EffectInvocation - public abstract class EffectInvocation - { - public virtual string Name { get; set; } - public virtual EventType Effectype { get; set; } - public virtual EffectInvocationType InvocationType { get; set; } - public virtual IEffectInvocationHandler Handler { get; set; } - public abstract bool IsManaged(); - public abstract bool IsCancelling(); - } - public class ReceiveMessages: EffectInvocation - { - public List Channels { get; set; } - public List ChannelGroups { get; set; } - public SubscriptionCursor SubscriptionCursor { get; set; } - - public override bool IsManaged() - { - return true; - } - public override bool IsCancelling() - { - return false; - } - - } - public class CancelReceiveMessages : EffectInvocation - { - public override bool IsManaged() - { - return false; - } - public override bool IsCancelling() - { - return true; - } - } - public class ReceiveReconnect: EffectInvocation - { - public List Channels { get; set; } - public List ChannelGroups { get; set; } - public SubscriptionCursor SubscriptionCursor { get; set; } - public int Attempts { get; set; } - public PubnubError Reason { get; set; } - public override bool IsManaged() - { - return true; - } - public override bool IsCancelling() - { - return false; - } - } - public class CancelReceiveReconnect : EffectInvocation - { - public override bool IsManaged() - { - return false; - } - public override bool IsCancelling() - { - return true; - } - } - public class Handshake : EffectInvocation - { - public List Channels { get; set; } - public List ChannelGroups { get; set; } - public override bool IsManaged() - { - return true; - } - public override bool IsCancelling() - { - return false; - } - } - public class CancelHandshake : EffectInvocation - { - public override bool IsManaged() - { - return false; - } - public override bool IsCancelling() - { - return true; - } - } - public class HandshakeReconnect : EffectInvocation - { - public List Channels { get; set; } - public List ChannelGroups { get; set; } - public SubscriptionCursor SubscriptionCursor { get; set; } - public int Attempts { get; set; } - public PubnubError Reason { get; set; } - public override bool IsManaged() - { - return true; - } - public override bool IsCancelling() - { - return false; - } - } - public class CancelHandshakeReconnect : EffectInvocation - { - public override bool IsManaged() - { - return false; - } - public override bool IsCancelling() - { - return true; - } - } - public class EmitStatus : EffectInvocation - { - private readonly PNStatusCategory statusCategory; - public Action AnnounceStatus { get; set; } - public EmitStatus() - { - } - public EmitStatus(PNStatusCategory status) - { - statusCategory = status; - } - - public void Announce() - { - if (Handler != null) - { - PNStatus status = Handler.GetPNStatus(); - if (AnnounceStatus != null && status != null) - { - if (Handler is ReceivingEffectHandler && status.StatusCode == 200) - { - //Ignore Announce for 200 - return; - } - else if (Handler is ReceiveReconnectingEffectHandler && status.StatusCode == 200) - { - //Ignore Announce for 200 - return; - } - System.Diagnostics.Debug.WriteLine($"Status Category = {status.Category} to be announced"); - AnnounceStatus(status); - } - } - } - - public override bool IsManaged() - { - return false; - } - public override bool IsCancelling() - { - return false; - } - } - public class EmitMessages : EffectInvocation - { - public Action LogCallback { get; set; } - //public SubscribeOperation2 SubscribeOperation { get; set; } - public Action> AnnounceMessage { get; set; } - public EmitMessages(List messages) - { - - } - public void Announce() - { - } - - public override bool IsManaged() - { - return false; - } - public override bool IsCancelling() - { - return false; - } - } - - public class HandshakeFailed : EffectInvocation - { - public List Channels { get; set; } - public List ChannelGroups { get; set; } - public override bool IsManaged() - { - return true; - } - public override bool IsCancelling() - { - return false; - } - } - public class CancelHandshakeFailed : EffectInvocation - { - public override bool IsManaged() - { - return false; - } - public override bool IsCancelling() - { - return true; - } - } - #endregion - public enum EventType - { - SubscriptionChanged, - SubscriptionRestored, - Handshake, - CancelHandshake, - HandshakeSuccess, - ReceiveMessages, - CancelReceiveMessages, - ReceiveSuccess, - HandshakeFailure, - CancelHandshakeFailure, - ReceiveFailure, - ReceiveReconnect, - CancelReceiveReconnect, - ReceiveReconnectSuccess, - ReceiveReconnectFailure, - ReceiveReconnectGiveUp, - HandshakeReconnect, - CancelHandshakeReconnect, - HandshakeReconnectSuccess, - HandshakeReconnectFailure, - HandshakeReconnectGiveUp, - ReconnectionFailed, - Disconnect, - Reconnect - } - - public class ExtendedState - { - public List Channels { get; set; } - public List ChannelGroups { get; set; } - public long? Timetoken { get; set; } - public int? Region { get; set; } - public int Attempts { get; set; } - - public ExtendedState() - { - Channels = new List(); - ChannelGroups = new List(); - Timetoken = 0; - Region = 0; - Attempts = 0; - } - - } - - public class EventEngine - { - private EventEngine pnEventEngine = null; - - public ExtendedState Context; - public State? CurrentState { get; set; } - public List States { get; set; } - - public EffectDispatcher Dispatcher; - - public EventEmitter Emitter; - public IPubnubUnitTest PubnubUnitTest { get; set; } - - public EventEngine(EffectDispatcher dispatcher, EventEmitter emitter) - { - if (PubnubUnitTest != null ) - { - PubnubUnitTest.EventTypeList?.Clear(); - } - this.Dispatcher = dispatcher; - States = new List(); - Context = new ExtendedState(); - this.Emitter = emitter; - emitter.RegisterHandler(this.Transition); - } - - public State CreateState(StateType type) - { - var newState = new State(type); - if (States.Find(s=> s.StateType == type) != null) - { - throw new InvalidOperationException($"StateType = {type} already exist."); - } - States.Add(newState); - return newState; - } - - public void Transition(Event e) - { - if (CurrentState != null) { - State findState = States.Find((s) => s.StateType == CurrentState.StateType); - StateType nextStateType; - if (findState != null && findState.transitions != null && findState.transitions.TryGetValue(e.EventType, out nextStateType)) - { - System.Diagnostics.Debug.WriteLine($"Current State = {CurrentState.StateType}; Transition = {e.EventType}"); - if (PubnubUnitTest != null ) - { - PubnubUnitTest.EventTypeList.Add(new KeyValuePair("event", e.Name)); - PubnubUnitTest.Attempts = e.Attempts; - } - if (findState != null) - { - if (findState.ExitList != null && findState.ExitList.Count > 0) - { - Dispatcher.dispatch(e.EventType, findState.ExitList, this.Context); - } - if (findState.EffectInvocationsList != null - && findState.EffectInvocationsList.ContainsKey(e.EventType) - && findState.EffectInvocationsList[e.EventType].Count > 0) - { - List effectInvocationList = findState.EffectInvocationsList[e.EventType]; - if (effectInvocationList != null && effectInvocationList.Count > 0) - { - Dispatcher.dispatch(e.EventType, effectInvocationList, this.Context); - } - } - - CurrentState = States.Find((s) => s.StateType == nextStateType); - UpdateContext(e.EventType, e.EventPayload); - if (CurrentState.EntryList != null && CurrentState.EntryList.Count > 0) - { - Dispatcher.dispatch(e.EventType, CurrentState.EntryList, this.Context); - } - - UpdateContext(e.EventType, e.EventPayload); - } - - } - - } - } - - public void Subscribe(List channels, List? channelGroups) - { - var evnt = new SubscriptionChanged(); - evnt.Name = "SUBSCRIPTION_CHANGED"; - evnt.EventType = EventType.SubscriptionChanged; - evnt.EventPayload.Channels = channels; - if (channelGroups != null) evnt.EventPayload.ChannelGroups = channelGroups; - this.Transition(evnt); - } - - private void UpdateContext(EventType eventType, EventPayload eventData) - { - if (CurrentState != null) - { - CurrentState.EventType = eventType; - } - if (eventData.Channels != null) Context.Channels = eventData.Channels; - if (eventData.ChannelGroups != null) Context.ChannelGroups = eventData.ChannelGroups; - if (eventData.Timetoken != null) - { - System.Diagnostics.Debug.WriteLine($"eventData.Timetoken = {eventData.Timetoken.Value}"); - System.Diagnostics.Debug.WriteLine($"Context.Timetoken = {Context.Timetoken.Value}"); - if (Context.Timetoken > 0 && - eventType == EventType.HandshakeSuccess && - Context.Timetoken < eventData.Timetoken) - { - System.Diagnostics.Debug.WriteLine("Keeping last Context.Timetoken"); - // do not change context timetoken. We want last timetoken. - } - else - { - Context.Timetoken = eventData.Timetoken; - } - } - if (eventData.Region != null) Context.Region = eventData.Region; - } - - public void InitialState(State state) - { - this.CurrentState = state; - } - - public State NextState() - { - State nextState = null; - if (CurrentState != null) - { - StateType nextStateType; - State findState = States.Find((s) => s.StateType == CurrentState.StateType); - if (findState != null && findState.transitions != null && findState.transitions.ContainsKey(CurrentState.EventType)) - { - nextStateType = findState.transitions[CurrentState.EventType]; - nextState = States.Find((s) => s.StateType == nextStateType); - } - } - return nextState; - } - - public void Setup(PNConfiguration config) - { - - - CreateState(StateType.Unsubscribed) - .On(EventType.SubscriptionChanged, StateType.Handshaking) - .On(EventType.SubscriptionRestored, StateType.Receiving); - - #region Handshake Effect Invocations and Emit Status - EmitStatus handshakeSuccessEmitStatus = new EmitStatus(); - handshakeSuccessEmitStatus.Name = "EMIT_STATUS"; - handshakeSuccessEmitStatus.Effectype = EventType.HandshakeSuccess; - - EffectInvocation handshakeInvocation = new Handshake(); - handshakeInvocation.Name = "HANDSHAKE"; - handshakeInvocation.Effectype = EventType.Handshake; - - EffectInvocation cancelHandshakeInvocation = new CancelHandshake(); - cancelHandshakeInvocation.Name = "CANCEL_HANDSHAKE"; - cancelHandshakeInvocation.Effectype = EventType.CancelHandshake; - #endregion - #region StateType.Handshaking - CreateState(StateType.Handshaking) - .On(EventType.SubscriptionChanged, StateType.Handshaking) - .On(EventType.HandshakeSuccess, StateType.Receiving, new List() - { - handshakeSuccessEmitStatus - } - ) - .On(EventType.HandshakeFailure, StateType.HandshakeReconnecting) - .On(EventType.Disconnect, StateType.HandshakeStopped) - .On(EventType.SubscriptionRestored, StateType.Receiving) - .OnEntry(entryInvocationList: new List() - { - handshakeInvocation - } - ) - .OnExit(exitInvocationList: new List() - { - cancelHandshakeInvocation - } - ); - #endregion - - #region HandshakeReconnecting Effect Invocations and Emit Status - EmitStatus handshakeReconnectSuccessEmitStatus = new EmitStatus(); - handshakeReconnectSuccessEmitStatus.Name = "EMIT_STATUS"; - handshakeReconnectSuccessEmitStatus.Effectype = EventType.HandshakeReconnectSuccess; - - //TBD - Should we emit status/error on HandshakeReconnectFailure - //EmitStatus handshakeReconnectFailureEmitStatus = new EmitStatus(); - // handshakeReconnectFailureEmitStatus.Name = "EMIT_STATUS"; - // handshakeReconnectFailureEmitStatus.Effectype = EventType.HandshakeReconnectFailure; - - EmitStatus handshakeReconnectGiveupEmitStatus = new EmitStatus(); - handshakeReconnectGiveupEmitStatus.Name = "EMIT_STATUS"; - handshakeReconnectGiveupEmitStatus.Effectype = EventType.HandshakeReconnectGiveUp; - - EffectInvocation handshakeReconnectInvocation = new HandshakeReconnect(); - handshakeReconnectInvocation.Name = "HANDSHAKE_RECONNECT"; - handshakeReconnectInvocation.Effectype = EventType.HandshakeReconnect; - - EffectInvocation cancelHandshakeReconnectInvocation = new CancelHandshakeReconnect(); - cancelHandshakeReconnectInvocation.Name = "CANCEL_HANDSHAKE_RECONNECT"; - cancelHandshakeReconnectInvocation.Effectype = EventType.CancelHandshakeReconnect; - #endregion - #region StateType.HandshakeReconnecting - CreateState(StateType.HandshakeReconnecting) - .On(EventType.SubscriptionChanged, StateType.Handshaking) - .On(EventType.HandshakeReconnectFailure, StateType.HandshakeReconnecting) - // .On(EventType.HandshakeReconnectFailure, StateType.HandshakeReconnecting, new List() - // { - // handshakeReconnectFailureEmitStatus - // } - //) - .On(EventType.Disconnect, StateType.HandshakeStopped) - .On(EventType.HandshakeReconnectGiveUp, StateType.HandshakeFailed, new List() - { - handshakeReconnectGiveupEmitStatus - } - ) - .On(EventType.HandshakeReconnectSuccess, StateType.Receiving, new List() - { - handshakeReconnectSuccessEmitStatus - } - ) - .On(EventType.SubscriptionRestored, StateType.Receiving) - .OnEntry(entryInvocationList: new List() - { - handshakeReconnectInvocation - } - ) - .OnExit(exitInvocationList: new List() - { - cancelHandshakeReconnectInvocation - } - ); - #endregion - - #region HandshakeFailed Effect Invocations and Emit Status - EffectInvocation handshakeFailedInvocation = new HandshakeFailed(); - handshakeFailedInvocation.Name = "HANDSHAKE_FAILED"; - handshakeFailedInvocation.Effectype = EventType.HandshakeFailure; - - EffectInvocation cancelHandshakeFailedInvocation = new CancelHandshakeFailed(); - cancelHandshakeFailedInvocation.Name = "CANCEL_HANDSHAKE_FAILED"; - cancelHandshakeFailedInvocation.Effectype = EventType.CancelHandshakeFailure; - #endregion - #region StateType.HandshakeFailed - CreateState(StateType.HandshakeFailed) - .On(EventType.SubscriptionChanged, StateType.Handshaking) - .On(EventType.Reconnect, StateType.Handshaking) - .On(EventType.SubscriptionRestored, StateType.Receiving) - .OnEntry(entryInvocationList: new List() - { - handshakeFailedInvocation - } - ) - .OnExit(exitInvocationList: new List() - { - cancelHandshakeFailedInvocation - } - ); - #endregion - - #region HandshakeStopped Effect Invocations and Emit Status - #endregion - #region StateType.HandshakeStopped - CreateState(StateType.HandshakeStopped) - .On(EventType.Reconnect, StateType.Handshaking); - #endregion - - #region Receiving Effect Invocations and Emit Status - EmitStatus receiveEmitStatus = new EmitStatus(); - receiveEmitStatus.Name = "EMIT_STATUS"; - receiveEmitStatus.Effectype = EventType.ReceiveSuccess; - - EmitMessages receiveEmitMessages = new EmitMessages(null); - receiveEmitMessages.Name = "EMIT_EVENTS"; - receiveEmitMessages.Effectype = EventType.ReceiveMessages; - - EmitStatus receiveDisconnectEmitStatus = new EmitStatus(); - receiveDisconnectEmitStatus.Name = "EMIT_STATUS"; - receiveDisconnectEmitStatus.Effectype = EventType.Disconnect; - - EffectInvocation receiveMessagesInvocation = new ReceiveMessages(); - receiveMessagesInvocation.Name = "RECEIVE_EVENTS"; - receiveMessagesInvocation.Effectype = EventType.ReceiveMessages; - - EffectInvocation cancelReceiveMessages = new CancelReceiveMessages(); - cancelReceiveMessages.Name = "CANCEL_RECEIVE_EVENTS"; - cancelReceiveMessages.Effectype = EventType.CancelReceiveMessages; - #endregion - #region StateType.Receiving - CreateState(StateType.Receiving) - .On(EventType.SubscriptionChanged, StateType.Receiving) - .On(EventType.SubscriptionRestored, StateType.Receiving) - .On(EventType.ReceiveSuccess, StateType.Receiving, new List() - { - receiveEmitStatus, - receiveEmitMessages - } - ) - .On(EventType.Disconnect, StateType.ReceiveStopped, new List() - { - receiveDisconnectEmitStatus - } - ) - .On(EventType.ReceiveFailure, StateType.ReceiveReconnecting) - .OnEntry(entryInvocationList: new List() - { - receiveMessagesInvocation - } - ) - .OnExit(exitInvocationList: new List() - { - cancelReceiveMessages - } - ); - #endregion - - #region ReceiveFailed Effect Invocations and Emit Status - #endregion - #region StateType.ReceiveFailed - CreateState(StateType.ReceiveFailed) - .On(EventType.SubscriptionChanged, StateType.Receiving) - .On(EventType.SubscriptionRestored, StateType.Receiving) - .On(EventType.Reconnect, StateType.Receiving); - #endregion - - #region ReceiveReconnecting Effect Invocations and Emit Status - EmitStatus receiveReconnectEmitStatus = new EmitStatus(); - receiveReconnectEmitStatus.Name = "RECONNECT_EMIT_STATUS"; - receiveReconnectEmitStatus.Effectype = EventType.ReceiveReconnectSuccess; - - EmitMessages receiveReconnectEmitMessages = new EmitMessages(null); - receiveReconnectEmitMessages.Name = "RECEIVE_RECONNECT_EVENTS"; - receiveReconnectEmitMessages.Effectype = EventType.ReceiveMessages; - - EmitStatus receiveReconnectDisconnectEmitStatus = new EmitStatus(); - receiveReconnectDisconnectEmitStatus.Name = "RECONNECT_DISCONNECT_STATUS"; - receiveReconnectDisconnectEmitStatus.Effectype = EventType.Disconnect; - - EmitStatus receiveReconnectGiveupEmitStatus = new EmitStatus(); - receiveReconnectGiveupEmitStatus.Name = "RECONNECT_GIVEUP_STATUS"; - receiveReconnectGiveupEmitStatus.Effectype = EventType.ReceiveReconnectGiveUp; - - EffectInvocation receiveReconnectInvocation = new ReceiveReconnect(); - receiveReconnectInvocation.Name = "RECEIVE_RECONNECT"; - receiveReconnectInvocation.Effectype = EventType.ReceiveReconnect; - - EffectInvocation cancelReceiveReconnect = new CancelReceiveReconnect(); - cancelReceiveReconnect.Name = "CANCEL_RECEIVE_RECONNECT"; - cancelReceiveReconnect.Effectype = EventType.CancelReceiveReconnect; - #endregion - #region StateType.ReceiveReconnecting - CreateState(StateType.ReceiveReconnecting) - .On(EventType.SubscriptionChanged, StateType.Receiving) - .On(EventType.ReceiveReconnectFailure, StateType.ReceiveReconnecting) - .On(EventType.SubscriptionRestored, StateType.Receiving) - .On(EventType.ReceiveReconnectSuccess, StateType.Receiving, new List() - { - //receiveReconnectEmitStatus, - receiveReconnectEmitMessages - } - ) - .On(EventType.Disconnect, StateType.ReceiveStopped) - .On(EventType.ReceiveReconnectGiveUp, StateType.ReceiveFailed, new List() - { - receiveReconnectGiveupEmitStatus - } - ) - .OnEntry(entryInvocationList: new List() - { - receiveReconnectInvocation - } - ) - .OnExit(exitInvocationList: new List() - { - cancelReceiveReconnect - } - ); - #endregion - - #region ReceiveStopped Effect Invocations and Emit Status - #endregion - #region StateType.ReceiveStopped - CreateState(StateType.ReceiveStopped) - .On(EventType.Reconnect, StateType.Receiving); - #endregion - - System.Diagnostics.Debug.WriteLine("EventEngine Setup done."); - } - - //public void SetCurrentStateType(StateType stateType, EventType eventType) - //{ - // State nextState = null; - // StateType nextStateType; - // IEnumerable eventTypeStates = States.Where(s => s.StateType == stateType && s.EventType == eventType); - // foreach (State state in eventTypeStates) - // { - // if (state.transitions.ContainsKey(eventType)) - // { - // nextStateType = state.transitions[eventType]; - // } - // } - //} - } -} diff --git a/src/Api/PubnubApi/EventEngine/HandshakeEffectHandler.cs b/src/Api/PubnubApi/EventEngine/HandshakeEffectHandler.cs deleted file mode 100644 index a93d2326e..000000000 --- a/src/Api/PubnubApi/EventEngine/HandshakeEffectHandler.cs +++ /dev/null @@ -1,185 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Newtonsoft.Json; - - -namespace PubnubApi.PubnubEventEngine -{ - public class HandshakeResponse - { - [JsonProperty("t")] - public Timetoken Timetoken { get; set; } - - [JsonProperty("m")] - public object[] Messages { get; set; } - } - public class HandshakeError - { - [JsonProperty("status")] - public int Status { get; set; } - - [JsonProperty("error")] - public string ErrorMessage { get; set; } - } - - public class Timetoken - { - [JsonProperty("t")] - public long? Timestamp { get; set; } - - [JsonProperty("r")] - public int? Region { get; set; } - - } - - public class HandshakeRequestEventArgs : EventArgs - { - public ExtendedState ExtendedState { get; set; } - public Action HandshakeResponseCallback { get; set; } - } - public class CancelHandshakeRequestEventArgs : EventArgs - { - } - - public class HandshakeEffectHandler : IEffectInvocationHandler - { - EventEmitter emitter; - private ExtendedState extendedState { get; set;} - public Action LogCallback { get; set; } - public Action AnnounceStatus { get; set; } - private PNStatus pnStatus { get; set; } - - public event EventHandler HandshakeRequested; - public event EventHandler CancelHandshakeRequested; - protected virtual void OnHandshakeRequested(HandshakeRequestEventArgs e) - { - EventHandler handler = HandshakeRequested; - if (handler != null) - { - handler(this, e); - } - } - protected virtual void OnCancelHandshakeRequested(CancelHandshakeRequestEventArgs e) - { - EventHandler handler = CancelHandshakeRequested; - if (handler != null) - { - handler(this, e); - } - } - - CancellationTokenSource cancellationTokenSource; - public HandshakeEffectHandler(EventEmitter emitter) - { - this.emitter = emitter; - cancellationTokenSource = new CancellationTokenSource(); - } - public async void Start(ExtendedState context, EventType eventType) - { - extendedState = context; - await Task.Factory.StartNew(() => { }); - if (cancellationTokenSource != null && cancellationTokenSource.Token.CanBeCanceled) { - Cancel(); - } - HandshakeRequestEventArgs args = new HandshakeRequestEventArgs(); - args.ExtendedState = context; - args.HandshakeResponseCallback = OnHandshakeEffectResponseReceived; - OnHandshakeRequested(args); - } - - public void OnHandshakeEffectResponseReceived(string json) - { - try - { - LogCallback?.Invoke($"OnHandshakeEffectResponseReceived Json Response = {json}"); - var handshakeResponse = JsonConvert.DeserializeObject(json); - if (handshakeResponse != null && handshakeResponse.Timetoken != null) - { - HandshakeSuccess handshakeSuccessEvent = new HandshakeSuccess(); - handshakeSuccessEvent.SubscriptionCursor = new SubscriptionCursor(); - handshakeSuccessEvent.SubscriptionCursor.Timetoken = handshakeResponse.Timetoken?.Timestamp; - handshakeSuccessEvent.SubscriptionCursor.Region = handshakeResponse.Timetoken?.Region; - - handshakeSuccessEvent.EventPayload.Timetoken = handshakeResponse.Timetoken?.Timestamp; - handshakeSuccessEvent.EventPayload.Region = handshakeResponse.Timetoken?.Region; - handshakeSuccessEvent.EventType = EventType.HandshakeSuccess; - handshakeSuccessEvent.Name = "HANDSHAKE_SUCCESS"; - LogCallback?.Invoke("OnHandshakeEffectResponseReceived - EventType.HandshakeSuccess"); - - pnStatus = new PNStatus(); - pnStatus.StatusCode = 200; - pnStatus.Operation = PNOperationType.PNSubscribeOperation; - pnStatus.AffectedChannels = extendedState.Channels; - pnStatus.AffectedChannelGroups = extendedState.ChannelGroups; - pnStatus.Category = PNStatusCategory.PNConnectedCategory; - pnStatus.Error = false; - - emitter.emit(handshakeSuccessEvent); - } - else - { - HandshakeFailure handshakeFailureEvent = new HandshakeFailure(); - handshakeFailureEvent.Name = "HANDSHAKE_FAILURE"; - handshakeFailureEvent.EventType = EventType.HandshakeFailure; - LogCallback?.Invoke("OnHandshakeEffectResponseReceived - EventType.HandshakeFailure"); - - pnStatus = new PNStatus(); - pnStatus.Operation = PNOperationType.PNSubscribeOperation; - pnStatus.AffectedChannels = extendedState.Channels; - pnStatus.AffectedChannelGroups = extendedState.ChannelGroups; - pnStatus.Category = PNStatusCategory.PNNetworkIssuesCategory; - pnStatus.Error = true; - - emitter.emit(handshakeFailureEvent); - } - } - catch (Exception ex) - { - LogCallback?.Invoke($"OnHandshakeEffectResponseReceived EXCEPTION - {ex}"); - HandshakeFailure handshakeFailureEvent = new HandshakeFailure(); - handshakeFailureEvent.Name = "HANDSHAKE_FAILURE"; - handshakeFailureEvent.EventType = EventType.HandshakeFailure; - handshakeFailureEvent.EventPayload.exception = ex; - - pnStatus = new PNStatus(); - pnStatus.Operation = PNOperationType.PNSubscribeOperation; - pnStatus.AffectedChannels = extendedState.Channels; - pnStatus.AffectedChannelGroups = extendedState.ChannelGroups; - pnStatus.Category = PNStatusCategory.PNNetworkIssuesCategory; - pnStatus.Error = true; - - emitter.emit(handshakeFailureEvent); - } - - //emitter.emit(json, true, 0); - } - public void Cancel() - { - if (cancellationTokenSource != null) - { - LogCallback?.Invoke($"HandshakeEffectHandler - cancellationTokenSource - cancellion attempted."); - cancellationTokenSource.Cancel(); - } - - LogCallback?.Invoke($"HandshakeEffectHandler - invoking OnCancelHandshakeRequested."); - CancelHandshakeRequestEventArgs args = new CancelHandshakeRequestEventArgs(); - OnCancelHandshakeRequested(args); - } - public void Run(ExtendedState context) - { - if (AnnounceStatus != null) - { - AnnounceStatus(pnStatus); - } - } - - public PNStatus GetPNStatus() - { - return pnStatus; - } - - } - - -} diff --git a/src/Api/PubnubApi/EventEngine/HandshakeFailedEffectHandler.cs b/src/Api/PubnubApi/EventEngine/HandshakeFailedEffectHandler.cs deleted file mode 100644 index 52100ca4a..000000000 --- a/src/Api/PubnubApi/EventEngine/HandshakeFailedEffectHandler.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Threading; - -namespace PubnubApi.PubnubEventEngine -{ - public class HandshakeFailedEffectHandler : IEffectInvocationHandler - { - EventEmitter emitter; - //public EffectInvocationType InvocationType { get; set; } - private ExtendedState extendedState { get; set;} - private PNStatus pnStatus { get; set; } - public Action LogCallback { get; set; } - public Action AnnounceStatus { get; set; } - - CancellationTokenSource? cancellationTokenSource; - - public HandshakeFailedEffectHandler(EventEmitter emitter) - { - this.emitter = emitter; - cancellationTokenSource = new CancellationTokenSource(); - } - - public async void Start(ExtendedState context, EventType eventType) - { - extendedState = context; - await Task.Factory.StartNew(() => { }); - if (cancellationTokenSource != null && cancellationTokenSource.Token.CanBeCanceled) { - Cancel(); - } - - if (eventType != EventType.HandshakeReconnectGiveUp) - { - LogCallback?.Invoke("HandshakeFailedEffectHandler - EventType.Handshake"); - Reconnect reconnectEvent = new Reconnect(); - reconnectEvent.Name = "RECONNECT"; - reconnectEvent.EventType = EventType.Reconnect; - - emitter.emit(reconnectEvent); - } - - } - - public void Cancel() - { - if (cancellationTokenSource != null) - { - LogCallback?.Invoke($"HandshakeFailedEffectHandler - cancellationTokenSource - cancellion attempted."); - cancellationTokenSource.Cancel(); - } - } - public void Run(ExtendedState context) - { - if (AnnounceStatus != null) - { - AnnounceStatus(pnStatus); - } - } - - public PNStatus GetPNStatus() - { - return pnStatus; - } - } -} diff --git a/src/Api/PubnubApi/EventEngine/HandshakeReconnectEffectHandler.cs b/src/Api/PubnubApi/EventEngine/HandshakeReconnectEffectHandler.cs deleted file mode 100644 index e8fa53f5c..000000000 --- a/src/Api/PubnubApi/EventEngine/HandshakeReconnectEffectHandler.cs +++ /dev/null @@ -1,274 +0,0 @@ -using Newtonsoft.Json; -using PubnubApi.PubnubEventEngine; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - - -namespace PubnubApi.PubnubEventEngine -{ - public class HandshakeReconnectRequestEventArgs : EventArgs - { - public ExtendedState ExtendedState { get; set; } - public Action HandshakeReconnectResponseCallback { get; set; } - } - public class CancelHandshakeReconnectRequestEventArgs : EventArgs - { - } - public class HandshakeReconnectEffectHandler : IEffectInvocationHandler - { - EventEmitter emitter; - private ExtendedState extendedState { get; set;} - public Action LogCallback { get; set; } - public Action AnnounceStatus { get; set; } - public PNReconnectionPolicy ReconnectionPolicy { get; set; } - public int MaxRetries { get; set; } - private PNStatus pnStatus { get; set; } - private int timerInterval; - const int MINEXPONENTIALBACKOFF = 1; - const int MAXEXPONENTIALBACKOFF = 25; - const int INTERVAL = 3; - - public event EventHandler HandshakeReconnectRequested; - public event EventHandler CancelHandshakeReconnectRequested; - System.Threading.Timer timer; - protected virtual void OnHandshakeReconnectRequested(HandshakeReconnectRequestEventArgs e) - { - EventHandler handler = HandshakeReconnectRequested; - if (handler != null) - { - handler(this, e); - } - } - protected virtual void OnCancelHandshakeReconnectRequested(CancelHandshakeReconnectRequestEventArgs e) - { - EventHandler handler = CancelHandshakeReconnectRequested; - if (handler != null) - { - handler(this, e); - } - } - - CancellationTokenSource cancellationTokenSource; - public HandshakeReconnectEffectHandler(EventEmitter emitter) - { - this.emitter = emitter; - cancellationTokenSource = new CancellationTokenSource(); - } - - public async void Start(ExtendedState context, EventType eventType) - { - extendedState = context; - await Task.Factory.StartNew(() => { }); - if (cancellationTokenSource != null && cancellationTokenSource.Token.CanBeCanceled) { - Cancel(); - } - - if (ReconnectionPolicy == PNReconnectionPolicy.EXPONENTIAL) - { - double numberForMath = extendedState.Attempts % 6; - timerInterval = (int)(Math.Pow(2, numberForMath) - 1); - if (timerInterval > MAXEXPONENTIALBACKOFF) - { - timerInterval = MINEXPONENTIALBACKOFF; - } - else if (timerInterval < 1) - { - timerInterval = MINEXPONENTIALBACKOFF; - } - } - else if (ReconnectionPolicy == PNReconnectionPolicy.LINEAR) - { - timerInterval = INTERVAL; - } - else - { - timerInterval = -1; - } - LogCallback?.Invoke($"HandshakeReconnectEffectHandler ReconnectionPolicy = {ReconnectionPolicy}; Interval = {timerInterval}"); - - if (timer != null) - { - timer.Change(Timeout.Infinite, Timeout.Infinite); - } - if (timerInterval != -1) - { - timer = new Timer(new TimerCallback(HandshakeReconnectTimerCallback), null, - (-1 == timerInterval) ? Timeout.Infinite : timerInterval * 1000, Timeout.Infinite); - } - else - { - PrepareFailurePNStatus(new HandshakeError() { Status = 400 }); - PrepareAndEmitHandshakeReconnectGiveupEvent(null); - } - } - - private void HandshakeReconnectTimerCallback(object state) - { - LogCallback?.Invoke("HandshakeReconnectEffectHandler Timer interval invoke"); - HandshakeReconnectRequestEventArgs args = new HandshakeReconnectRequestEventArgs(); - args.ExtendedState = extendedState; - args.HandshakeReconnectResponseCallback = OnHandshakeReconnectEffectResponseReceived; - OnHandshakeReconnectRequested(args); - } - - public void OnHandshakeReconnectEffectResponseReceived(string json) - { - try - { - LogCallback?.Invoke($"OnHandshakeReconnectEffectResponseReceived Json Response = {json}"); - var handshakeResponse = JsonConvert.DeserializeObject(json); - if (handshakeResponse != null && handshakeResponse.Timetoken != null) - { - HandshakeReconnectSuccess handshakeReconnectSuccessEvent = new HandshakeReconnectSuccess(); - handshakeReconnectSuccessEvent.SubscriptionCursor = new SubscriptionCursor(); - handshakeReconnectSuccessEvent.SubscriptionCursor.Timetoken = handshakeResponse.Timetoken?.Timestamp; - handshakeReconnectSuccessEvent.SubscriptionCursor.Region = handshakeResponse.Timetoken?.Region; - - handshakeReconnectSuccessEvent.EventPayload.Timetoken = handshakeResponse.Timetoken?.Timestamp; - handshakeReconnectSuccessEvent.EventPayload.Region = handshakeResponse.Timetoken?.Region; - handshakeReconnectSuccessEvent.EventType = EventType.HandshakeReconnectSuccess; - handshakeReconnectSuccessEvent.Name = "HANDSHAKE_RECONNECT_SUCCESS"; - LogCallback?.Invoke("OnHandshakeReconnectEffectResponseReceived - EventType.HandshakeReconnectSuccess"); - - pnStatus = new PNStatus(); - pnStatus.StatusCode = 200; - pnStatus.Operation = PNOperationType.PNSubscribeOperation; - pnStatus.AffectedChannels = extendedState.Channels; - pnStatus.AffectedChannelGroups = extendedState.ChannelGroups; - pnStatus.Category = PNStatusCategory.PNConnectedCategory; - pnStatus.Error = false; - - extendedState.Attempts = 0; - - emitter.emit(handshakeReconnectSuccessEvent); - } - else - { - var handshakeError = JsonConvert.DeserializeObject(json); - extendedState.Attempts++; - PrepareFailurePNStatus(handshakeError); - - if (MaxRetries != -1 && extendedState.Attempts > MaxRetries) - { - LogCallback?.Invoke($"Attempt: {extendedState.Attempts}; OnHandshakeReconnectEffectResponseReceived - EventType.HandshakeReconnectGiveUp"); - PrepareAndEmitHandshakeReconnectGiveupEvent(null); - } - else - { - LogCallback?.Invoke($"Attempt: {extendedState.Attempts}; OnHandshakeReconnectEffectResponseReceived - EventType.HandshakeReconnectFailure"); - PrepareAndEmitHandshakeReconnectFailureEvent(null); - } - } - } - catch (Exception ex) - { - extendedState.Attempts++; - PrepareFailurePNStatus(new HandshakeError() { Status = 400 }); - - if (MaxRetries != -1 && extendedState.Attempts > MaxRetries) - { - LogCallback?.Invoke($"Attempt: {extendedState.Attempts}; OnHandshakeReconnectEffectResponseReceived - EventType.HandshakeReconnectGiveUp"); - PrepareAndEmitHandshakeReconnectGiveupEvent(null); - - } - else - { - LogCallback?.Invoke($"Attempt: {extendedState.Attempts}; OnHandshakeReconnectEffectResponseReceived - EventType.HandshakeReconnectFailure"); - PrepareAndEmitHandshakeReconnectFailureEvent(ex); - } - } - finally - { - if (timer != null) - { - try - { - timer.Change(Timeout.Infinite, Timeout.Infinite); - } - catch { } - } - } - } - - private void PrepareFailurePNStatus(HandshakeError error) - { - pnStatus = new PNStatus(); - pnStatus.StatusCode = (error.Status != 0) ? error.Status : 504; - pnStatus.Operation = PNOperationType.PNSubscribeOperation; - pnStatus.AffectedChannels = extendedState.Channels; - pnStatus.AffectedChannelGroups = extendedState.ChannelGroups; - pnStatus.Category = PNStatusCategory.PNNetworkIssuesCategory; - pnStatus.Error = true; - } - - private void PrepareAndEmitHandshakeReconnectFailureEvent(Exception ex) - { - HandshakeReconnectFailure handshakeReconnectFailureEvent = new HandshakeReconnectFailure(); - handshakeReconnectFailureEvent.Name = "HANDSHAKE_RECONNECT_FAILURE"; - handshakeReconnectFailureEvent.EventType = EventType.HandshakeReconnectFailure; - handshakeReconnectFailureEvent.Attempts = extendedState.Attempts; - if (ex != null) - { - handshakeReconnectFailureEvent.EventPayload.exception = ex; - } - - emitter.emit(handshakeReconnectFailureEvent); - } - - private void PrepareAndEmitHandshakeReconnectGiveupEvent(Exception ex) - { - HandshakeReconnectGiveUp handshakeReconnectGiveupEvent = new HandshakeReconnectGiveUp(); - handshakeReconnectGiveupEvent.Name = "HANDSHAKE_RECONNECT_GIVEUP"; - handshakeReconnectGiveupEvent.EventType = EventType.HandshakeReconnectGiveUp; - handshakeReconnectGiveupEvent.Attempts = extendedState.Attempts; - if (ex != null) - { - handshakeReconnectGiveupEvent.EventPayload.exception = ex; - } - - emitter.emit(handshakeReconnectGiveupEvent); - } - - //private void PrepareAndEmitHandshakeFailedEvent(Exception ex) - //{ - // HandshakeFailure handshakeFailureEvent = new HandshakeFailure(); - // handshakeFailureEvent.Name = "HANDSHAKE_FAILURE"; - // handshakeFailureEvent.EventType = EventType.HandshakeReconnectGiveUp; - // handshakeFailureEvent.Attempts = extendedState.Attempts; - // if (ex != null) - // { - // handshakeFailureEvent.EventPayload.exception = ex; - // } - - // emitter.emit(handshakeFailureEvent); - //} - public void Cancel() - { - if (cancellationTokenSource != null) - { - LogCallback?.Invoke($"HandshakeReconnectEffectHandler - cancellationTokenSource - cancellion attempted."); - cancellationTokenSource.Cancel(); - } - LogCallback?.Invoke($"HandshakeReconnectEffectHandler - invoking OnCancelHandshakeReconnectRequested."); - CancelHandshakeReconnectRequestEventArgs args = new CancelHandshakeReconnectRequestEventArgs(); - OnCancelHandshakeReconnectRequested(args); - } - public void Run(ExtendedState context) - { - if (AnnounceStatus != null) - { - AnnounceStatus(pnStatus); - } - } - - public PNStatus GetPNStatus() - { - return pnStatus; - } - } -} diff --git a/src/Api/PubnubApi/EventEngine/IEffectInvocationHandler.cs b/src/Api/PubnubApi/EventEngine/IEffectInvocationHandler.cs deleted file mode 100644 index 4350f3a22..000000000 --- a/src/Api/PubnubApi/EventEngine/IEffectInvocationHandler.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; - -namespace PubnubApi.PubnubEventEngine -{ - - public enum EffectInvocationType - { - Handshake, - HandshakeSuccess, - CancelHandshake, - ReceiveMessages, - ReceiveSuccess, - Disconnect, - HandshakeReconnect, - HandshakeReconnectSuccess, - CancelHandshakeReconnect, - CancelReceiveMessages, - ReceiveReconnect, - ReceiveReconnectSuccess, - ReceiveReconnectGiveUp, - CancelReceiveReconnect, - ReconnectionAttempt - } - - public interface IEffectInvocationHandler - { - void Start(ExtendedState context, EventType eventType); - void Cancel(); - void Run(ExtendedState context); - PNStatus GetPNStatus(); - } - - public interface IReceiveMessageHandler - { - Message[] GetMessages(); - } -} diff --git a/src/Api/PubnubApi/EventEngine/ReceiveReconnectingEffectHandler.cs b/src/Api/PubnubApi/EventEngine/ReceiveReconnectingEffectHandler.cs deleted file mode 100644 index 6e8872253..000000000 --- a/src/Api/PubnubApi/EventEngine/ReceiveReconnectingEffectHandler.cs +++ /dev/null @@ -1,273 +0,0 @@ -using Newtonsoft.Json; -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace PubnubApi.PubnubEventEngine -{ - public class ReceiveReconnectRequestEventArgs : EventArgs - { - public ExtendedState ExtendedState { get; set; } - public Action ReceiveReconnectResponseCallback { get; set; } - } - public class CancelReceiveReconnectRequestEventArgs : EventArgs - { - } - public class ReceiveReconnectingEffectHandler : IEffectInvocationHandler - { - EventEmitter eventEmitter; - private ExtendedState extendedState { get; set;} - public Action LogCallback { get; set; } - public Action AnnounceStatus { get; set; } - public PNReconnectionPolicy ReconnectionPolicy { get; set; } - public int MaxRetries { get; set; } - private Message[] receiveMessages { get; set; } - private PNStatus pnStatus { get; set; } - private int timerInterval; - const int MINEXPONENTIALBACKOFF = 1; - const int MAXEXPONENTIALBACKOFF = 25; - const int INTERVAL = 3; - - public event EventHandler ReceiveReconnectRequested; - public event EventHandler CancelReceiveReconnectRequested; - System.Threading.Timer timer; - protected virtual void OnReceiveReconnectRequested(ReceiveReconnectRequestEventArgs e) - { - EventHandler handler = ReceiveReconnectRequested; - if (handler != null) - { - handler(this, e); - } - } - protected virtual void OnCancelReceiveReconnectRequested(CancelReceiveReconnectRequestEventArgs e) - { - EventHandler handler = CancelReceiveReconnectRequested; - if (handler != null) - { - handler(this, e); - } - } - - CancellationTokenSource cancellationTokenSource; - public ReceiveReconnectingEffectHandler(EventEmitter emitter) - { - this.eventEmitter = emitter; - cancellationTokenSource = new CancellationTokenSource(); - } - - public async void Start(ExtendedState context, EventType eventType) - { - extendedState = context; - await Task.Factory.StartNew(() => { }); - if (cancellationTokenSource != null && cancellationTokenSource.Token.CanBeCanceled) { - Cancel(); - } - - if (ReconnectionPolicy == PNReconnectionPolicy.EXPONENTIAL) - { - double numberForMath = extendedState.Attempts % 6; - timerInterval = (int)(Math.Pow(2, numberForMath) - 1); - if (timerInterval > MAXEXPONENTIALBACKOFF) - { - timerInterval = MINEXPONENTIALBACKOFF; - } - else if (timerInterval < 1) - { - timerInterval = MINEXPONENTIALBACKOFF; - } - } - else if (ReconnectionPolicy == PNReconnectionPolicy.LINEAR) - { - timerInterval = INTERVAL; - } - else - { - timerInterval = -1; - } - LogCallback?.Invoke($"ReceiveReconnectingEffectHandler ReconnectionPolicy = {ReconnectionPolicy}; Interval = {timerInterval}"); - - if (timer != null) - { - timer.Change(Timeout.Infinite, Timeout.Infinite); - } - if (timerInterval != -1) - { - timer = new Timer(new TimerCallback(ReceiveReconnectTimerCallback), null, - (-1 == timerInterval) ? Timeout.Infinite : timerInterval * 1000, Timeout.Infinite); - } - else - { - PrepareFailurePNStatus(new ReceiveError() { Status = 400 }); - PrepareAndEmitReceiveReconnectGiveupEvent(null); - } - } - - private void ReceiveReconnectTimerCallback(object state) - { - LogCallback?.Invoke("ReceiveReconnectingEffectHandler Timer interval invoke"); - ReceiveReconnectRequestEventArgs args = new ReceiveReconnectRequestEventArgs(); - args.ExtendedState = extendedState; - args.ReceiveReconnectResponseCallback = OnReceiveReconnectEffectResponseReceived; - OnReceiveReconnectRequested(args); - } - - public void OnReceiveReconnectEffectResponseReceived(string json) - { - try - { - pnStatus = null; - LogCallback?.Invoke($"OnReceiveReconnectEffectResponseReceived Json Response = {json}"); - var receivedResponse = JsonConvert.DeserializeObject>(json); - if (receivedResponse != null && receivedResponse.Timetoken != null) - { - receiveMessages = receivedResponse.Messages; - - ReceiveReconnectSuccess receiveReconnectSuccessEvent = new ReceiveReconnectSuccess(); - receiveReconnectSuccessEvent.SubscriptionCursor = new SubscriptionCursor(); - receiveReconnectSuccessEvent.SubscriptionCursor.Timetoken = receivedResponse.Timetoken.Timestamp; - receiveReconnectSuccessEvent.SubscriptionCursor.Region = receivedResponse.Timetoken.Region; - receiveReconnectSuccessEvent.EventPayload.Timetoken = receivedResponse.Timetoken.Timestamp; - receiveReconnectSuccessEvent.EventPayload.Region = receivedResponse.Timetoken.Region; - receiveReconnectSuccessEvent.EventType = EventType.ReceiveReconnectSuccess; - receiveReconnectSuccessEvent.Name = "RECEIVE_RECONNECT_SUCCESS"; - LogCallback?.Invoke("OnReceiveReconnectEffectResponseReceived - EventType.ReceiveReconnectSuccess"); - - pnStatus = new PNStatus(); - pnStatus.StatusCode = 200; - pnStatus.Operation = PNOperationType.PNSubscribeOperation; - pnStatus.AffectedChannels = extendedState.Channels; - pnStatus.AffectedChannelGroups = extendedState.ChannelGroups; - pnStatus.Category = PNStatusCategory.PNConnectedCategory; - pnStatus.Error = false; - - extendedState.Attempts = 0; - - eventEmitter.emit(receiveReconnectSuccessEvent); - } - else - { - ReceiveReconnectFailure receiveReconnectFailureEvent = new ReceiveReconnectFailure(); - receiveReconnectFailureEvent.Name = "RECEIVE_RECONNECT_FAILURE"; - receiveReconnectFailureEvent.EventType = EventType.ReceiveReconnectFailure; - LogCallback?.Invoke("OnReceivingReconnectEffectResponseReceived - EventType.ReceiveReconnectFailure"); - - pnStatus = new PNStatus(); - pnStatus.Operation = PNOperationType.PNSubscribeOperation; - pnStatus.AffectedChannels = extendedState.Channels; - pnStatus.AffectedChannelGroups = extendedState.ChannelGroups; - pnStatus.Error = true; - - - var receiveReconnectError = JsonConvert.DeserializeObject(json); - extendedState.Attempts++; - PrepareFailurePNStatus(receiveReconnectError); - - if (MaxRetries != -1 && extendedState.Attempts > MaxRetries) - { - LogCallback?.Invoke($"Attempt: {extendedState.Attempts}; OnReceivingReconnectEffectResponseReceived - EventType.ReceiveReconnectGiveUp"); - PrepareAndEmitReceiveReconnectGiveupEvent(null); - } - else - { - LogCallback?.Invoke($"Attempt: {extendedState.Attempts}; OnReceivingReconnectEffectResponseReceived - EventType.ReceiveReconnectFailure"); - PrepareAndEmitReceiveReconnectFailureEvent(null); - } - } - } - catch (Exception ex) - { - extendedState.Attempts++; - PrepareFailurePNStatus(new ReceiveError() { Status = 400 }); - - if (MaxRetries != -1 && extendedState.Attempts > MaxRetries) - { - LogCallback?.Invoke($"Attempt: {extendedState.Attempts}; OnHandshakeReconnectEffectResponseReceived - EventType.ReceiveReconnectGiveUp"); - PrepareAndEmitReceiveReconnectGiveupEvent(null); - - } - else - { - LogCallback?.Invoke($"Attempt: {extendedState.Attempts}; OnHandshakeReconnectEffectResponseReceived - EventType.ReceiveReconnectFailure"); - PrepareAndEmitReceiveReconnectFailureEvent(ex); - } - } - finally - { - if (timer != null) - { - try - { - timer.Change(Timeout.Infinite, Timeout.Infinite); - } - catch { } - } - } - } - - private void PrepareFailurePNStatus(ReceiveError error) - { - pnStatus = new PNStatus(); - pnStatus.StatusCode = (error != null && error.Status != 0) ? error.Status : 504; - pnStatus.Operation = PNOperationType.PNSubscribeOperation; - pnStatus.AffectedChannels = extendedState.Channels; - pnStatus.AffectedChannelGroups = extendedState.ChannelGroups; - pnStatus.Category = PNStatusCategory.PNNetworkIssuesCategory; - pnStatus.Error = true; - } - - private void PrepareAndEmitReceiveReconnectFailureEvent(Exception ex) - { - ReceiveReconnectFailure receiveReconnectFailureEvent = new ReceiveReconnectFailure(); - receiveReconnectFailureEvent.Name = "RECEIVE_RECONNECT_FAILURE"; - receiveReconnectFailureEvent.EventType = EventType.ReceiveReconnectFailure; - receiveReconnectFailureEvent.Attempts = extendedState.Attempts; - if (ex != null) - { - receiveReconnectFailureEvent.EventPayload.exception = ex; - } - - eventEmitter.emit(receiveReconnectFailureEvent); - } - - private void PrepareAndEmitReceiveReconnectGiveupEvent(Exception ex) - { - ReceiveReconnectGiveUp receiveReconnectGiveupEvent = new ReceiveReconnectGiveUp(); - receiveReconnectGiveupEvent.Name = "RECEIVE_RECONNECT_GIVEUP"; - receiveReconnectGiveupEvent.EventType = EventType.ReceiveReconnectGiveUp; - receiveReconnectGiveupEvent.Attempts = extendedState.Attempts; - if (ex != null) - { - receiveReconnectGiveupEvent.EventPayload.exception = ex; - } - - eventEmitter.emit(receiveReconnectGiveupEvent); - } - - public void Cancel() - { - if (cancellationTokenSource != null) - { - LogCallback?.Invoke($"ReceiveReconnectEffectHandler - cancellationTokenSource - cancellion attempted."); - cancellationTokenSource.Cancel(); - } - if (timer != null) - { - timer.Change(Timeout.Infinite, Timeout.Infinite); - } - LogCallback?.Invoke($"ReceiveReconnectEffectHandler - invoking OnCancelReceiveReconnectRequested."); - CancelReceiveReconnectRequestEventArgs args = new CancelReceiveReconnectRequestEventArgs(); - OnCancelReceiveReconnectRequested(args); - } - public void Run(ExtendedState context) - { - if (AnnounceStatus != null && pnStatus != null) - { - AnnounceStatus(pnStatus); - } - } - public PNStatus GetPNStatus() - { - return pnStatus; - } - } -} diff --git a/src/Api/PubnubApi/EventEngine/ReceivingEffectHandler.cs b/src/Api/PubnubApi/EventEngine/ReceivingEffectHandler.cs deleted file mode 100644 index 1c719582c..000000000 --- a/src/Api/PubnubApi/EventEngine/ReceivingEffectHandler.cs +++ /dev/null @@ -1,294 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Newtonsoft.Json; - -namespace PubnubApi.PubnubEventEngine -{ - public class ReceiveingResponse - { - [JsonProperty("t")] - public Timetoken Timetoken { get; set; } - - [JsonProperty("m")] - public Message[] Messages { get; set; } - } - - public class Message - { - [JsonProperty ("a")] - public string Shard { get; set;} - - [JsonProperty ("b")] - public string SubscriptionMatch { get; set;} - - [JsonProperty("c")] - public string Channel { get; set; } - - [JsonProperty("d")] - public T Payload { get; set; } - - [JsonProperty("e")] - public int MessageType { get; set; } - - [JsonProperty("f")] - public string Flags { get; set; } - - //[JsonProperty("i")] - //public string IssuingClientId { get; set; } - - [JsonProperty("k")] - public string SubscribeKey { get; set; } - - [JsonProperty("o")] - public object OriginatingTimetoken { get; set; } - - [JsonProperty("p")] - public object PublishMetadata { get; set; } - - [JsonProperty("s")] - public long SequenceNumber { get; set; } - } - - public class PresenceEvent - { - [JsonProperty("action")] - public string Action { get; set; } - - [JsonProperty("uuid")] - public string Uuid { get; set; } - - [JsonProperty("timestamp")] - public long Timestamp { get; set; } - - [JsonProperty("occupancy")] - public int Occupancy { get; set; } - - } - - public class ReceiveError - { - [JsonProperty("status")] - public int Status { get; set; } - - [JsonProperty("error")] - public string ErrorMessage { get; set; } - } - - public class ReceiveRequestEventArgs : EventArgs - { - public ExtendedState ExtendedState { get; set; } - public Action ReceiveResponseCallback { get; set; } - } - - public class CancelReceiveRequestEventArgs : EventArgs - { - - } - - public class ReceivingEffectHandler : IEffectInvocationHandler, IReceiveMessageHandler - { - EventEmitter emitter; - private ExtendedState extendedState { get; set;} - private PNStatus pnStatus { get; set; } - private Message[] receiveMessages { get; set; } - public Action LogCallback { get; set; } - public Action AnnounceStatus { get; set; } - public Action> AnnounceMessage { get; set; } - public Action AnnouncePresenceEvent { get; set; } - public PNReconnectionPolicy ReconnectionPolicy { get; set; } - - public event EventHandler ReceiveRequested; - public event EventHandler CancelReceiveRequested; - protected virtual void OnReceiveRequested(ReceiveRequestEventArgs e) - { - EventHandler handler = ReceiveRequested; - if (handler != null) - { - handler(this, e); - } - } - - protected virtual void OnCancelReceiveRequested(CancelReceiveRequestEventArgs e) - { - EventHandler handler = CancelReceiveRequested; - if (handler != null) - { - handler(this, e); - } - } - - CancellationTokenSource cancellationTokenSource; - - public ReceivingEffectHandler(EventEmitter emitter) - { - this.emitter = emitter; - cancellationTokenSource = new CancellationTokenSource(); - } - - public async void Start(ExtendedState context, EventType eventType) - { - extendedState = context; - await Task.Factory.StartNew(() => { }); - if (cancellationTokenSource != null && cancellationTokenSource.Token.CanBeCanceled) { - Cancel(); - } - cancellationTokenSource = new CancellationTokenSource(); - - await Task.Factory.StartNew(() => { }); - ReceiveRequestEventArgs args = new ReceiveRequestEventArgs(); - args.ExtendedState = context; - args.ReceiveResponseCallback = OnReceivingEffectResponseReceived; - OnReceiveRequested(args); - } - - public void OnReceivingEffectResponseReceived(string json) - { - try - { - pnStatus = null; - var receivedResponse = JsonConvert.DeserializeObject>(json); - if (receivedResponse != null && receivedResponse.Timetoken != null) - { - receiveMessages = receivedResponse.Messages; - - ReceiveSuccess receiveSuccessEvent = new ReceiveSuccess(); - receiveSuccessEvent.SubscriptionCursor = new SubscriptionCursor(); - receiveSuccessEvent.SubscriptionCursor.Timetoken = receivedResponse.Timetoken.Timestamp; - receiveSuccessEvent.SubscriptionCursor.Region = receivedResponse.Timetoken.Region; - receiveSuccessEvent.EventPayload.Timetoken = receivedResponse.Timetoken.Timestamp; - receiveSuccessEvent.EventPayload.Region = receivedResponse.Timetoken.Region; - receiveSuccessEvent.EventType = EventType.ReceiveSuccess; - receiveSuccessEvent.Name = "RECEIVE_SUCCESS"; - LogCallback?.Invoke("OnReceivingEffectResponseReceived - EventType.ReceiveSuccess"); - - emitter.emit(receiveSuccessEvent); - } - else - { - ReceiveFailure receiveFailureEvent = new ReceiveFailure(); - receiveFailureEvent.Name = "RECEIVE_FAILURE"; - receiveFailureEvent.EventType = EventType.ReceiveFailure; - LogCallback?.Invoke("OnReceivingEffectResponseReceived - EventType.ReceiveFailure"); - - pnStatus = new PNStatus(); - pnStatus.Operation = PNOperationType.PNSubscribeOperation; - pnStatus.AffectedChannels = extendedState.Channels; - pnStatus.AffectedChannelGroups = extendedState.ChannelGroups; - pnStatus.Error = true; - - emitter.emit(receiveFailureEvent); - } - } - catch (Exception ex) - { - LogCallback?.Invoke($"ReceivingEffectHandler EXCEPTION - {ex}"); - - ReceiveFailure receiveFailureEvent = new ReceiveFailure(); - receiveFailureEvent.Name = "RECEIVE_FAILURE"; - receiveFailureEvent.EventType = EventType.ReceiveFailure; - receiveFailureEvent.EventPayload.exception = ex; - LogCallback?.Invoke("OnReceivingEffectResponseReceived - EventType.ReceiveFailure"); - - pnStatus = new PNStatus(); - pnStatus.Operation = PNOperationType.PNSubscribeOperation; - pnStatus.AffectedChannels = extendedState.Channels; - pnStatus.AffectedChannelGroups = extendedState.ChannelGroups; - pnStatus.Error = true; - - emitter.emit(receiveFailureEvent); - } - } - - public void Cancel() - { - if (cancellationTokenSource != null) - { - LogCallback?.Invoke($"ReceivingEffectHandler - Receiving request cancellion attempted."); - cancellationTokenSource.Cancel(); - } - LogCallback?.Invoke($"ReceivingEffectHandler - invoking OnCancelReceiveRequested."); - CancelReceiveRequestEventArgs args = new CancelReceiveRequestEventArgs(); - OnCancelReceiveRequested(args); - } - public void Run(ExtendedState context) - { - if (AnnounceStatus != null && pnStatus != null) - { - AnnounceStatus(pnStatus); - } - Message[] receiveMessages = GetMessages(); - int messageCount = (receiveMessages != null) ? receiveMessages.Length : 0; - if (messageCount > 0) - { - for (int index = 0; index < receiveMessages.Length; index++) - { - LogCallback?.Invoke($"Received Message ({index + 1} of {receiveMessages.Length}) : {JsonConvert.SerializeObject(receiveMessages[index])}"); - if (receiveMessages[index].Channel.IndexOf("-pnpres") > 0) - { - if (AnnouncePresenceEvent != null) - { - var presenceEvent = JsonConvert.DeserializeObject(receiveMessages[index].Payload.ToString()); - PNPresenceEventResult presenceEventResult = new PNPresenceEventResult(); - presenceEventResult.Channel = receiveMessages[index].Channel; - presenceEventResult.Event = presenceEvent.Action; - presenceEventResult.Occupancy = presenceEvent.Occupancy; - presenceEventResult.Uuid = presenceEvent.Uuid; - presenceEventResult.Timestamp = presenceEvent.Timestamp; - presenceEventResult.UserMetadata = receiveMessages[index].PublishMetadata; - - AnnouncePresenceEvent?.Invoke(presenceEventResult); - } - } - else - { - if (receiveMessages[index].MessageType == 1) - { - //TODO: Callback for Signal message - PNSignalResult signalMessage = new PNSignalResult - { - Channel = receiveMessages[index].Channel, - Message = receiveMessages[index].Payload, - }; - AnnounceMessage?.Invoke(signalMessage); - } - else if (receiveMessages[index].MessageType == 2) - { - //TODO: Callback for Object message - } - else if (receiveMessages[index].MessageType == 3) - { - //TODO: Callback for Message Action message - } - else if (receiveMessages[index].MessageType == 4) - { - //TODO: Callback for File message - } - else - { - //Callback for regular message - if (AnnounceMessage != null) - { - LogCallback?.Invoke($"Message : {JsonConvert.SerializeObject(receiveMessages[index].Payload)}"); - PNMessageResult messageResult = new PNMessageResult(); - messageResult.Channel = receiveMessages[index].Channel; - messageResult.Message = receiveMessages[index].Payload; - AnnounceMessage?.Invoke(messageResult); - } - } - } - } - } - } - - public PNStatus GetPNStatus() - { - return pnStatus; - } - - public Message[] GetMessages() - { - return receiveMessages; - } - } -} diff --git a/src/Api/PubnubApi/EventEngine/State.cs b/src/Api/PubnubApi/EventEngine/State.cs deleted file mode 100644 index 9bbbe1e26..000000000 --- a/src/Api/PubnubApi/EventEngine/State.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace PubnubApi.PubnubEventEngine -{ - - public enum StateType { Unsubscribed, Handshaking, HandshakingFailed, Receiving, ReceiveReconnecting, ReceiveStopped, ReceiveFailed, HandshakeFailed, HandshakeReconnecting, HandshakeStopped }; - - public class State - { - public EventType EventType { get; set; } - public StateType StateType { get; set; } - - public Dictionary transitions; - public Dictionary> EffectInvocationsList { get; private set; } - public List EntryList { get; private set; } - - public List ExitList { get; private set; } - - public State(StateType type) - { - this.StateType = type; - this.transitions = new Dictionary(); - //EffectInvocationsList = new List(); - EffectInvocationsList = new Dictionary>(); - } - - public State On(EventType e, StateType nextState) - { - transitions.Add(e, nextState); - return this; - } - public State On(EventType e, StateType nextState, List effectInvocation) - { - transitions.Add(e, nextState); - EffectInvocationsList.Add(e, effectInvocation); - return this; - } - - public State OnEntry(List entryInvocationList) - { - this.EntryList = entryInvocationList; - return this; - } - - public State OnExit(List exitInvocationList) - { - this.ExitList = exitInvocationList; - return this; - } - - //public State EffectInvocation(EffectInvocationType trigger, IEffectInvocationHandler effectInvocationHandler) - //{ - // this.EffectInvocationsList.Add(new EffectInvocation() { Effectype=trigger, Handler = effectInvocationHandler}); - // return this; - //} - } -} diff --git a/src/Api/PubnubApi/Interface/IPubnubUnitTest.cs b/src/Api/PubnubApi/Interface/IPubnubUnitTest.cs index fd5de104e..ce0e7601c 100644 --- a/src/Api/PubnubApi/Interface/IPubnubUnitTest.cs +++ b/src/Api/PubnubApi/Interface/IPubnubUnitTest.cs @@ -1,5 +1,4 @@ -using PubnubApi.PubnubEventEngine; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Net; diff --git a/src/Api/PubnubApiPCL/PubnubApiPCL.csproj b/src/Api/PubnubApiPCL/PubnubApiPCL.csproj index 55134d8f3..14d535957 100644 --- a/src/Api/PubnubApiPCL/PubnubApiPCL.csproj +++ b/src/Api/PubnubApiPCL/PubnubApiPCL.csproj @@ -219,16 +219,6 @@ - - - - - - - - - - diff --git a/src/Api/PubnubApiUWP/PubnubApiUWP.csproj b/src/Api/PubnubApiUWP/PubnubApiUWP.csproj index 5cb01b762..f3e3d01ad 100644 --- a/src/Api/PubnubApiUWP/PubnubApiUWP.csproj +++ b/src/Api/PubnubApiUWP/PubnubApiUWP.csproj @@ -336,16 +336,6 @@ - - - - - - - - - - From 714d676d0dd567aebea454317f8f2ec1e0737ecb Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Tue, 8 Aug 2023 16:09:01 +0530 Subject: [PATCH 19/56] fix ReceiveRequest for timeout --- src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs | 8 ++++++-- .../Subscribe/Effects/ReceivingEffectHandler.cs | 2 +- src/UnitTests/AcceptanceTests/Steps/EventEngineSteps.cs | 1 - 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs index e261aa739..6476ba3e2 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs @@ -171,8 +171,12 @@ internal async Task, PNStatus>> ReceiveRequest receiveResponse = JsonConvert.DeserializeObject>(responseTuple.Item1); return new Tuple, PNStatus>(receiveResponse, status); - } - return new Tuple, PNStatus>(null, responseTuple.Item2); + } + else if (responseTuple.Item2 != null) + { + return new Tuple, PNStatus>(null, responseTuple.Item2); + } + return new Tuple, PNStatus>(null, new PNStatus(new Exception("ReceiveRequest failed."), PNOperationType.PNSubscribeOperation, PNStatusCategory.PNUnknownCategory, channels, channelGroups)); } catch(Exception ex) { diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs index b8e03514f..94a1e44b4 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs @@ -71,7 +71,7 @@ public override async Task Run(ReceiveMessagesInvocation invocation) eventQueue.Enqueue(new Events.ReceiveReconnectSuccessEvent() { Cursor = cursor, Status = response.Item2 }); break; case { } when response.Item2.Error: - eventQueue.Enqueue(new Events.ReceiveFailureEvent() { Cursor = cursor, Status = response.Item2}); + eventQueue.Enqueue(new Events.ReceiveFailureEvent() { Cursor = invocation.Cursor, Status = response.Item2}); break; case { }: eventQueue.Enqueue(new Events.ReceiveSuccessEvent() { Channels = invocation?.Channels, ChannelGroups = invocation?.ChannelGroups, Cursor = cursor, Messages= response.Item1, Status = response.Item2 }); diff --git a/src/UnitTests/AcceptanceTests/Steps/EventEngineSteps.cs b/src/UnitTests/AcceptanceTests/Steps/EventEngineSteps.cs index 9b2edae6b..8123a7b15 100644 --- a/src/UnitTests/AcceptanceTests/Steps/EventEngineSteps.cs +++ b/src/UnitTests/AcceptanceTests/Steps/EventEngineSteps.cs @@ -11,7 +11,6 @@ using System.Text.Json; using System.Threading.Channels; using System.Threading; -using PubnubApi.PubnubEventEngine; using TechTalk.SpecFlow.Assist; using System.Net.Http; From 5be1234c07fefc79467b4863fe9a821b2c7c7de7 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Tue, 8 Aug 2023 16:42:06 +0530 Subject: [PATCH 20/56] reconnect fix from network failure --- .../EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs index 94a1e44b4..7bf3d7531 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs @@ -68,7 +68,7 @@ public override async Task Run(ReceiveMessagesInvocation invocation) eventQueue.Enqueue(new Events.ReceiveReconnectFailureEvent() { AttemptedRetries = reconnectInvocation.AttemptedRetries + 1, Status = response.Item2}); break; case Invocations.ReceiveReconnectInvocation reconnectInvocation: - eventQueue.Enqueue(new Events.ReceiveReconnectSuccessEvent() { Cursor = cursor, Status = response.Item2 }); + eventQueue.Enqueue(new Events.ReceiveReconnectSuccessEvent() { Channels = invocation?.Channels, ChannelGroups = invocation?.ChannelGroups, Cursor = cursor, Status = response.Item2 }); break; case { } when response.Item2.Error: eventQueue.Enqueue(new Events.ReceiveFailureEvent() { Cursor = invocation.Cursor, Status = response.Item2}); From 6ce2853a1d063021f8bdb5f0b2dc1f29e3e4cc82 Mon Sep 17 00:00:00 2001 From: Mohit Tejani Date: Tue, 8 Aug 2023 16:56:25 +0530 Subject: [PATCH 21/56] reconnection delay fix for exponential type --- .../EventEngine/Subscribe/Context/ReconnectionDelayUtil.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Context/ReconnectionDelayUtil.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Context/ReconnectionDelayUtil.cs index 393002481..31d6c108b 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Context/ReconnectionDelayUtil.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Context/ReconnectionDelayUtil.cs @@ -13,11 +13,10 @@ public static int CalculateDelay(PNReconnectionPolicy policy, int attempts) delayValue = attempts * backoff + numGenerator.Next(1000); break; case PNReconnectionPolicy.EXPONENTIAL: - delayValue = (int)(Math.Pow(2, attempts - 1) * 1000 + numGenerator.Next(1000)); + delayValue = (int)(Math.Pow(2, attempts) * 1000 + numGenerator.Next(1000)); break; } return delayValue; - } public static bool shouldRetry(ReconnectionConfiguration reconnectionConfiguration, int attemptedRetries) From 4e1fe1aaab4456a9c5d3e7d6d8f7e1aca0c02b18 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Tue, 8 Aug 2023 17:40:03 +0530 Subject: [PATCH 22/56] HandshakeFailureEvent to UnsubscribedState --- .../Subscribe/Events/SubscriptionEvents.cs | 2 ++ .../Subscribe/States/UnsubscribedState.cs | 6 ++++ .../UnsubscribedStateTransition.cs | 28 +++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs index 47a715a0a..d72b3f4fb 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs @@ -22,6 +22,8 @@ public class HandshakeSuccessEvent : Core.IEvent { } public class HandshakeFailureEvent : Core.IEvent { + public IEnumerable Channels; + public IEnumerable ChannelGroups; public PNStatus Status; public int AttemptedRetries; } diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs index 132a0a06d..c141e44d9 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs @@ -28,6 +28,12 @@ public override TransitionResult Transition(Core.IEvent e) ReconnectionConfiguration = this.ReconnectionConfiguration }, + Events.HandshakeFailureEvent handshakeFailure => new States.HandshakeReconnectingState() + { + Channels = handshakeFailure.Channels, + ChannelGroups = handshakeFailure.ChannelGroups, + ReconnectionConfiguration = this.ReconnectionConfiguration + }, _ => null }; } diff --git a/src/UnitTests/PubnubApi.Tests/EventEngine/UnsubscribedStateTransition.cs b/src/UnitTests/PubnubApi.Tests/EventEngine/UnsubscribedStateTransition.cs index 6147eec88..a81693d58 100644 --- a/src/UnitTests/PubnubApi.Tests/EventEngine/UnsubscribedStateTransition.cs +++ b/src/UnitTests/PubnubApi.Tests/EventEngine/UnsubscribedStateTransition.cs @@ -70,5 +70,33 @@ public void UnsubscribedState_OnSubscriptionRestoreEvent_TransitionToReceivingSt Assert.AreEqual(expectedState.ReconnectionConfiguration.ReconnectionPolicy, ((ReceivingState)result.State).ReconnectionConfiguration.ReconnectionPolicy); Assert.AreEqual(expectedState.ReconnectionConfiguration.MaximumReconnectionRetries, ((ReceivingState)result.State).ReconnectionConfiguration.MaximumReconnectionRetries); } + + [Test] + public void UnsubscribedState_OnHandshakeFailureEvent_TransitionToHandshakeReconnectingState() + { + //Arrange + var currentState = new UnsubscribedState() { Channels = new string[] { "ch1", "ch2" }, ChannelGroups = new string[] { "cg1", "cg2" }, ReconnectionConfiguration = new ReconnectionConfiguration(PNReconnectionPolicy.LINEAR, 50) }; + var eventToTriggerTransition = new HandshakeFailureEvent() + { + Channels = new string[] { "ch1", "ch2" }, + ChannelGroups = new string[] { "cg1", "cg2" }, + }; + var expectedState = new HandshakeReconnectingState() + { + Channels = new string[] { "ch1", "ch2" }, + ChannelGroups = new string[] { "cg1", "cg2" }, + ReconnectionConfiguration = new ReconnectionConfiguration(PNReconnectionPolicy.LINEAR, 50) + }; + + //Act + var result = currentState.Transition(eventToTriggerTransition); + + //Assert + Assert.IsInstanceOf(result.State); + CollectionAssert.AreEqual(expectedState.Channels, ((HandshakeReconnectingState)result.State).Channels); + CollectionAssert.AreEqual(expectedState.ChannelGroups, ((HandshakeReconnectingState)result.State).ChannelGroups); + Assert.AreEqual(expectedState.ReconnectionConfiguration.ReconnectionPolicy, ((HandshakeReconnectingState)result.State).ReconnectionConfiguration.ReconnectionPolicy); + Assert.AreEqual(expectedState.ReconnectionConfiguration.MaximumReconnectionRetries, ((HandshakeReconnectingState)result.State).ReconnectionConfiguration.MaximumReconnectionRetries); + } } } From dc5f9ab9378a27653c333ad56c03666612736a1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Tue, 8 Aug 2023 14:20:15 +0200 Subject: [PATCH 23/56] fix: background invocations --- src/Api/PubnubApi/EventEngine/Core/EffectDispatcher.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Api/PubnubApi/EventEngine/Core/EffectDispatcher.cs b/src/Api/PubnubApi/EventEngine/Core/EffectDispatcher.cs index e4fea80fc..46869f638 100644 --- a/src/Api/PubnubApi/EventEngine/Core/EffectDispatcher.cs +++ b/src/Api/PubnubApi/EventEngine/Core/EffectDispatcher.cs @@ -26,12 +26,17 @@ public async Task Dispatch(IEffectInvocation invocation) { { var handler = effectInvocationHandlerMap[invocation.GetType()]; if (handler.IsBackground(invocation)) - await handler.Run(invocation); + FireAndForget(handler, invocation); else await handler.Run(invocation); } } + void FireAndForget(IEffectHandler handler, IEffectInvocation invocation) + { + handler.Run(invocation); + } + /// /// Assign a handler implementation to an invocation. /// From 9eef18f06de220d8f5f772a9bf251c8209764044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Tue, 8 Aug 2023 15:47:12 +0200 Subject: [PATCH 24/56] fix: race condition --- src/Api/PubnubApi/EventEngine/Core/Engine.cs | 27 +++++++++++++------ .../PubnubApi/EventEngine/Core/EventQueue.cs | 2 +- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Core/Engine.cs b/src/Api/PubnubApi/EventEngine/Core/Engine.cs index 48ca50f08..91422d11f 100644 --- a/src/Api/PubnubApi/EventEngine/Core/Engine.cs +++ b/src/Api/PubnubApi/EventEngine/Core/Engine.cs @@ -1,12 +1,15 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using System.Collections.Generic; namespace PubnubApi.EventEngine.Core { public abstract class Engine { - public EventQueue EventQueue = new EventQueue(); + public readonly EventQueue EventQueue = new EventQueue(); protected EffectDispatcher dispatcher = new EffectDispatcher(); protected State currentState; + public State CurrentState => currentState; + private bool transitioning = false; private Task currentTransitionLoop = Utils.EmptyTask; @@ -42,21 +45,29 @@ public Engine() { private async void OnEvent(EventQueue q) { OnEventQueued?.Invoke(q.Peek()); - await currentTransitionLoop; - currentTransitionLoop = EventQueue.Loop(async e => currentState = await Transition(e)); + if (transitioning) return; + transitioning = true; + while (q.Count > 0) + { + await Transition(q.Dequeue()); + } + + transitioning = false; } - private async Task Transition(IEvent e) { + private async Task Transition(IEvent e) + { var stateInvocationPair = currentState.Transition(e); OnStateTransition?.Invoke(stateInvocationPair); - if (stateInvocationPair is null) { - return currentState; + if (stateInvocationPair is null) + { + return; } await ExecuteStateChange(currentState, stateInvocationPair.State, stateInvocationPair.Invocations); - return stateInvocationPair.State; + this.currentState = stateInvocationPair.State; } /// diff --git a/src/Api/PubnubApi/EventEngine/Core/EventQueue.cs b/src/Api/PubnubApi/EventEngine/Core/EventQueue.cs index e22991e0b..7cf2f397d 100644 --- a/src/Api/PubnubApi/EventEngine/Core/EventQueue.cs +++ b/src/Api/PubnubApi/EventEngine/Core/EventQueue.cs @@ -25,7 +25,7 @@ public void Enqueue(IEvent e) } } - private IEvent Dequeue() + public IEvent Dequeue() { lock (lockObj) { From db02e2766bc600cf8fe78d8496f6b2ca7f573785 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Tue, 8 Aug 2023 22:07:43 +0530 Subject: [PATCH 25/56] SubscribeEventEngine delegates for logging --- .../EndPoint/PubSub/SubscribeOperation2.cs | 31 ++++++++++++++++++- .../UnsubscribedStateTransition.cs | 28 ----------------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs index 9fa53a56b..bf187bede 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs @@ -8,6 +8,9 @@ using System.Globalization; using PubnubApi.EventEngine.Subscribe; using PubnubApi; +using PubnubApi.EventEngine.Core; +using PubnubApi.EventEngine.Subscribe.Events; +using PubnubApi.EventEngine.Subscribe.States; namespace PubnubApi.EndPoint { @@ -658,11 +661,37 @@ private void Subscribe(string[] channels, string[] channelGroups, Dictionary(channels, channelGroups); } + private void SubscribeEventEngine_OnEffectDispatch(IEffectInvocation obj) + { + LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnEffectDispatch : CurrentState = {subscribeEventEngine.CurrentState} => Invocation = {obj}", config.LogVerbosity); + } + + private void SubscribeEventEngine_OnEventQueued(IEvent @event) + { + int attempts = 0; + if (subscribeEventEngine.CurrentState is HandshakeReconnectingState handshakeReconnectingState) + { + attempts = handshakeReconnectingState.AttemptedRetries; + } + else if (subscribeEventEngine.CurrentState is ReceiveReconnectingState receiveReconnectingState) + { + attempts = receiveReconnectingState.AttemptedRetries; + } + LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnEventQueued : CurrentState: {subscribeEventEngine.CurrentState}; Event = {@event.GetType()}; Attempt = {attempts} of {config.ConnectionMaxRetries}", config.LogVerbosity); + } + + private void SubscribeEventEngine_OnStateTransition(EventEngine.Core.TransitionResult obj) + { + LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnStateTransition : CurrentState = {subscribeEventEngine.CurrentState} => Transition State = {obj.State}", config.LogVerbosity); + } + internal bool Retry(bool reconnect) { return false; diff --git a/src/UnitTests/PubnubApi.Tests/EventEngine/UnsubscribedStateTransition.cs b/src/UnitTests/PubnubApi.Tests/EventEngine/UnsubscribedStateTransition.cs index a81693d58..6147eec88 100644 --- a/src/UnitTests/PubnubApi.Tests/EventEngine/UnsubscribedStateTransition.cs +++ b/src/UnitTests/PubnubApi.Tests/EventEngine/UnsubscribedStateTransition.cs @@ -70,33 +70,5 @@ public void UnsubscribedState_OnSubscriptionRestoreEvent_TransitionToReceivingSt Assert.AreEqual(expectedState.ReconnectionConfiguration.ReconnectionPolicy, ((ReceivingState)result.State).ReconnectionConfiguration.ReconnectionPolicy); Assert.AreEqual(expectedState.ReconnectionConfiguration.MaximumReconnectionRetries, ((ReceivingState)result.State).ReconnectionConfiguration.MaximumReconnectionRetries); } - - [Test] - public void UnsubscribedState_OnHandshakeFailureEvent_TransitionToHandshakeReconnectingState() - { - //Arrange - var currentState = new UnsubscribedState() { Channels = new string[] { "ch1", "ch2" }, ChannelGroups = new string[] { "cg1", "cg2" }, ReconnectionConfiguration = new ReconnectionConfiguration(PNReconnectionPolicy.LINEAR, 50) }; - var eventToTriggerTransition = new HandshakeFailureEvent() - { - Channels = new string[] { "ch1", "ch2" }, - ChannelGroups = new string[] { "cg1", "cg2" }, - }; - var expectedState = new HandshakeReconnectingState() - { - Channels = new string[] { "ch1", "ch2" }, - ChannelGroups = new string[] { "cg1", "cg2" }, - ReconnectionConfiguration = new ReconnectionConfiguration(PNReconnectionPolicy.LINEAR, 50) - }; - - //Act - var result = currentState.Transition(eventToTriggerTransition); - - //Assert - Assert.IsInstanceOf(result.State); - CollectionAssert.AreEqual(expectedState.Channels, ((HandshakeReconnectingState)result.State).Channels); - CollectionAssert.AreEqual(expectedState.ChannelGroups, ((HandshakeReconnectingState)result.State).ChannelGroups); - Assert.AreEqual(expectedState.ReconnectionConfiguration.ReconnectionPolicy, ((HandshakeReconnectingState)result.State).ReconnectionConfiguration.ReconnectionPolicy); - Assert.AreEqual(expectedState.ReconnectionConfiguration.MaximumReconnectionRetries, ((HandshakeReconnectingState)result.State).ReconnectionConfiguration.MaximumReconnectionRetries); - } } } From 812fa3a1f166fb9102ed8a3a0ac3e7b8809f8b73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Wed, 9 Aug 2023 10:21:37 +0200 Subject: [PATCH 26/56] fix: core abstraction not broken anymore --- src/Api/PubnubApi/EventEngine/Core/EventEngineInterfaces.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Core/EventEngineInterfaces.cs b/src/Api/PubnubApi/EventEngine/Core/EventEngineInterfaces.cs index c58119d7a..2041f6745 100644 --- a/src/Api/PubnubApi/EventEngine/Core/EventEngineInterfaces.cs +++ b/src/Api/PubnubApi/EventEngine/Core/EventEngineInterfaces.cs @@ -68,10 +68,10 @@ public abstract class EffectDoubleHandler : EffectHandler, IEffectHa { public new Task Run(IEffectInvocation invocation) => - invocation is T1 ? (this as EffectHandler).Run(invocation) : Run(invocation as T2); + invocation is T2 ? Run(invocation as T2) : (this as EffectHandler).Run(invocation); public new bool IsBackground(IEffectInvocation invocation) => - invocation is T1 ? (this as EffectHandler).IsBackground(invocation) : IsBackground(invocation as T2); + invocation is T2 ? IsBackground(invocation as T2) : (this as EffectHandler).IsBackground(invocation); public abstract Task Run(T2 invocation); From 2e6e738836f9806f9de4d4d454cdd56b0ec498a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Wed, 9 Aug 2023 10:42:51 +0200 Subject: [PATCH 27/56] fix: delay --- src/Api/PubnubApi/EventEngine/Common/Delay.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Common/Delay.cs b/src/Api/PubnubApi/EventEngine/Common/Delay.cs index 3afb9a4a6..05be6e9ea 100644 --- a/src/Api/PubnubApi/EventEngine/Common/Delay.cs +++ b/src/Api/PubnubApi/EventEngine/Common/Delay.cs @@ -6,7 +6,7 @@ namespace PubnubApi.EventEngine.Common public class Delay { public bool Cancelled { get; private set; } = false; - private readonly TaskCompletionSource taskCompletionSource = new TaskCompletionSource(); + private TaskCompletionSource taskCompletionSource; private readonly object monitor = new object(); private readonly int milliseconds; @@ -17,6 +17,7 @@ public Delay(int milliseconds) public Task Start() { + taskCompletionSource = new TaskCompletionSource(); #if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 Task taskAwaiter = Task.Factory.StartNew(AwaiterLoop); taskAwaiter.Wait(); @@ -24,7 +25,8 @@ public Task Start() Thread awaiterThread = new Thread(AwaiterLoop); awaiterThread.Start(); #endif - return taskCompletionSource.Task; } + return taskCompletionSource.Task; + } public void Cancel() { From 2d889f3ded90516f2acaf5ddec708b2a9c47a4dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Wed, 9 Aug 2023 10:45:42 +0200 Subject: [PATCH 28/56] fix: fix --- src/Api/PubnubApi/EventEngine/Common/Delay.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Api/PubnubApi/EventEngine/Common/Delay.cs b/src/Api/PubnubApi/EventEngine/Common/Delay.cs index 05be6e9ea..017fc9552 100644 --- a/src/Api/PubnubApi/EventEngine/Common/Delay.cs +++ b/src/Api/PubnubApi/EventEngine/Common/Delay.cs @@ -30,6 +30,7 @@ public Task Start() public void Cancel() { + if (Cancelled) return; lock (monitor) { Cancelled = true; @@ -39,7 +40,7 @@ public void Cancel() private void AwaiterLoop() { - while(true) + while(!Cancelled) { lock (monitor) { From f5623445173901544c814046beac40b826561758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Wed, 9 Aug 2023 10:46:45 +0200 Subject: [PATCH 29/56] fix: delay --- src/Api/PubnubApi/EventEngine/Common/Delay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Api/PubnubApi/EventEngine/Common/Delay.cs b/src/Api/PubnubApi/EventEngine/Common/Delay.cs index 017fc9552..dbbe39f43 100644 --- a/src/Api/PubnubApi/EventEngine/Common/Delay.cs +++ b/src/Api/PubnubApi/EventEngine/Common/Delay.cs @@ -18,6 +18,7 @@ public Delay(int milliseconds) public Task Start() { taskCompletionSource = new TaskCompletionSource(); + Cancelled = false; #if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 Task taskAwaiter = Task.Factory.StartNew(AwaiterLoop); taskAwaiter.Wait(); @@ -56,6 +57,7 @@ private void AwaiterLoop() break; } taskCompletionSource.SetResult(null); + Cancelled = true; } } } From d406f85e505bed71bf372f5cd1aeb1f054ab4832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Wed, 9 Aug 2023 10:50:17 +0200 Subject: [PATCH 30/56] fix: delay --- src/Api/PubnubApi/EventEngine/Common/Delay.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Api/PubnubApi/EventEngine/Common/Delay.cs b/src/Api/PubnubApi/EventEngine/Common/Delay.cs index dbbe39f43..21ef3da57 100644 --- a/src/Api/PubnubApi/EventEngine/Common/Delay.cs +++ b/src/Api/PubnubApi/EventEngine/Common/Delay.cs @@ -41,7 +41,7 @@ public void Cancel() private void AwaiterLoop() { - while(!Cancelled) + while(true) { lock (monitor) { @@ -58,6 +58,7 @@ private void AwaiterLoop() } taskCompletionSource.SetResult(null); Cancelled = true; + break; } } } From 4db4290933668ba276cc2e11d5340b3a8fdb493f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Wed, 9 Aug 2023 11:02:39 +0200 Subject: [PATCH 31/56] fix: delay --- src/Api/PubnubApi/EventEngine/Common/Delay.cs | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Common/Delay.cs b/src/Api/PubnubApi/EventEngine/Common/Delay.cs index 21ef3da57..09b34afe1 100644 --- a/src/Api/PubnubApi/EventEngine/Common/Delay.cs +++ b/src/Api/PubnubApi/EventEngine/Common/Delay.cs @@ -21,7 +21,6 @@ public Task Start() Cancelled = false; #if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 Task taskAwaiter = Task.Factory.StartNew(AwaiterLoop); - taskAwaiter.Wait(); #else Thread awaiterThread = new Thread(AwaiterLoop); awaiterThread.Start(); @@ -41,25 +40,21 @@ public void Cancel() private void AwaiterLoop() { - while(true) + lock (monitor) { - lock (monitor) + if (Cancelled) + { + taskCompletionSource.SetCanceled(); + return; + } + Monitor.Wait(monitor, milliseconds); + if (Cancelled) { - if (Cancelled) - { - taskCompletionSource.SetCanceled(); - break; - } - Monitor.Wait(monitor, milliseconds); - if (Cancelled) - { - taskCompletionSource.SetCanceled(); - break; - } - taskCompletionSource.SetResult(null); - Cancelled = true; - break; + taskCompletionSource.SetCanceled(); + return; } + taskCompletionSource.SetResult(null); + Cancelled = true; } } } From 8066cd7bcdf3c9fa8c64f3d0fb8919893378f6cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Wed, 9 Aug 2023 11:50:41 +0200 Subject: [PATCH 32/56] fix: handshake --- .../EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs index a517a0601..299c4df6c 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs @@ -39,7 +39,7 @@ public override async Task Run(HandshakeReconnectInvocation invocation) retryDelay = new Delay(ReconnectionDelayUtil.CalculateDelay(invocation.ReconnectionConfiguration.ReconnectionPolicy, invocation.AttemptedRetries)); await retryDelay.Start(); if (!retryDelay.Cancelled) - await Run((HandshakeInvocation)invocation); + await Run(new HandshakeInvocation() { Channels = invocation.Channels, ChannelGroups = invocation.ChannelGroups, ExternalQueryParams = invocation.ExternalQueryParams, InitialSubscribeQueryParams = invocation.InitialSubscribeQueryParams }); } } From 3c44ccf8f478f67ed5f2e5f4c2c4ab4d33c820b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Wed, 9 Aug 2023 12:18:55 +0200 Subject: [PATCH 33/56] fix: HandshakeEffectHandler.cs composition pattern --- .../Effects/HandshakeEffectHandler.cs | 70 ++++++++++++------- .../Subscribe/SubscribeEventEngine.cs | 7 +- 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs index 299c4df6c..e845ea0c8 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs @@ -15,12 +15,10 @@ namespace PubnubApi.EventEngine.Subscribe.Effects { public class HandshakeEffectHandler : - EffectDoubleCancellableHandler + EffectCancellableHandler { - private SubscribeManager2 manager; - private EventQueue eventQueue; - - private Delay retryDelay = new Delay(0); + private readonly SubscribeManager2 manager; + private readonly EventQueue eventQueue; internal HandshakeEffectHandler(SubscribeManager2 manager, EventQueue eventQueue) { @@ -28,26 +26,6 @@ internal HandshakeEffectHandler(SubscribeManager2 manager, EventQueue eventQueue this.eventQueue = eventQueue; } - public override async Task Run(HandshakeReconnectInvocation invocation) - { - if (!ReconnectionDelayUtil.shouldRetry(invocation.ReconnectionConfiguration, invocation.AttemptedRetries)) - { - eventQueue.Enqueue(new HandshakeReconnectGiveUpEvent() { Status = new PNStatus(PNStatusCategory.PNCancelledCategory) }); - } - else - { - retryDelay = new Delay(ReconnectionDelayUtil.CalculateDelay(invocation.ReconnectionConfiguration.ReconnectionPolicy, invocation.AttemptedRetries)); - await retryDelay.Start(); - if (!retryDelay.Cancelled) - await Run(new HandshakeInvocation() { Channels = invocation.Channels, ChannelGroups = invocation.ChannelGroups, ExternalQueryParams = invocation.ExternalQueryParams, InitialSubscribeQueryParams = invocation.InitialSubscribeQueryParams }); - } - } - - public override bool IsBackground(HandshakeReconnectInvocation invocation) - { - return true; - } - public override async Task Run(HandshakeInvocation invocation) { var response = await MakeHandshakeRequest(invocation); @@ -98,6 +76,45 @@ public override bool IsBackground(HandshakeInvocation invocation) ); } + public override async Task Cancel() + { + manager.HandshakeRequestCancellation(); + } + + } + + public class HandshakeReconnectEffectHandler : EffectCancellableHandler + { + private readonly EventQueue eventQueue; + + private HandshakeEffectHandler handshakeEffectHandler; + + private Delay retryDelay = new Delay(0); + + + internal HandshakeReconnectEffectHandler(SubscribeManager2 manager, EventQueue eventQueue, HandshakeEffectHandler handshakeEffectHandler) + { + this.eventQueue = eventQueue; + this.handshakeEffectHandler = handshakeEffectHandler; + } + + public override async Task Run(HandshakeReconnectInvocation invocation) + { + if (!ReconnectionDelayUtil.shouldRetry(invocation.ReconnectionConfiguration, invocation.AttemptedRetries)) + { + eventQueue.Enqueue(new HandshakeReconnectGiveUpEvent() { Status = new PNStatus(PNStatusCategory.PNCancelledCategory) }); + } + else + { + retryDelay = new Delay(ReconnectionDelayUtil.CalculateDelay(invocation.ReconnectionConfiguration.ReconnectionPolicy, invocation.AttemptedRetries)); + await retryDelay.Start(); + if (!retryDelay.Cancelled) + await handshakeEffectHandler.Run(invocation as HandshakeInvocation); + } + } + + public override bool IsBackground(HandshakeReconnectInvocation invocation) => true; + public override async Task Cancel() { if (!retryDelay.Cancelled) @@ -106,9 +123,8 @@ public override async Task Cancel() } else { - manager.HandshakeRequestCancellation(); + await handshakeEffectHandler.Cancel(); } } - } } \ No newline at end of file diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs index 4b6f5a4d1..fbcb93dcc 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs @@ -8,6 +8,8 @@ using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; +using System.Linq; +using PubnubApi.EventEngine.Subscribe.Common; namespace PubnubApi.EventEngine.Subscribe { public class SubscribeEventEngine : Engine { @@ -30,10 +32,11 @@ internal SubscribeEventEngine(Pubnub pubnubInstance, // initialize the handler, pass dependencies var handshakeHandler = new Effects.HandshakeEffectHandler(subscribeManager, EventQueue); + var handshakeReconnectHandler = new Effects.HandshakeReconnectEffectHandler(subscribeManager, EventQueue, handshakeHandler); dispatcher.Register(handshakeHandler); dispatcher.Register(handshakeHandler); - dispatcher.Register(handshakeHandler); - dispatcher.Register(handshakeHandler); + dispatcher.Register(handshakeReconnectHandler); + dispatcher.Register(handshakeReconnectHandler); var receiveHandler = new Effects.ReceivingEffectHandler(subscribeManager, EventQueue); dispatcher.Register(receiveHandler); From dcbc426089cfbb307b887422ef0099ebb732eb8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Wed, 9 Aug 2023 12:29:54 +0200 Subject: [PATCH 34/56] fix: ReceivingEffectHandler.cs composition pattern --- .../Effects/ReceivingEffectHandler.cs | 69 ++++++++++++------- .../Subscribe/SubscribeEventEngine.cs | 5 +- 2 files changed, 47 insertions(+), 27 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs index 7bf3d7531..71bc99196 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs @@ -15,12 +15,10 @@ namespace PubnubApi.EventEngine.Subscribe.Effects { public class ReceivingEffectHandler: - EffectDoubleCancellableHandler + EffectCancellableHandler { private SubscribeManager2 manager; private EventQueue eventQueue; - - private Delay retryDelay = new Delay(0); internal ReceivingEffectHandler(SubscribeManager2 manager, EventQueue eventQueue) { @@ -28,27 +26,6 @@ internal ReceivingEffectHandler(SubscribeManager2 manager, EventQueue eventQueue this.eventQueue = eventQueue; } - public override Task Run(ReceiveReconnectInvocation invocation) - { - if (!ReconnectionDelayUtil.shouldRetry(invocation.ReconnectionConfiguration, invocation.AttemptedRetries)) - { - eventQueue.Enqueue(new ReceiveReconnectGiveUpEvent() { Status = new PNStatus(PNStatusCategory.PNCancelledCategory) }); - } - else - { - retryDelay = new Delay(ReconnectionDelayUtil.CalculateDelay(invocation.ReconnectionConfiguration.ReconnectionPolicy, invocation.AttemptedRetries)); - // Run in the background - retryDelay.Start().ContinueWith((_) => this.Run((ReceiveMessagesInvocation)invocation)); - } - - return Utils.EmptyTask; - } - - public override bool IsBackground(ReceiveReconnectInvocation invocation) - { - return true; - } - public override async Task Run(ReceiveMessagesInvocation invocation) { var response = await MakeReceiveMessagesRequest(invocation); @@ -97,6 +74,48 @@ public override bool IsBackground(ReceiveMessagesInvocation invocation) ); } + public override async Task Cancel() + { + manager.ReceiveRequestCancellation(); + } + } + + public class ReceivingReconnectEffectHandler : + EffectCancellableHandler + { + private SubscribeManager2 manager; + private EventQueue eventQueue; + private ReceivingEffectHandler receivingEffectHandler; + + private Delay retryDelay = new Delay(0); + + internal ReceivingReconnectEffectHandler(SubscribeManager2 manager, EventQueue eventQueue, ReceivingEffectHandler receivingEffectHandler) + { + this.manager = manager; + this.eventQueue = eventQueue; + this.receivingEffectHandler = receivingEffectHandler; + } + + public override async Task Run(ReceiveReconnectInvocation invocation) + { + if (!ReconnectionDelayUtil.shouldRetry(invocation.ReconnectionConfiguration, invocation.AttemptedRetries)) + { + eventQueue.Enqueue(new ReceiveReconnectGiveUpEvent() { Status = new PNStatus(PNStatusCategory.PNCancelledCategory) }); + } + else + { + retryDelay = new Delay(ReconnectionDelayUtil.CalculateDelay(invocation.ReconnectionConfiguration.ReconnectionPolicy, invocation.AttemptedRetries)); + // Run in the background + await retryDelay.Start(); + await receivingEffectHandler.Run(invocation); + } + } + + public override bool IsBackground(ReceiveReconnectInvocation invocation) + { + return true; + } + public override async Task Cancel() { if (!retryDelay.Cancelled) @@ -105,7 +124,7 @@ public override async Task Cancel() } else { - manager.ReceiveRequestCancellation(); + await receivingEffectHandler.Cancel(); } } } diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs index fbcb93dcc..d5f463b61 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs @@ -39,10 +39,11 @@ internal SubscribeEventEngine(Pubnub pubnubInstance, dispatcher.Register(handshakeReconnectHandler); var receiveHandler = new Effects.ReceivingEffectHandler(subscribeManager, EventQueue); + var receiveReconnectHandler = new Effects.ReceivingReconnectEffectHandler(subscribeManager, EventQueue, receiveHandler); dispatcher.Register(receiveHandler); dispatcher.Register(receiveHandler); - dispatcher.Register(receiveHandler); - dispatcher.Register(receiveHandler); + dispatcher.Register(receiveReconnectHandler); + dispatcher.Register(receiveReconnectHandler); var emitMessageHandler = new Effects.EmitMessagesHandler(pubnubInstance, messageListener, Serializer, channelTypeMap, channelGroupTypeMap); dispatcher.Register(emitMessageHandler); From 71767ab97ae1809f3ddff878e3183c30031853a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dobrza=C5=84ski?= Date: Wed, 9 Aug 2023 12:52:42 +0200 Subject: [PATCH 35/56] fix: cancel --- .../Subscribe/Effects/HandshakeEffectHandler.cs | 10 ++-------- .../Subscribe/Effects/ReceivingEffectHandler.cs | 10 ++-------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs index e845ea0c8..cb9ed6000 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs @@ -117,14 +117,8 @@ public override async Task Run(HandshakeReconnectInvocation invocation) public override async Task Cancel() { - if (!retryDelay.Cancelled) - { - retryDelay.Cancel(); - } - else - { - await handshakeEffectHandler.Cancel(); - } + retryDelay.Cancel(); + await handshakeEffectHandler.Cancel(); } } } \ No newline at end of file diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs index 71bc99196..414694b6b 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs @@ -118,14 +118,8 @@ public override bool IsBackground(ReceiveReconnectInvocation invocation) public override async Task Cancel() { - if (!retryDelay.Cancelled) - { - retryDelay.Cancel(); - } - else - { - await receivingEffectHandler.Cancel(); - } + retryDelay.Cancel(); + await receivingEffectHandler.Cancel(); } } } From 106983373cb38e4454c10e68ed250ac0ac367524 Mon Sep 17 00:00:00 2001 From: Mohit Tejani Date: Wed, 9 Aug 2023 16:47:06 +0530 Subject: [PATCH 36/56] `Unsubscribe()` at eventengine --- .../EventEngine/Subscribe/SubscribeEventEngine.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs index d5f463b61..63c204483 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs @@ -75,5 +75,13 @@ public void UnsubscribeAll() { this.EventQueue.Enqueue(new UnsubscribeAllEvent()); } + + public void Unsubscribe(string[] channels, string[] channelGroups) + { + this.EventQueue.Enqueue(new SubscriptionChangedEvent() { + Channels = (this.currentState as SubscriptionState).Channels.Except(channels), + ChannelGroups = (this.currentState as SubscriptionState).ChannelGroups.Except(channelGroups) + }); + } } } \ No newline at end of file From b846c145993a57b5e16297356f82c4975d53308d Mon Sep 17 00:00:00 2001 From: Mohit Tejani Date: Wed, 9 Aug 2023 17:40:49 +0530 Subject: [PATCH 37/56] fix: delay calculation as per doc --- .../Subscribe/Context/ReconnectionDelayUtil.cs | 14 +++++++------- .../Subscribe/States/HandshakingState.cs | 2 +- .../EventEngine/Subscribe/States/ReceivingState.cs | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Context/ReconnectionDelayUtil.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Context/ReconnectionDelayUtil.cs index 31d6c108b..92fe9f5ac 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Context/ReconnectionDelayUtil.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Context/ReconnectionDelayUtil.cs @@ -5,25 +5,25 @@ public static class ReconnectionDelayUtil { public static int CalculateDelay(PNReconnectionPolicy policy, int attempts) { - Random numGenerator = new Random(); - int delayValue = 0; - int backoff = 5; + int delayMillisecond = 0; switch (policy) { case PNReconnectionPolicy.LINEAR: - delayValue = attempts * backoff + numGenerator.Next(1000); + delayMillisecond = 3000; break; case PNReconnectionPolicy.EXPONENTIAL: - delayValue = (int)(Math.Pow(2, attempts) * 1000 + numGenerator.Next(1000)); + int i = attempts % int.MaxValue; + if (attempts % 6 == 0) i = attempts + 1; + delayMillisecond = (int)((Math.Pow(2, (i % 6)) - 1) * 1000); break; } - return delayValue; + return delayMillisecond; } public static bool shouldRetry(ReconnectionConfiguration reconnectionConfiguration, int attemptedRetries) { if (reconnectionConfiguration.ReconnectionPolicy == PNReconnectionPolicy.NONE) return false; if (reconnectionConfiguration.MaximumReconnectionRetries < 0) return true; - return reconnectionConfiguration.MaximumReconnectionRetries < attemptedRetries; + return reconnectionConfiguration.MaximumReconnectionRetries >= attemptedRetries; } } } diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs index 457f9316a..ed42dc8ad 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs @@ -45,7 +45,7 @@ public override TransitionResult Transition(IEvent e) Channels = this.Channels, ChannelGroups = this.ChannelGroups, ReconnectionConfiguration = this.ReconnectionConfiguration, - AttemptedRetries = 0 + AttemptedRetries = 1 }.With(new EmitStatusInvocation(handshakeFailure.Status)), Events.DisconnectEvent disconnect => new States.HandshakeStoppedState() diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs index d08ae8abb..cdc2edcd7 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs @@ -66,7 +66,7 @@ public override TransitionResult Transition(IEvent e) ChannelGroups = this.ChannelGroups, Cursor = this.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration, - AttemptedRetries = 0 + AttemptedRetries = 1 }, _ => null From a225a770844ff998983205254a943c2f3d3c0d81 Mon Sep 17 00:00:00 2001 From: Mohit Tejani Date: Wed, 9 Aug 2023 18:04:15 +0530 Subject: [PATCH 38/56] attempt value bound --- .../EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs | 2 +- .../EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs | 2 +- .../EventEngine/Subscribe/States/HandshakeReconnectingState.cs | 2 +- .../EventEngine/Subscribe/States/ReceiveReconnectingState.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs index cb9ed6000..e391ecfac 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs @@ -42,7 +42,7 @@ public override async Task Run(HandshakeInvocation invocation) switch (invocation) { case Invocations.HandshakeReconnectInvocation reconnectInvocation when response.Item2.Error: - eventQueue.Enqueue(new Events.HandshakeReconnectFailureEvent() { AttemptedRetries = reconnectInvocation.AttemptedRetries + 1, Status = response.Item2}); + eventQueue.Enqueue(new Events.HandshakeReconnectFailureEvent() { AttemptedRetries = (reconnectInvocation.AttemptedRetries + 1) % int.MaxValue, Status = response.Item2}); break; case Invocations.HandshakeReconnectInvocation reconnectInvocation: eventQueue.Enqueue(new Events.HandshakeReconnectSuccessEvent() { Cursor = cursor, Status = response.Item2 }); diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs index 414694b6b..3a33c1978 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs @@ -42,7 +42,7 @@ public override async Task Run(ReceiveMessagesInvocation invocation) switch (invocation) { case Invocations.ReceiveReconnectInvocation reconnectInvocation when response.Item2.Error: - eventQueue.Enqueue(new Events.ReceiveReconnectFailureEvent() { AttemptedRetries = reconnectInvocation.AttemptedRetries + 1, Status = response.Item2}); + eventQueue.Enqueue(new Events.ReceiveReconnectFailureEvent() { AttemptedRetries = (reconnectInvocation.AttemptedRetries + 1) % int.MaxValue, Status = response.Item2}); break; case Invocations.ReceiveReconnectInvocation reconnectInvocation: eventQueue.Enqueue(new Events.ReceiveReconnectSuccessEvent() { Channels = invocation?.Channels, ChannelGroups = invocation?.ChannelGroups, Cursor = cursor, Status = response.Item2 }); diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs index eae980448..4853be3eb 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs @@ -57,7 +57,7 @@ public override TransitionResult Transition(IEvent e) Channels = this.Channels, ChannelGroups = this.ChannelGroups, ReconnectionConfiguration = this.ReconnectionConfiguration, - AttemptedRetries = this.AttemptedRetries + 1 + AttemptedRetries = (this.AttemptedRetries + 1) % int.MaxValue }.With(new EmitStatusInvocation(handshakeReconnectFailure.Status)), Events.HandshakeReconnectSuccessEvent handshakeReconnectSuccess => new ReceivingState() diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs index 61dcbf397..42652231f 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs @@ -74,7 +74,7 @@ public override TransitionResult Transition(IEvent e) ChannelGroups = this.ChannelGroups, Cursor = this.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration, - AttemptedRetries = this.AttemptedRetries + 1 + AttemptedRetries = (this.AttemptedRetries + 1) % int.MaxValue }.With(new EmitStatusInvocation(receiveReconnectFailure.Status)), Events.ReceiveReconnectGiveUpEvent receiveReconnectGiveUp => new ReceiveFailedState() From 4c7e727e5fd90f198b932ce8544cd116a2777673 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Wed, 9 Aug 2023 21:26:08 +0530 Subject: [PATCH 39/56] fix for disconnect and reconnect --- .../EndPoint/PubSub/SubscribeManager2.cs | 52 ------------------ .../EndPoint/PubSub/SubscribeOperation2.cs | 8 +-- .../Subscribe/Common/CommonSubscribeTypes.cs | 1 + .../Effects/HandshakeEffectHandler.cs | 15 ++++-- .../Invocations/SubscriptionInvocations.cs | 1 + .../Subscribe/States/HandshakingState.cs | 5 +- .../Subscribe/States/ReceiveFailedState.cs | 2 - .../States/ReceiveReconnectingState.cs | 6 +-- .../Subscribe/States/ReceiveStoppedState.cs | 2 - .../Subscribe/States/ReceivingState.cs | 2 - src/Api/PubnubApi/Pubnub.cs | 53 +++++++++++++++---- 11 files changed, 63 insertions(+), 84 deletions(-) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs index 6476ba3e2..55ffdf710 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs @@ -558,58 +558,6 @@ private PNStatus GetStatusIfError(RequestState asyncRequestState, string j return status; } - internal List WrapResultBasedOnResponseType(PNOperationType type, string jsonString, string[] channels, string[] channelGroups) - { - List result = new List(); - try - { - string multiChannel = (channels != null) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ""; - string multiChannelGroup = (channelGroups != null) ? string.Join(",", channelGroups.OrderBy(x => x).ToArray()) : ""; - - if (!string.IsNullOrEmpty(jsonString)) - { - object deserializedResult = jsonLibrary.DeserializeToObject(jsonString); - List result1 = ((IEnumerable)deserializedResult).Cast().ToList(); - - if (result1 != null && result1.Count > 0) - { - result = result1; - } - - switch (type) - { - case PNOperationType.PNSubscribeOperation: - case PNOperationType.Presence: - if (result.Count == 3 && result[0] is object[] && (result[0] as object[]).Length == 0 && result[2].ToString() == "") - { - result.RemoveAt(2); - } - if (result.Count == 4 && result[0] is object[] && (result[0] as object[]).Length == 0 && result[2].ToString() == "" && result[3].ToString() == "") - { - result.RemoveRange(2, 2); - } - result.Add(multiChannelGroup); - result.Add(multiChannel); - - break; - case PNOperationType.PNHeartbeatOperation: - //Dictionary heartbeatadictionary = jsonLibrary.DeserializeToDictionaryOfObject(jsonString); - //result = new List(); - //result.Add(heartbeatadictionary); - //result.Add(multiChannel); - break; - default: - break; - } - //switch stmt end - } - } - catch { /* ignore */ } - - return result; - } - - internal bool Disconnect() { return true; diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs index bf187bede..faa27d0fb 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs @@ -11,6 +11,7 @@ using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Events; using PubnubApi.EventEngine.Subscribe.States; +using PubnubApi.EventEngine.Subscribe.Common; namespace PubnubApi.EndPoint { @@ -670,12 +671,13 @@ private void Subscribe(string[] channels, string[] channelGroups, Dictionary Invocation = {obj}", config.LogVerbosity); + LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnEffectDispatch : CurrentState = {subscribeEventEngine.CurrentState.GetType().Name} => Invocation = {obj.GetType().Name}", config.LogVerbosity); } private void SubscribeEventEngine_OnEventQueued(IEvent @event) { int attempts = 0; + SubscriptionCursor subscriptionCursor = null; if (subscribeEventEngine.CurrentState is HandshakeReconnectingState handshakeReconnectingState) { attempts = handshakeReconnectingState.AttemptedRetries; @@ -684,12 +686,12 @@ private void SubscribeEventEngine_OnEventQueued(IEvent @event) { attempts = receiveReconnectingState.AttemptedRetries; } - LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnEventQueued : CurrentState: {subscribeEventEngine.CurrentState}; Event = {@event.GetType()}; Attempt = {attempts} of {config.ConnectionMaxRetries}", config.LogVerbosity); + LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnEventQueued : CurrentState: {subscribeEventEngine.CurrentState.GetType().Name}; Event = {@event.GetType().Name}; Attempt = {attempts} of {config.ConnectionMaxRetries}", config.LogVerbosity); } private void SubscribeEventEngine_OnStateTransition(EventEngine.Core.TransitionResult obj) { - LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnStateTransition : CurrentState = {subscribeEventEngine.CurrentState} => Transition State = {obj.State}", config.LogVerbosity); + LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnStateTransition : CurrentState = {subscribeEventEngine.CurrentState.GetType().Name} => Transition State = {obj?.State.GetType().Name}", config.LogVerbosity); } internal bool Retry(bool reconnect) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs index ff2362cfe..e9b56ffe8 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs @@ -89,6 +89,7 @@ public abstract class SubscriptionState : Core.State { public IEnumerable Channels; public IEnumerable ChannelGroups; + public SubscriptionCursor Cursor; public ReconnectionConfiguration ReconnectionConfiguration; } } \ No newline at end of file diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs index e391ecfac..23e8dcd9d 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs @@ -32,11 +32,18 @@ public override async Task Run(HandshakeInvocation invocation) SubscriptionCursor cursor = null; if (response.Item1 != null) { - cursor = new SubscriptionCursor() + if (invocation.Cursor != null && invocation.Cursor.Timetoken != null) + { + cursor = invocation.Cursor; + } + else if (response.Item1.Timetoken != null) { - Region = response.Item1.Timetoken.Region, - Timetoken = response.Item1.Timetoken.Timestamp - }; + cursor = new SubscriptionCursor() + { + Region = response.Item1.Timetoken.Region, + Timetoken = response.Item1.Timetoken.Timestamp + }; + } } switch (invocation) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs index 365bd465c..6e4a542a3 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs @@ -41,6 +41,7 @@ public EmitStatusInvocation(PNStatusCategory category) public class HandshakeInvocation : Core.IEffectInvocation { public IEnumerable Channels; public IEnumerable ChannelGroups; + public SubscriptionCursor Cursor; // TODO if we need these, figure out how to pass them. public Dictionary InitialSubscribeQueryParams = new Dictionary(); public Dictionary ExternalQueryParams = new Dictionary(); diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs index ed42dc8ad..4e77a7956 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs @@ -9,10 +9,8 @@ namespace PubnubApi.EventEngine.Subscribe.States { public class HandshakingState : SubscriptionState { - public SubscriptionCursor Cursor { get; set; } public override IEnumerable OnEntry => new HandshakeInvocation() - { Channels = this.Channels, - ChannelGroups = this.ChannelGroups }.AsArray(); + { Channels = this.Channels, ChannelGroups = this.ChannelGroups, Cursor = this.Cursor }.AsArray(); public override IEnumerable OnExit { get; } = new CancelHandshakeInvocation().AsArray(); @@ -52,6 +50,7 @@ public override TransitionResult Transition(IEvent e) { Channels = disconnect.Channels, ChannelGroups = disconnect.ChannelGroups, + Cursor = disconnect.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration }.With(new EmitStatusInvocation(PNStatusCategory.PNDisconnectedCategory)), diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveFailedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveFailedState.cs index 9fb34c77f..e7718b597 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveFailedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveFailedState.cs @@ -9,8 +9,6 @@ namespace PubnubApi.EventEngine.Subscribe.States { public class ReceiveFailedState : SubscriptionState { - public SubscriptionCursor Cursor; - public override IEnumerable OnEntry { get; } public override IEnumerable OnExit { get; } diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs index 42652231f..fcbcbd6a9 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs @@ -9,11 +9,7 @@ namespace PubnubApi.EventEngine.Subscribe.States { public class ReceiveReconnectingState : SubscriptionState { - public IEnumerable Channels; - public IEnumerable ChannelGroups; - public SubscriptionCursor Cursor; - public ReconnectionConfiguration ReconnectionConfiguration; - public int AttemptedRetries; + public int AttemptedRetries { get; set;} public override IEnumerable OnEntry => new ReceiveReconnectInvocation() { diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveStoppedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveStoppedState.cs index 93c5236bd..e8ccb1795 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveStoppedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveStoppedState.cs @@ -9,8 +9,6 @@ namespace PubnubApi.EventEngine.Subscribe.States { public class ReceiveStoppedState : SubscriptionState { - public SubscriptionCursor Cursor; - public override TransitionResult Transition(IEvent e) { return e switch diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs index cdc2edcd7..3509c66f2 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs @@ -9,8 +9,6 @@ namespace PubnubApi.EventEngine.Subscribe.States { public class ReceivingState : SubscriptionState { - public SubscriptionCursor Cursor; - public override IEnumerable OnEntry => new ReceiveMessagesInvocation() { Channels = this.Channels,ChannelGroups = this.ChannelGroups, Cursor = this.Cursor }.AsArray(); diff --git a/src/Api/PubnubApi/Pubnub.cs b/src/Api/PubnubApi/Pubnub.cs index dbbbd2a27..b7181f148 100644 --- a/src/Api/PubnubApi/Pubnub.cs +++ b/src/Api/PubnubApi/Pubnub.cs @@ -5,6 +5,7 @@ using PubnubApi.EventEngine.Subscribe; using PubnubApi.EndPoint; using PubnubApi.EventEngine.Subscribe.Events; +using PubnubApi.EventEngine.Subscribe.Common; #if !NET35 && !NET40 using System.Collections.Concurrent; #endif @@ -64,9 +65,17 @@ public ISubscribeOperation Subscribe() public EndPoint.UnsubscribeOperation Unsubscribe() { - EndPoint.UnsubscribeOperation unsubscribeOperation = new EndPoint.UnsubscribeOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); - unsubscribeOperation.CurrentPubnubInstance(this); - return unsubscribeOperation; + if (pubnubConfig[InstanceId].EnableEventEngine) + { + //TODO: Add support for Unsubscribe in Event Engine + throw new NotImplementedException("Unsubscribe is not implemented for Event Engine"); + } + else + { + EndPoint.UnsubscribeOperation unsubscribeOperation = new EndPoint.UnsubscribeOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + unsubscribeOperation.CurrentPubnubInstance(this); + return unsubscribeOperation; + } } public EndPoint.UnsubscribeAllOperation UnsubscribeAll() @@ -539,12 +548,23 @@ public void SetAuthToken(string token) public bool Reconnect() { bool ret = false; - if (savedSubscribeOperation is EndPoint.SubscribeOperation) + if (pubnubConfig[InstanceId].EnableEventEngine) { - EndPoint.SubscribeOperation subscibeOperationInstance = savedSubscribeOperation as EndPoint.SubscribeOperation; - if (subscibeOperationInstance != null) + if (subscribeEventEngineFactory.hasEventEngine(InstanceId)) + { + var subscribeEventEngine = subscribeEventEngineFactory.getEventEngine(InstanceId); + subscribeEventEngine.EventQueue.Enqueue(new ReconnectEvent() { Channels = (subscribeEventEngine.CurrentState as SubscriptionState).Channels, ChannelGroups = (subscribeEventEngine.CurrentState as SubscriptionState).ChannelGroups, Cursor = (subscribeEventEngine.CurrentState as SubscriptionState).Cursor }); + } + } + else + { + if (savedSubscribeOperation is EndPoint.SubscribeOperation) { - ret = subscibeOperationInstance.Retry(true, false); + EndPoint.SubscribeOperation subscibeOperationInstance = savedSubscribeOperation as EndPoint.SubscribeOperation; + if (subscibeOperationInstance != null) + { + ret = subscibeOperationInstance.Retry(true, false); + } } } return ret; @@ -567,12 +587,23 @@ public bool Reconnect(bool resetSubscribeTimetoken) public bool Disconnect() { bool ret = false; - if (savedSubscribeOperation is EndPoint.SubscribeOperation) + if (pubnubConfig[InstanceId].EnableEventEngine) { - EndPoint.SubscribeOperation subscibeOperationInstance = savedSubscribeOperation as EndPoint.SubscribeOperation; - if (subscibeOperationInstance != null) + if (subscribeEventEngineFactory.hasEventEngine(InstanceId)) { - ret = subscibeOperationInstance.Retry(false); + var subscribeEventEngine = subscribeEventEngineFactory.getEventEngine(InstanceId); + subscribeEventEngine.EventQueue.Enqueue(new DisconnectEvent() { Channels = (subscribeEventEngine.CurrentState as SubscriptionState).Channels, ChannelGroups = (subscribeEventEngine.CurrentState as SubscriptionState).ChannelGroups }); + } + } + else + { + if (savedSubscribeOperation is EndPoint.SubscribeOperation) + { + EndPoint.SubscribeOperation subscibeOperationInstance = savedSubscribeOperation as EndPoint.SubscribeOperation; + if (subscibeOperationInstance != null) + { + ret = subscibeOperationInstance.Retry(false); + } } } return ret; From 4ecdb578c4a580eaf5462fd7ffcae2471c3e12e5 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Wed, 9 Aug 2023 21:51:48 +0530 Subject: [PATCH 40/56] Reconnect --- src/Api/PubnubApi/Pubnub.cs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Api/PubnubApi/Pubnub.cs b/src/Api/PubnubApi/Pubnub.cs index b7181f148..41a6499ad 100644 --- a/src/Api/PubnubApi/Pubnub.cs +++ b/src/Api/PubnubApi/Pubnub.cs @@ -573,12 +573,23 @@ public bool Reconnect() public bool Reconnect(bool resetSubscribeTimetoken) { bool ret = false; - if (savedSubscribeOperation is EndPoint.SubscribeOperation) + if (pubnubConfig[InstanceId].EnableEventEngine) { - EndPoint.SubscribeOperation subscibeOperationInstance = savedSubscribeOperation as EndPoint.SubscribeOperation; - if (subscibeOperationInstance != null) + if (subscribeEventEngineFactory.hasEventEngine(InstanceId)) { - ret = subscibeOperationInstance.Retry(true, resetSubscribeTimetoken); + var subscribeEventEngine = subscribeEventEngineFactory.getEventEngine(InstanceId); + subscribeEventEngine.EventQueue.Enqueue(new ReconnectEvent() { Channels = (subscribeEventEngine.CurrentState as SubscriptionState).Channels, ChannelGroups = (subscribeEventEngine.CurrentState as SubscriptionState).ChannelGroups, Cursor = resetSubscribeTimetoken ? null : (subscribeEventEngine.CurrentState as SubscriptionState).Cursor }); + } + } + else + { + if (savedSubscribeOperation is EndPoint.SubscribeOperation) + { + EndPoint.SubscribeOperation subscibeOperationInstance = savedSubscribeOperation as EndPoint.SubscribeOperation; + if (subscibeOperationInstance != null) + { + ret = subscibeOperationInstance.Retry(true, resetSubscribeTimetoken); + } } } return ret; From 748806a370b90b6926d9edc81885fbfa60e2999b Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Wed, 9 Aug 2023 22:16:09 +0530 Subject: [PATCH 41/56] unused code --- .../EndPoint/PubSub/SubscribeOperation2.cs | 41 ------------------- 1 file changed, 41 deletions(-) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs index faa27d0fb..32dabd7b3 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs @@ -677,7 +677,6 @@ private void SubscribeEventEngine_OnEffectDispatch(IEffectInvocation obj) private void SubscribeEventEngine_OnEventQueued(IEvent @event) { int attempts = 0; - SubscriptionCursor subscriptionCursor = null; if (subscribeEventEngine.CurrentState is HandshakeReconnectingState handshakeReconnectingState) { attempts = handshakeReconnectingState.AttemptedRetries; @@ -694,46 +693,6 @@ private void SubscribeEventEngine_OnStateTransition(EventEngine.Core.TransitionR LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnStateTransition : CurrentState = {subscribeEventEngine.CurrentState.GetType().Name} => Transition State = {obj?.State.GetType().Name}", config.LogVerbosity); } - internal bool Retry(bool reconnect) - { - return false; - //if (manager == null) - //{ - // return false; - //} - - //if (reconnect) - //{ - // return manager.Reconnect(false); - //} - //else - //{ - // return manager.Disconnect(); - //} - } - - internal bool Retry(bool reconnect, bool resetSubscribeTimetoken) - { - return false; - //if (manager == null) - //{ - // return false; - //} - - //if (reconnect) - //{ - // return manager.Reconnect(resetSubscribeTimetoken); - //} - //else - //{ - // return manager.Disconnect(); - //} - } - - internal void CurrentPubnubInstance(Pubnub instance) - { - PubnubInstance = instance; - } private void MessageEmitter(Pubnub pubnubInstance, PNMessageResult messageResult) { foreach (var listener in SubscribeListenerList) From 13ad8b494d63e905781cc181a2cb8ad1f2b3a9fb Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Wed, 9 Aug 2023 23:15:09 +0530 Subject: [PATCH 42/56] multi subscribes. add new channels to existing. --- .../EventEngine/Subscribe/States/HandshakeFailedState.cs | 5 +++-- .../Subscribe/States/HandshakeReconnectingState.cs | 5 +++-- .../EventEngine/Subscribe/States/HandshakeStoppedState.cs | 5 +++-- .../EventEngine/Subscribe/States/HandshakingState.cs | 5 +++-- .../EventEngine/Subscribe/States/ReceiveFailedState.cs | 5 +++-- .../EventEngine/Subscribe/States/ReceiveReconnectingState.cs | 5 +++-- .../EventEngine/Subscribe/States/ReceiveStoppedState.cs | 5 +++-- .../PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs | 5 +++-- .../EventEngine/Subscribe/States/UnsubscribedState.cs | 5 +++-- 9 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeFailedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeFailedState.cs index f01083e28..33d2c02c7 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeFailedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeFailedState.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; using PubnubApi.EventEngine.Subscribe.Context; @@ -20,8 +21,8 @@ public override TransitionResult Transition(IEvent e) Events.SubscriptionChangedEvent subscriptionChanged => new HandshakingState() { - Channels = subscriptionChanged.Channels, - ChannelGroups = subscriptionChanged.ChannelGroups, + Channels = (Channels ?? Enumerable.Empty()).Union(subscriptionChanged.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(subscriptionChanged.ChannelGroups), ReconnectionConfiguration = this.ReconnectionConfiguration }, diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs index 4853be3eb..cac50df4f 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; using PubnubApi.EventEngine.Subscribe.Context; @@ -31,8 +32,8 @@ public override TransitionResult Transition(IEvent e) Events.SubscriptionChangedEvent subscriptionChanged => new HandshakingState() { - Channels = subscriptionChanged.Channels, - ChannelGroups = subscriptionChanged.ChannelGroups, + Channels = (Channels ?? Enumerable.Empty()).Union(subscriptionChanged.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(subscriptionChanged.ChannelGroups), ReconnectionConfiguration = this.ReconnectionConfiguration }, diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeStoppedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeStoppedState.cs index db3455832..827a16f14 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeStoppedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeStoppedState.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; using PubnubApi.EventEngine.Subscribe.Context; @@ -20,8 +21,8 @@ public override TransitionResult Transition(IEvent e) Events.SubscriptionChangedEvent subscriptionChanged => new HandshakingState() { - Channels = subscriptionChanged.Channels, - ChannelGroups = subscriptionChanged.ChannelGroups, + Channels = (Channels ?? Enumerable.Empty()).Union(subscriptionChanged.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(subscriptionChanged.ChannelGroups), ReconnectionConfiguration = this.ReconnectionConfiguration }, diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs index 4e77a7956..a7d7a9941 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; using PubnubApi.EventEngine.Subscribe.Context; @@ -25,8 +26,8 @@ public override TransitionResult Transition(IEvent e) Events.SubscriptionChangedEvent subscriptionChanged => new States.HandshakingState() { - Channels = subscriptionChanged.Channels, - ChannelGroups = subscriptionChanged.ChannelGroups, + Channels = (Channels ?? Enumerable.Empty()).Union(subscriptionChanged.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(subscriptionChanged.ChannelGroups), ReconnectionConfiguration = this.ReconnectionConfiguration }, diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveFailedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveFailedState.cs index e7718b597..53ee6560d 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveFailedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveFailedState.cs @@ -4,6 +4,7 @@ using PubnubApi.EventEngine.Subscribe.Invocations; using PubnubApi.EventEngine.Subscribe.Common; using PubnubApi.EventEngine.Subscribe.Context; +using System.Linq; namespace PubnubApi.EventEngine.Subscribe.States { @@ -23,8 +24,8 @@ public override TransitionResult Transition(IEvent e) Events.SubscriptionChangedEvent subscriptionChanged => new HandshakingState() { - Channels = subscriptionChanged.Channels, - ChannelGroups = subscriptionChanged.ChannelGroups, + Channels = (Channels ?? Enumerable.Empty()).Union(subscriptionChanged.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(subscriptionChanged.ChannelGroups), Cursor = this.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration }, diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs index fcbcbd6a9..b0c7ba8c3 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs @@ -4,6 +4,7 @@ using PubnubApi.EventEngine.Subscribe.Invocations; using PubnubApi.EventEngine.Subscribe.Common; using PubnubApi.EventEngine.Subscribe.Context; +using System.Linq; namespace PubnubApi.EventEngine.Subscribe.States { @@ -34,8 +35,8 @@ public override TransitionResult Transition(IEvent e) Events.SubscriptionChangedEvent subscriptionChanged => new ReceivingState() { - Channels = subscriptionChanged.Channels, - ChannelGroups = subscriptionChanged.ChannelGroups, + Channels = (Channels ?? Enumerable.Empty()).Union(subscriptionChanged.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(subscriptionChanged.ChannelGroups), Cursor = this.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration }, diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveStoppedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveStoppedState.cs index e8ccb1795..23c1428f2 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveStoppedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveStoppedState.cs @@ -4,6 +4,7 @@ using PubnubApi.EventEngine.Subscribe.Invocations; using PubnubApi.EventEngine.Subscribe.Common; using PubnubApi.EventEngine.Subscribe.Context; +using System.Linq; namespace PubnubApi.EventEngine.Subscribe.States { @@ -20,8 +21,8 @@ public override TransitionResult Transition(IEvent e) Events.SubscriptionChangedEvent subscriptionChanged => new ReceiveStoppedState() { - Channels = subscriptionChanged.Channels, - ChannelGroups = subscriptionChanged.ChannelGroups, + Channels = (Channels ?? Enumerable.Empty()).Union(subscriptionChanged.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(subscriptionChanged.ChannelGroups), Cursor = this.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration }, diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs index 3509c66f2..217718dbe 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs @@ -4,6 +4,7 @@ using PubnubApi.EventEngine.Subscribe.Invocations; using PubnubApi.EventEngine.Subscribe.Common; using PubnubApi.EventEngine.Subscribe.Context; +using System.Linq; namespace PubnubApi.EventEngine.Subscribe.States { @@ -36,8 +37,8 @@ public override TransitionResult Transition(IEvent e) Events.SubscriptionChangedEvent subscriptionChanged => new ReceivingState() { - Channels = subscriptionChanged.Channels, - ChannelGroups = subscriptionChanged.ChannelGroups, + Channels = (Channels ?? Enumerable.Empty()).Union(subscriptionChanged.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(subscriptionChanged.ChannelGroups), Cursor = this.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration }, diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs index c141e44d9..4338e7adc 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; using PubnubApi.EventEngine.Subscribe.Context; @@ -15,8 +16,8 @@ public override TransitionResult Transition(Core.IEvent e) { Events.SubscriptionChangedEvent subscriptionChanged => new HandshakingState() { - Channels = subscriptionChanged.Channels, - ChannelGroups = subscriptionChanged.ChannelGroups, + Channels = (Channels ?? Enumerable.Empty()).Union(subscriptionChanged.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(subscriptionChanged.ChannelGroups), ReconnectionConfiguration = this.ReconnectionConfiguration }, From 35de95e19de305ada8806bddeed4be476ba4a958 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Fri, 18 Aug 2023 22:24:49 +0530 Subject: [PATCH 43/56] SubscribeEndpoint and UnsubscribeEndpoint --- ...ribeOperation2.cs => SubscribeEndpoint.cs} | 14 +-- .../EndPoint/PubSub/UnsubscribeEndpoint.cs | 87 +++++++++++++++++++ .../EndPoint/PubSub/UnsubscribeOperation.cs | 9 +- .../Subscribe/SubscribeEventEngineFactory.cs | 16 ++-- .../Interface/IUnsubscribeOperation.cs | 15 ++++ src/Api/PubnubApi/Pubnub.cs | 21 ++--- src/Api/PubnubApiPCL/PubnubApiPCL.csproj | 4 +- src/Api/PubnubApiUWP/PubnubApiUWP.csproj | 10 ++- 8 files changed, 144 insertions(+), 32 deletions(-) rename src/Api/PubnubApi/EndPoint/PubSub/{SubscribeOperation2.cs => SubscribeEndpoint.cs} (98%) create mode 100644 src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeEndpoint.cs create mode 100644 src/Api/PubnubApi/Interface/IUnsubscribeOperation.cs diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs similarity index 98% rename from src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs rename to src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs index 32dabd7b3..f5578b9c7 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation2.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs @@ -15,7 +15,7 @@ namespace PubnubApi.EndPoint { - public class SubscribeOperation2: ISubscribeOperation + public class SubscribeEndpoint: ISubscribeOperation { private readonly PNConfiguration config; private readonly IJsonPluggableLibrary jsonLibrary; @@ -32,15 +32,15 @@ public class SubscribeOperation2: ISubscribeOperation private Dictionary queryParam; private Pubnub PubnubInstance; private SubscribeEventEngine subscribeEventEngine; - public SubscribeEventEngineFactory subscribeEventEngineFactory; - public string instanceId; + private SubscribeEventEngineFactory subscribeEventEngineFactory { get; set; } + private string instanceId { get; set; } public List SubscribeListenerList { get; set; } = new List(); - public SubscribeOperation2(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager,SubscribeEventEngineFactory subscribeEventEngineFactory, string instanceId, Pubnub instance) + public SubscribeEndpoint(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager,SubscribeEventEngineFactory subscribeEventEngineFactory, string instanceId, Pubnub instance) { PubnubInstance = instance; config = pubnubConfig; @@ -654,14 +654,14 @@ private void Subscribe(string[] channels, string[] channelGroups, Dictionary : IUnsubscribeOperation + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; + private readonly EndPoint.TokenManager pubnubTokenMgr; + + private string[] subscribeChannelNames; + private string[] subscribeChannelGroupNames; + private Dictionary queryParam{ get; set; } + private Pubnub pubnubInstance{ get; set; } + private SubscribeEventEngine subscribeEventEngine { get; set; } + private SubscribeEventEngineFactory subscribeEventEngineFactory { get; set; } + private string instanceId { get; set; } + + public UnsubscribeEndpoint(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, SubscribeEventEngineFactory subscribeEventEngineFactory, Pubnub instance) + { + pubnubInstance = instance; + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + pubnubTelemetryMgr = telemetryManager; + pubnubTokenMgr = tokenManager; + instanceId = instance.InstanceId; + } + + public IUnsubscribeOperation Channels(string[] channels) + { + this.subscribeChannelNames = channels; + return this; + } + + public IUnsubscribeOperation ChannelGroups(string[] channelGroups) + { + this.subscribeChannelGroupNames = channelGroups; + return this; + } + + public IUnsubscribeOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute() + { + Unsubscribe(subscribeChannelNames, subscribeChannelGroupNames); + } + + private void Unsubscribe(string[] channels, string[] channelGroups) + { + if ((channels == null || channels.Length == 0) && (channelGroups == null || channelGroups.Length == 0)) + { + throw new ArgumentException("Either Channel Or Channel Group or Both should be provided."); + } + + string channel = (channels != null) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ""; + string channelGroup = (channelGroups != null) ? string.Join(",", channelGroups.OrderBy(x => x).ToArray()) : ""; + + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, requested unsubscribe for channel(s)={1}, cg(s)={2}", DateTime.Now.ToString(CultureInfo.InvariantCulture), channel, channelGroup), config.LogVerbosity); + + if (this.subscribeEventEngineFactory.HasEventEngine(instanceId)) + { + subscribeEventEngine = subscribeEventEngineFactory.GetEventEngine(instanceId); + subscribeEventEngine.Unsubscribe(channels, channelGroups); + } + else + { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, Attempted Unsubscribe without EventEngine subscribe."), config.LogVerbosity); + } + } + } +} diff --git a/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeOperation.cs b/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeOperation.cs index cb2c92594..5a6bc45ba 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeOperation.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeOperation.cs @@ -5,13 +5,14 @@ using System.Net; using System.Threading; using System.Threading.Tasks; +using PubnubApi.Interface; #if !NET35 && !NET40 using System.Collections.Concurrent; #endif namespace PubnubApi.EndPoint { - public class UnsubscribeOperation : PubnubCoreBase + public class UnsubscribeOperation : PubnubCoreBase, IUnsubscribeOperation { private readonly PNConfiguration config; private readonly IJsonPluggableLibrary jsonLibrary; @@ -34,19 +35,19 @@ public UnsubscribeOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary pubnubTokenMgr = tokenManager; } - public UnsubscribeOperation Channels(string[] channels) + public IUnsubscribeOperation Channels(string[] channels) { this.subscribeChannelNames = channels; return this; } - public UnsubscribeOperation ChannelGroups(string[] channelGroups) + public IUnsubscribeOperation ChannelGroups(string[] channelGroups) { this.subscribeChannelGroupNames = channelGroups; return this; } - public UnsubscribeOperation QueryParam(Dictionary customQueryParam) + public IUnsubscribeOperation QueryParam(Dictionary customQueryParam) { this.queryParam = customQueryParam; return this; diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngineFactory.cs b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngineFactory.cs index c8d48c09c..ae2a5ad20 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngineFactory.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngineFactory.cs @@ -6,23 +6,23 @@ namespace PubnubApi.EventEngine.Subscribe { public class SubscribeEventEngineFactory { - private ConcurrentDictionary engineinstances; + private ConcurrentDictionary engineInstances { get; set;} internal SubscribeEventEngineFactory() { - this.engineinstances = new ConcurrentDictionary(); + this.engineInstances = new ConcurrentDictionary(); } - internal bool hasEventEngine(string instanceId) + internal bool HasEventEngine(string instanceId) { - return engineinstances.ContainsKey(instanceId); + return engineInstances.ContainsKey(instanceId); } - internal SubscribeEventEngine getEventEngine(string instanceId) + internal SubscribeEventEngine GetEventEngine(string instanceId) { SubscribeEventEngine subscribeEventEngine; - engineinstances.TryGetValue(instanceId, out subscribeEventEngine); + engineInstances.TryGetValue(instanceId, out subscribeEventEngine); return subscribeEventEngine; } - internal SubscribeEventEngine initializeEventEngine(string instanceId, + internal SubscribeEventEngine InitializeEventEngine(string instanceId, Pubnub pubnubInstance, PNConfiguration pubnubConfiguration, SubscribeManager2 subscribeManager, @@ -30,7 +30,7 @@ internal SubscribeEventEngine initializeEventEngine(string instanceId, Action> messageListener= null) { var subscribeEventEngine = new SubscribeEventEngine(pubnubInstance, pubnubConfiguration: pubnubConfiguration, subscribeManager,statusListener, messageListener); - if (engineinstances.TryAdd(instanceId, subscribeEventEngine)) { + if (engineInstances.TryAdd(instanceId, subscribeEventEngine)) { return subscribeEventEngine; } else { diff --git a/src/Api/PubnubApi/Interface/IUnsubscribeOperation.cs b/src/Api/PubnubApi/Interface/IUnsubscribeOperation.cs new file mode 100644 index 000000000..5693a129e --- /dev/null +++ b/src/Api/PubnubApi/Interface/IUnsubscribeOperation.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PubnubApi.Interface +{ + public interface IUnsubscribeOperation + { + IUnsubscribeOperation Channels(string[] channels); + IUnsubscribeOperation ChannelGroups(string[] channelGroups); + IUnsubscribeOperation QueryParam(Dictionary customQueryParam); + void Execute(); + } +} diff --git a/src/Api/PubnubApi/Pubnub.cs b/src/Api/PubnubApi/Pubnub.cs index 41a6499ad..f79dbb18a 100644 --- a/src/Api/PubnubApi/Pubnub.cs +++ b/src/Api/PubnubApi/Pubnub.cs @@ -6,6 +6,7 @@ using PubnubApi.EndPoint; using PubnubApi.EventEngine.Subscribe.Events; using PubnubApi.EventEngine.Subscribe.Common; +using PubnubApi.Interface; #if !NET35 && !NET40 using System.Collections.Concurrent; #endif @@ -47,7 +48,7 @@ public ISubscribeOperation Subscribe() { if (pubnubConfig[InstanceId].EnableEventEngine) { - EndPoint.SubscribeOperation2 subscribeOperation = new EndPoint.SubscribeOperation2(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, null, tokenManager, this.subscribeEventEngineFactory,InstanceId ,this); + EndPoint.SubscribeEndpoint subscribeOperation = new EndPoint.SubscribeEndpoint(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, null, tokenManager, this.subscribeEventEngineFactory,InstanceId ,this); subscribeOperation.SubscribeListenerList = subscribeCallbackListenerList; //subscribeOperation.CurrentPubnubInstance(this); @@ -63,12 +64,12 @@ public ISubscribeOperation Subscribe() } } - public EndPoint.UnsubscribeOperation Unsubscribe() + public IUnsubscribeOperation Unsubscribe() { if (pubnubConfig[InstanceId].EnableEventEngine) { - //TODO: Add support for Unsubscribe in Event Engine - throw new NotImplementedException("Unsubscribe is not implemented for Event Engine"); + EndPoint.UnsubscribeEndpoint unsubscribeOperation = new EndPoint.UnsubscribeEndpoint(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, subscribeEventEngineFactory, this); + return unsubscribeOperation; } else { @@ -550,9 +551,9 @@ public bool Reconnect() bool ret = false; if (pubnubConfig[InstanceId].EnableEventEngine) { - if (subscribeEventEngineFactory.hasEventEngine(InstanceId)) + if (subscribeEventEngineFactory.HasEventEngine(InstanceId)) { - var subscribeEventEngine = subscribeEventEngineFactory.getEventEngine(InstanceId); + var subscribeEventEngine = subscribeEventEngineFactory.GetEventEngine(InstanceId); subscribeEventEngine.EventQueue.Enqueue(new ReconnectEvent() { Channels = (subscribeEventEngine.CurrentState as SubscriptionState).Channels, ChannelGroups = (subscribeEventEngine.CurrentState as SubscriptionState).ChannelGroups, Cursor = (subscribeEventEngine.CurrentState as SubscriptionState).Cursor }); } } @@ -575,9 +576,9 @@ public bool Reconnect(bool resetSubscribeTimetoken) bool ret = false; if (pubnubConfig[InstanceId].EnableEventEngine) { - if (subscribeEventEngineFactory.hasEventEngine(InstanceId)) + if (subscribeEventEngineFactory.HasEventEngine(InstanceId)) { - var subscribeEventEngine = subscribeEventEngineFactory.getEventEngine(InstanceId); + var subscribeEventEngine = subscribeEventEngineFactory.GetEventEngine(InstanceId); subscribeEventEngine.EventQueue.Enqueue(new ReconnectEvent() { Channels = (subscribeEventEngine.CurrentState as SubscriptionState).Channels, ChannelGroups = (subscribeEventEngine.CurrentState as SubscriptionState).ChannelGroups, Cursor = resetSubscribeTimetoken ? null : (subscribeEventEngine.CurrentState as SubscriptionState).Cursor }); } } @@ -600,9 +601,9 @@ public bool Disconnect() bool ret = false; if (pubnubConfig[InstanceId].EnableEventEngine) { - if (subscribeEventEngineFactory.hasEventEngine(InstanceId)) + if (subscribeEventEngineFactory.HasEventEngine(InstanceId)) { - var subscribeEventEngine = subscribeEventEngineFactory.getEventEngine(InstanceId); + var subscribeEventEngine = subscribeEventEngineFactory.GetEventEngine(InstanceId); subscribeEventEngine.EventQueue.Enqueue(new DisconnectEvent() { Channels = (subscribeEventEngine.CurrentState as SubscriptionState).Channels, ChannelGroups = (subscribeEventEngine.CurrentState as SubscriptionState).ChannelGroups }); } } diff --git a/src/Api/PubnubApiPCL/PubnubApiPCL.csproj b/src/Api/PubnubApiPCL/PubnubApiPCL.csproj index 14d535957..fbe8574ee 100644 --- a/src/Api/PubnubApiPCL/PubnubApiPCL.csproj +++ b/src/Api/PubnubApiPCL/PubnubApiPCL.csproj @@ -146,6 +146,7 @@ + EndPoint\PubSub\SubscribeManager.cs @@ -153,10 +154,10 @@ EndPoint\PubSub\SubscribeOperation.cs - EndPoint\PubSub\UnsubscribeAllOperation.cs + EndPoint\PubSub\UnsubscribeOperation.cs @@ -262,6 +263,7 @@ Interface\IPubnubUnitTest.cs + Interface\IUrlRequestBuilder.cs diff --git a/src/Api/PubnubApiUWP/PubnubApiUWP.csproj b/src/Api/PubnubApiUWP/PubnubApiUWP.csproj index f3e3d01ad..6b64e24a4 100644 --- a/src/Api/PubnubApiUWP/PubnubApiUWP.csproj +++ b/src/Api/PubnubApiUWP/PubnubApiUWP.csproj @@ -268,8 +268,8 @@ EndPoint\PubSub\SubscribeOperation.cs - - EndPoint\PubSub\SubscribeOperation2.cs + + EndPoint\PubSub\SubscribeEndpoint.cs EndPoint\PubSub\UnsubscribeAllOperation.cs @@ -277,6 +277,9 @@ EndPoint\PubSub\UnsubscribeOperation.cs + + EndPoint\PubSub\UnsubscribeEndpoint.cs + EndPoint\Push\AddPushChannelOperation.cs @@ -375,6 +378,9 @@ Interface\ISubscribeOperation.cs + + Interface\IUnsubscribeOperation.cs + Interface\IPubnubLog.cs From a41c6ee1ce1bf2864d3638d94844452f38136466 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Fri, 18 Aug 2023 23:05:15 +0530 Subject: [PATCH 44/56] Added ee param for EE --- src/Api/PubnubApi/Builder/UrlRequestBuilder.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Api/PubnubApi/Builder/UrlRequestBuilder.cs b/src/Api/PubnubApi/Builder/UrlRequestBuilder.cs index 135ec60c7..372f620a7 100644 --- a/src/Api/PubnubApi/Builder/UrlRequestBuilder.cs +++ b/src/Api/PubnubApi/Builder/UrlRequestBuilder.cs @@ -85,6 +85,11 @@ Uri IUrlRequestBuilder.BuildMultiChannelSubscribeRequest(string requestMethod, s requestQueryStringParams.Add("filter-expr", UriUtil.EncodeUriComponent(pubnubConfig[pubnubInstanceId].FilterExpression, currentType, false, false, false)); } + if (!requestQueryStringParams.ContainsKey("ee") && pubnubConfig.ContainsKey(pubnubInstanceId) && pubnubConfig[pubnubInstanceId].EnableEventEngine) + { + requestQueryStringParams.Add("ee", "1"); + } + if (!requestQueryStringParams.ContainsKey("tt")) { requestQueryStringParams.Add("tt", timetoken.ToString(CultureInfo.InvariantCulture)); From 49c7846bc103c4e324f38f832abb130b2463ea5d Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Mon, 21 Aug 2023 17:34:19 +0530 Subject: [PATCH 45/56] Added Name to IEvent and IEffectInvocation --- .../EndPoint/PubSub/SubscribeEndpoint.cs | 525 +----------------- .../EventEngine/Core/EventEngineInterfaces.cs | 2 + .../Subscribe/Events/SubscriptionEvents.cs | 22 +- .../Invocations/SubscriptionInvocations.cs | 14 +- 4 files changed, 32 insertions(+), 531 deletions(-) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs index f5578b9c7..a353cd7ce 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs @@ -51,528 +51,7 @@ public SubscribeEndpoint(PNConfiguration pubnubConfig, IJsonPluggableLibrary jso pubnubTokenMgr = tokenManager; this.subscribeEventEngineFactory = subscribeEventEngineFactory; this.instanceId = instanceId; - - } - - protected void ProcessListenerCallback(List result, bool zeroTimeTokenRequest, int messageCount, string[] channels, string[] channelGroups) - { - bool callbackAvailable = false; - if (result != null && result.Count >= 1 && SubscribeListenerList.Count >= 1) - { - callbackAvailable = true; - } - if (callbackAvailable) - { - if (zeroTimeTokenRequest) - { - ResponseToConnectCallback(PNOperationType.PNSubscribeOperation, channels, channelGroups); - } - else if (messageCount > 0) - { - ResponseToUserCallback(result, PNOperationType.PNSubscribeOperation); - } - } - } - - private void ResponseToConnectCallback(PNOperationType type, string[] channels, string[] channelGroups) - { - StatusBuilder statusBuilder = new StatusBuilder(config, jsonLibrary); - PNStatus status = statusBuilder.CreateStatusResponse(type, PNStatusCategory.PNConnectedCategory, null, (int)HttpStatusCode.OK, null); - - Announce(status); - } - - internal void Announce(PNStatus status) - { - List callbackList = SubscribeListenerList; - for (int listenerIndex = 0; listenerIndex < callbackList.Count; listenerIndex++) - { - callbackList[listenerIndex].Status(PubnubInstance, status); - } - } - - internal void Announce(PNMessageResult message) - { - List callbackList = SubscribeListenerList; - for (int listenerIndex = 0; listenerIndex < callbackList.Count; listenerIndex++) - { - callbackList[listenerIndex].Message(PubnubInstance, message); - } - } - - internal void Announce(PNSignalResult message) - { - List callbackList = SubscribeListenerList; - for (int listenerIndex = 0; listenerIndex < callbackList.Count; listenerIndex++) - { - callbackList[listenerIndex].Signal(PubnubInstance, message); - } - } - - internal void Announce(PNFileEventResult message) - { - List callbackList = SubscribeListenerList; - for (int listenerIndex = 0; listenerIndex < callbackList.Count; listenerIndex++) - { - callbackList[listenerIndex].File(PubnubInstance, message); - } - } - - internal void Announce(PNPresenceEventResult presence) - { - List callbackList = SubscribeListenerList; - for (int listenerIndex = 0; listenerIndex < callbackList.Count; listenerIndex++) - { - callbackList[listenerIndex].Presence(PubnubInstance, presence); - } - } - - internal void Announce(PNObjectEventResult objectApiEvent) - { - List callbackList = SubscribeListenerList; - for (int listenerIndex = 0; listenerIndex < callbackList.Count; listenerIndex++) - { - callbackList[listenerIndex].ObjectEvent(PubnubInstance, objectApiEvent); - } - } - - internal void Announce(PNMessageActionEventResult messageActionEvent) - { - List callbackList = SubscribeListenerList; - for (int listenerIndex = 0; listenerIndex < callbackList.Count; listenerIndex++) - { - callbackList[listenerIndex].MessageAction(PubnubInstance, messageActionEvent); - } - } - - private void ResponseToUserCallback(List result, PNOperationType type) - { - IPubnubLog currentLog = null; - try - { - switch (type) - { - case PNOperationType.PNSubscribeOperation: - case PNOperationType.Presence: - List messageList = GetMessageFromMultiplexResult(result); - if (messageList != null && messageList.Count > 0) - { - if (messageList.Count >= config.RequestMessageCountThreshold) - { - StatusBuilder statusBuilder = new StatusBuilder(config, jsonLibrary); - PNStatus status = statusBuilder.CreateStatusResponse(type, PNStatusCategory.PNRequestMessageCountExceededCategory, null, (int)HttpStatusCode.OK, null); - Announce(status); - } - - if (config != null && currentLog != null) - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, ResponseToUserCallback - messageList.Count = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), messageList.Count), config.LogVerbosity); - } - for (int messageIndex = 0; messageIndex < messageList.Count; messageIndex++) - { - SubscribeMessage currentMessage = messageList[messageIndex]; - if (currentMessage != null) - { - if (config != null && currentLog != null && config.DedupOnSubscribe && IsTargetForDedup(currentMessage)) - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, ResponseToUserCallback - messageList for loop - messageIndex = {1} => IsTargetForDedup", DateTime.Now.ToString(CultureInfo.InvariantCulture), messageIndex), config.LogVerbosity); - continue; - } - - string currentMessageChannel = currentMessage.Channel; - string currentMessageChannelGroup = currentMessage.SubscriptionMatch; - - if (currentMessageChannel.Replace("-pnpres", "") == currentMessageChannelGroup.Replace("-pnpres", "")) - { - currentMessageChannelGroup = ""; - } - - object payload = currentMessage.Payload; - - List payloadContainer = new List(); //First item always message - if (currentMessageChannel.Contains("-pnpres") || currentMessageChannel.Contains(".*-pnpres")) - { - payloadContainer.Add(payload); - } - else if (currentMessage.MessageType == 2) //Objects Simplification events - { - double objectsVersion = -1; - Dictionary objectsDic = payload as Dictionary; - if (objectsDic != null - && objectsDic.ContainsKey("source") && objectsDic.ContainsKey("version") - && objectsDic["source"].ToString() == "objects" && Double.TryParse(objectsDic["version"].ToString(), out objectsVersion)) - { - if (objectsVersion.CompareTo(2D) == 0) //Process only version=2 for Objects Simplification. Ignore 1. - { - payloadContainer.Add(payload); - } - else - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, ResponseToUserCallback - Legacy Objects V1. Ignoring this.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); - continue; - } - } - else - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, ResponseToUserCallback - MessageType =2 but NOT valid format to process", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); - continue; - } - } - else - { - if (config.CipherKey.Length > 0 && currentMessage.MessageType != 1) //decrypt the subscriber message if cipherkey is available - { - string decryptMessage = ""; - PubnubCrypto aes = new PubnubCrypto(config.CipherKey, config, currentLog, null); - try - { - decryptMessage = aes.Decrypt(payload.ToString()); - } - catch (Exception ex) - { - decryptMessage = "**DECRYPT ERROR**"; - - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(ex); - PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, category, null, (int)HttpStatusCode.NotFound, new PNException(ex)); - if (!string.IsNullOrEmpty(currentMessageChannel)) - { - status.AffectedChannels.Add(currentMessageChannel); - status.AffectedChannels = status.AffectedChannels.Distinct().ToList(); - } - if (!string.IsNullOrEmpty(currentMessageChannelGroup)) - { - status.AffectedChannelGroups.Add(currentMessageChannelGroup); - status.AffectedChannelGroups = status.AffectedChannelGroups.Distinct().ToList(); - } - - Announce(status); - } - object decodeMessage = (decryptMessage == "**DECRYPT ERROR**") ? decryptMessage : jsonLibrary.DeserializeToObject(decryptMessage); - - payloadContainer.Add(decodeMessage); - } - else - { - string payloadJson = jsonLibrary.SerializeToJsonString(payload); - object payloadJObject = jsonLibrary.BuildJsonObject(payloadJson); - if (payloadJObject == null) - { - payloadContainer.Add(payload); - } - else - { - payloadContainer.Add(payloadJObject); - } - } - } - - object userMetaData = currentMessage.UserMetadata; - - payloadContainer.Add(userMetaData); //Second one always user meta data - - payloadContainer.Add(currentMessage.PublishTimetokenMetadata.Timetoken); //Third one always Timetoken - - payloadContainer.Add(currentMessage.IssuingClientId); //Fourth one always Publisher - - if (!string.IsNullOrEmpty(currentMessageChannelGroup)) //Add cg first before channel - { - payloadContainer.Add(currentMessageChannelGroup); - } - - if (!string.IsNullOrEmpty(currentMessageChannel)) - { - payloadContainer.Add(currentMessageChannel); - } - - if (currentMessage.MessageType == 1) - { - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, currentLog); - PNMessageResult pnMessageResult = responseBuilder.JsonToObject>(payloadContainer, true); - if (pnMessageResult != null) - { - PNSignalResult signalMessage = new PNSignalResult - { - Channel = pnMessageResult.Channel, - Message = pnMessageResult.Message, - Subscription = pnMessageResult.Subscription, - Timetoken = pnMessageResult.Timetoken, - UserMetadata = pnMessageResult.UserMetadata, - Publisher = pnMessageResult.Publisher - }; - Announce(signalMessage); - } - } - else if (currentMessage.MessageType == 2) - { - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, currentLog); - PNObjectEventResult objectApiEvent = responseBuilder.JsonToObject(payloadContainer, true); - if (objectApiEvent != null) - { - Announce(objectApiEvent); - } - } - else if (currentMessage.MessageType == 3) - { - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, currentLog); - PNMessageActionEventResult msgActionEventEvent = responseBuilder.JsonToObject(payloadContainer, true); - if (msgActionEventEvent != null) - { - Announce(msgActionEventEvent); - } - } - else if (currentMessage.MessageType == 4) - { - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, currentLog); - PNMessageResult pnFileResult = responseBuilder.JsonToObject>(payloadContainer, true); - if (pnFileResult != null) - { - PNFileEventResult fileMessage = new PNFileEventResult - { - Channel = pnFileResult.Channel, - Subscription = pnFileResult.Subscription, - Timetoken = pnFileResult.Timetoken, - Publisher = pnFileResult.Publisher, - }; - Dictionary pnMsgObjDic = JsonDataParseInternalUtil.ConvertToDictionaryObject(pnFileResult.Message); - if (pnMsgObjDic != null && pnMsgObjDic.Count > 0) - { - if (pnMsgObjDic.ContainsKey("message") && pnMsgObjDic["message"] != null) - { - fileMessage.Message = pnMsgObjDic["message"]; - } - if (pnMsgObjDic.ContainsKey("file")) - { - Dictionary fileObjDic = JsonDataParseInternalUtil.ConvertToDictionaryObject(pnMsgObjDic["file"]); - if (fileObjDic != null && fileObjDic.ContainsKey("id") && fileObjDic.ContainsKey("name")) - { - fileMessage.File = new PNFile { Id = fileObjDic["id"].ToString(), Name = fileObjDic["name"].ToString() }; - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, currentLog, pubnubTelemetryMgr, pubnubTokenMgr, PubnubInstance.InstanceId); - Uri fileUrlRequest = urlBuilder.BuildGetFileUrlOrDeleteReqest("GET", "", fileMessage.Channel, fileMessage.File.Id, fileMessage.File.Name, null, type); - fileMessage.File.Url = fileUrlRequest.ToString(); - } - } - } - else - { - if (pnFileResult.Message != null) - { - fileMessage.Message = pnFileResult.Message; - } - } - Announce(fileMessage); - } - } - else if (currentMessageChannel.Contains("-pnpres")) - { - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, currentLog); - PNPresenceEventResult presenceEvent = responseBuilder.JsonToObject(payloadContainer, true); - if (presenceEvent != null) - { - Announce(presenceEvent); - } - } - else - { - if (config != null && currentLog != null) - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, ResponseToUserCallback - payload = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), jsonLibrary.SerializeToJsonString(payloadContainer)), config.LogVerbosity); - } - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, currentLog); - PNMessageResult userMessage = responseBuilder.JsonToObject>(payloadContainer, true); - if (userMessage != null) - { - Announce(userMessage); - } - } - - } - else - { - if (config != null && currentLog != null) - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, ResponseToUserCallback - messageList for loop - messageIndex = {1} => null message", DateTime.Now.ToString(CultureInfo.InvariantCulture), messageIndex), config.LogVerbosity); - } - } - } - - } - break; - case PNOperationType.PNHeartbeatOperation: - break; - default: - break; - } - } - catch (Exception ex) - { - if (config != null && currentLog != null) - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, ResponseToUserCallback - Exception = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex), config.LogVerbosity); - } - } - } - - private bool IsTargetForDedup(SubscribeMessage message) - { - bool isTargetOfDedup = false; - PNConfiguration currentConfig; - IPubnubLog currentLog; - try - { - //if (pubnubSubscribeDuplicationManager.IsDuplicate(message)) - //{ - // isTargetOfDedup = true; - // if (pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig) && pubnubLog.TryGetValue(PubnubInstance.InstanceId, out currentLog)) - // { - // LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, Dedupe - Duplicate skipped - msg = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), jsonLib.SerializeToJsonString(message)), currentConfig.LogVerbosity); - // } - //} - //else - //{ - // if (pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig) && pubnubLog.TryGetValue(PubnubInstance.InstanceId, out currentLog)) - // { - // LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, Dedupe - AddEntry - msg = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), jsonLib.SerializeToJsonString(message)), currentConfig.LogVerbosity); - // } - // pubnubSubscribeDuplicationManager.AddEntry(message); - //} - } - catch (Exception ex) - { - //Log and ignore any exception due to Dedupe manager - //if (pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig) && pubnubLog.TryGetValue(PubnubInstance.InstanceId, out currentLog)) - //{ - // LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, IsTargetForDedup - dedupe error = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex), currentConfig.LogVerbosity); - //} - } - - return isTargetOfDedup; - } - - private List GetMessageFromMultiplexResult(List result) - { - List jsonMessageList = null; - List msgList = new List(); - - Dictionary messageDicObj = jsonLibrary.ConvertToDictionaryObject(result[1]); - if (messageDicObj != null && messageDicObj.Count > 0 && messageDicObj.ContainsKey("m")) - { - jsonMessageList = messageDicObj["m"] as List; - } - else - { - messageDicObj = jsonLibrary.ConvertToDictionaryObject(result[0]); - if (messageDicObj != null && messageDicObj.Count > 0 && messageDicObj.ContainsKey("m")) - { - jsonMessageList = messageDicObj["m"] as List; - } - } - - if (jsonMessageList != null && jsonMessageList.Count > 0) - { - foreach (Dictionary dicItem in jsonMessageList) - { - if (dicItem.Count > 0) - { - SubscribeMessage msg = new SubscribeMessage(); - foreach (string key in dicItem.Keys) - { - switch (key.ToLowerInvariant()) - { - case "a": - msg.Shard = dicItem[key].ToString(); - break; - case "b": - msg.SubscriptionMatch = dicItem[key].ToString(); - break; - case "c": - msg.Channel = dicItem[key].ToString(); - break; - case "d": - msg.Payload = dicItem[key]; - break; - case "e": - int subscriptionTypeIndicator; - var _ = Int32.TryParse(dicItem[key].ToString(), out subscriptionTypeIndicator); - msg.MessageType = subscriptionTypeIndicator; - break; - case "f": - msg.Flags = dicItem[key].ToString(); - break; - case "i": - msg.IssuingClientId = dicItem[key].ToString(); - break; - case "k": - msg.SubscribeKey = dicItem[key].ToString(); - break; - case "s": - int seqNum; - _ = Int32.TryParse(dicItem[key].ToString(), out seqNum); - msg.SequenceNumber = seqNum; - break; - case "o": - Dictionary ttOriginMetaData = jsonLibrary.ConvertToDictionaryObject(dicItem[key]); - if (ttOriginMetaData != null && ttOriginMetaData.Count > 0) - { - TimetokenMetadata ttMeta = new TimetokenMetadata(); - - foreach (string metaKey in ttOriginMetaData.Keys) - { - if (metaKey.ToLowerInvariant().Equals("t", StringComparison.OrdinalIgnoreCase)) - { - long timetoken; - _ = Int64.TryParse(ttOriginMetaData[metaKey].ToString(), out timetoken); - ttMeta.Timetoken = timetoken; - } - else if (metaKey.ToLowerInvariant().Equals("r", StringComparison.OrdinalIgnoreCase)) - { - ttMeta.Region = ttOriginMetaData[metaKey].ToString(); - } - } - msg.OriginatingTimetoken = ttMeta; - } - break; - case "p": - Dictionary ttPublishMetaData = jsonLibrary.ConvertToDictionaryObject(dicItem[key]); - if (ttPublishMetaData != null && ttPublishMetaData.Count > 0) - { - TimetokenMetadata ttMeta = new TimetokenMetadata(); - - foreach (string metaKey in ttPublishMetaData.Keys) - { - string currentMetaKey = metaKey.ToLowerInvariant(); - - if (currentMetaKey.Equals("t", StringComparison.OrdinalIgnoreCase)) - { - long timetoken; - _ = Int64.TryParse(ttPublishMetaData[metaKey].ToString(), out timetoken); - ttMeta.Timetoken = timetoken; - } - else if (currentMetaKey.Equals("r", StringComparison.OrdinalIgnoreCase)) - { - ttMeta.Region = ttPublishMetaData[metaKey].ToString(); - } - } - msg.PublishTimetokenMetadata = ttMeta; - } - break; - case "u": - msg.UserMetadata = dicItem[key]; - break; - default: - break; - } - } - - msgList.Add(msg); - } - } - } - return msgList; - } - - private void LogCallback(string log) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), log), config.LogVerbosity); + if (unit != null) { unit.EventTypeList = new List>(); } } public ISubscribeOperation Channels(string[] channels) @@ -671,11 +150,13 @@ private void Subscribe(string[] channels, string[] channelGroups, Dictionary("invocation", obj?.Name)); LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnEffectDispatch : CurrentState = {subscribeEventEngine.CurrentState.GetType().Name} => Invocation = {obj.GetType().Name}", config.LogVerbosity); } private void SubscribeEventEngine_OnEventQueued(IEvent @event) { + unit?.EventTypeList.Add(new KeyValuePair("event", @event?.Name)); int attempts = 0; if (subscribeEventEngine.CurrentState is HandshakeReconnectingState handshakeReconnectingState) { diff --git a/src/Api/PubnubApi/EventEngine/Core/EventEngineInterfaces.cs b/src/Api/PubnubApi/EventEngine/Core/EventEngineInterfaces.cs index 2041f6745..e96d3bf18 100644 --- a/src/Api/PubnubApi/EventEngine/Core/EventEngineInterfaces.cs +++ b/src/Api/PubnubApi/EventEngine/Core/EventEngineInterfaces.cs @@ -127,6 +127,7 @@ public Task Run(T4 invocation) /// public interface IEffectInvocation { + string Name { get; set;} } /// @@ -138,6 +139,7 @@ public interface IEffectCancelInvocation : IEffectInvocation public interface IEvent { + string Name { get; set;} }; public abstract class State diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs index d72b3f4fb..c7cca0e55 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs @@ -3,22 +3,26 @@ namespace PubnubApi.EventEngine.Subscribe.Events { public class UnsubscribeAllEvent : Core.IEvent { + public string Name { get; set; } = "UNSUBSCRIBE_ALL"; } public class SubscriptionChangedEvent : Core.IEvent { public IEnumerable Channels; public IEnumerable ChannelGroups; + public string Name { get; set; } = "SUBSCRIPTION_CHANGED"; } public class SubscriptionRestoredEvent : Core.IEvent { public IEnumerable Channels; public IEnumerable ChannelGroups; public SubscriptionCursor Cursor; + public string Name { get; set; } = "SUBSCRIPTION_RESTORED"; } public class HandshakeSuccessEvent : Core.IEvent { public SubscriptionCursor Cursor; public PNStatus Status; + public string Name { get; set; } = "HANDSHAKE_SUCCESS"; } public class HandshakeFailureEvent : Core.IEvent { @@ -26,25 +30,25 @@ public class HandshakeFailureEvent : Core.IEvent { public IEnumerable ChannelGroups; public PNStatus Status; public int AttemptedRetries; + public string Name { get; set; } = "HANDSHAKE_FAILURE"; } public class HandshakeReconnectSuccessEvent : HandshakeSuccessEvent { public PNStatus Status; public SubscriptionCursor Cursor; + public new string Name { get; set; } = "HANDSHAKE_RECONNECT_SUCCESS"; } public class HandshakeReconnectFailureEvent : HandshakeFailureEvent { public IEnumerable Channels; public IEnumerable ChannelGroups; - } - - // Do we have this in system description ? - public class HandshakeReconnectRetryEvent : Core.IEvent { + public new string Name { get; set; } = "HANDSHAKE_RECONNECT_FAILURE"; } public class HandshakeReconnectGiveUpEvent : Core.IEvent { public PNStatus Status; + public string Name { get; set; } = "HANDSHAKE_RECONNECT_GIVEUP"; } public class ReceiveSuccessEvent : Core.IEvent { @@ -53,21 +57,22 @@ public class ReceiveSuccessEvent : Core.IEvent { public ReceivingResponse Messages; public SubscriptionCursor Cursor; public PNStatus Status; + public string Name { get; set; } = "RECEIVE_SUCCESS"; } public class ReceiveFailureEvent : Core.IEvent { public PNStatus Status; public int AttemptedRetries; public SubscriptionCursor Cursor; - } - - public class ReceiveReconnectRetry : Core.IEvent { + public string Name { get; set; } = "RECEIVE_FAILURE"; } public class ReceiveReconnectSuccessEvent : ReceiveSuccessEvent { + public new string Name { get; set; } = "RECEIVE_RECONNECT_SUCCESS"; } public class ReceiveReconnectFailureEvent : ReceiveFailureEvent { + public new string Name { get; set; } = "RECEIVE_RECONNECT_FAILURE"; } public class ReceiveReconnectGiveUpEvent : Core.IEvent { @@ -75,17 +80,20 @@ public class ReceiveReconnectGiveUpEvent : Core.IEvent { public IEnumerable ChannelGroups; public SubscriptionCursor Cursor; public PNStatus Status; + public string Name { get; set; } = "RECEIVE_RECONNECT_GIVEUP"; } public class DisconnectEvent : Core.IEvent { public IEnumerable Channels; public IEnumerable ChannelGroups; public SubscriptionCursor Cursor; + public string Name { get; set; } = "DISCONNECT"; } public class ReconnectEvent : Core.IEvent { public IEnumerable Channels; public IEnumerable ChannelGroups; public SubscriptionCursor Cursor; + public string Name { get; set; } = "RECONNECT"; } } \ No newline at end of file diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs index 6e4a542a3..101dec33b 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs @@ -7,6 +7,7 @@ namespace PubnubApi.EventEngine.Subscribe.Invocations { public class EmitMessagesInvocation : Core.IEffectInvocation { public ReceivingResponse Messages; public SubscriptionCursor Cursor; + public string Name { get; set; } = "EMIT_MESSAGES"; public EmitMessagesInvocation(SubscriptionCursor cursor, ReceivingResponse messages) { this.Cursor = cursor; @@ -18,6 +19,7 @@ public class EmitStatusInvocation : Core.IEffectInvocation { // TODO merge status variables into one? public PNStatusCategory StatusCategory; public PNStatus Status; + public string Name { get; set; } = "EMIT_STATUS"; public EmitStatusInvocation(PNStatus status) { @@ -45,6 +47,7 @@ public class HandshakeInvocation : Core.IEffectInvocation { // TODO if we need these, figure out how to pass them. public Dictionary InitialSubscribeQueryParams = new Dictionary(); public Dictionary ExternalQueryParams = new Dictionary(); + public string Name { get; set; } = "HANDSHAKE"; } public class ReceiveMessagesInvocation : Core.IEffectInvocation @@ -54,11 +57,18 @@ public class ReceiveMessagesInvocation : Core.IEffectInvocation public SubscriptionCursor Cursor; public Dictionary InitialSubscribeQueryParams = new Dictionary(); public Dictionary ExternalQueryParams = new Dictionary(); + public string Name { get; set; } = "RECEIVE_MESSAGES"; } - public class CancelReceiveMessagesInvocation : ReceiveMessagesInvocation, Core.IEffectCancelInvocation { } + public class CancelReceiveMessagesInvocation : ReceiveMessagesInvocation, Core.IEffectCancelInvocation + { + public new string Name { get; set; } = "CANCEL RECEIVE_MESSAGES"; + } - public class CancelHandshakeInvocation : HandshakeInvocation, Core.IEffectCancelInvocation { } + public class CancelHandshakeInvocation : HandshakeInvocation, Core.IEffectCancelInvocation + { + public new string Name { get; set; } = "CANCEL HANDSHAKE"; + } public class HandshakeReconnectInvocation: HandshakeInvocation { From 1f7d82234b71976315a38e66a8ed69df3f2aed17 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Mon, 21 Aug 2023 20:07:57 +0530 Subject: [PATCH 46/56] default value, typos and minor fixes --- src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs | 4 ++++ .../EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs | 4 ++-- .../Subscribe/Invocations/SubscriptionInvocations.cs | 4 ++-- .../EventEngine/Subscribe/States/HandshakingState.cs | 6 +++--- src/Api/PubnubApi/PNConfiguration.cs | 2 +- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs index 55ffdf710..d467db3ae 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs @@ -554,6 +554,10 @@ private PNStatus GetStatusIfError(RequestState asyncRequestState, string j { status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, PNStatusCategory.PNNetworkIssuesCategory, asyncRequestState, (int)HttpStatusCode.NotFound, new PNException(jsonString)); } + else if (!NewtonsoftJsonDotNet.JsonFastCheck(jsonString)) + { + status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, PNStatusCategory.PNNetworkIssuesCategory, asyncRequestState, (int)HttpStatusCode.NotFound, new PNException(jsonString)); + } return status; } diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs index 3a33c1978..48db70577 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs @@ -31,8 +31,8 @@ public override async Task Run(ReceiveMessagesInvocation invocation) var response = await MakeReceiveMessagesRequest(invocation); var cursor = new SubscriptionCursor() { - Region = response.Item1?.Timetoken.Region, - Timetoken = response.Item1?.Timetoken.Timestamp + Region = response.Item1?.Timetoken?.Region, + Timetoken = response.Item1?.Timetoken?.Timestamp }; // Assume that if status is null, the effect was cancelled. diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs index 101dec33b..a011d86aa 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs @@ -62,12 +62,12 @@ public class ReceiveMessagesInvocation : Core.IEffectInvocation public class CancelReceiveMessagesInvocation : ReceiveMessagesInvocation, Core.IEffectCancelInvocation { - public new string Name { get; set; } = "CANCEL RECEIVE_MESSAGES"; + public new string Name { get; set; } = "CANCEL_RECEIVE_MESSAGES"; } public class CancelHandshakeInvocation : HandshakeInvocation, Core.IEffectCancelInvocation { - public new string Name { get; set; } = "CANCEL HANDSHAKE"; + public new string Name { get; set; } = "CANCEL_HANDSHAKE"; } public class HandshakeReconnectInvocation: HandshakeInvocation diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs index a7d7a9941..f127709fb 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs @@ -41,11 +41,11 @@ public override TransitionResult Transition(IEvent e) Events.HandshakeFailureEvent handshakeFailure => new States.HandshakeReconnectingState() { - Channels = this.Channels, - ChannelGroups = this.ChannelGroups, + Channels = handshakeFailure.Channels, + ChannelGroups = handshakeFailure.ChannelGroups, ReconnectionConfiguration = this.ReconnectionConfiguration, AttemptedRetries = 1 - }.With(new EmitStatusInvocation(handshakeFailure.Status)), + }, Events.DisconnectEvent disconnect => new States.HandshakeStoppedState() { diff --git a/src/Api/PubnubApi/PNConfiguration.cs b/src/Api/PubnubApi/PNConfiguration.cs index f4eb3620c..b9ebeffc0 100644 --- a/src/Api/PubnubApi/PNConfiguration.cs +++ b/src/Api/PubnubApi/PNConfiguration.cs @@ -184,7 +184,7 @@ private void ConstructorInit(UserId currentUserId) UseRandomInitializationVector = true; FileMessagePublishRetryLimit = 5; _userId = currentUserId; - EnableEventEngine = false; + EnableEventEngine = true; ConnectionMaxRetries = -1; } public PNConfiguration SetPresenceTimeoutWithCustomInterval(int timeout, int interval) From e859a5329b469c7acb70b14f55e7f385c95605a3 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Tue, 22 Aug 2023 22:39:23 +0530 Subject: [PATCH 47/56] happy path contract tests --- .../EndPoint/PubSub/SubscribeEndpoint.cs | 41 +++++++++--- .../EndPoint/PubSub/SubscribeManager2.cs | 5 +- .../Subscribe/Effects/EmitMessagesHandler.cs | 2 +- .../Effects/HandshakeEffectHandler.cs | 24 ++++--- .../Effects/ReceivingEffectHandler.cs | 2 +- .../Subscribe/Events/SubscriptionEvents.cs | 16 ++--- .../Invocations/SubscriptionInvocations.cs | 20 ++++-- .../States/HandshakeReconnectingState.cs | 2 +- .../States/ReceiveReconnectingState.cs | 5 +- src/Api/PubnubApi/PNConfiguration.cs | 2 +- .../Features/event-engine/happy-path.feature | 52 ++++++++------- .../event-engine/happy-path.feature.cs | 66 +++++++++---------- .../AcceptanceTests/Steps/EventEngineSteps.cs | 23 +++++-- 13 files changed, 157 insertions(+), 103 deletions(-) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs index a353cd7ce..b1b2bd101 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs @@ -150,28 +150,49 @@ private void Subscribe(string[] channels, string[] channelGroups, Dictionary("invocation", obj?.Name)); - LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnEffectDispatch : CurrentState = {subscribeEventEngine.CurrentState.GetType().Name} => Invocation = {obj.GetType().Name}", config.LogVerbosity); + try + { + unit?.EventTypeList.Add(new KeyValuePair("invocation", obj?.Name)); + LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnEffectDispatch : CurrentState = {subscribeEventEngine.CurrentState.GetType().Name} => Invocation = {obj.GetType().Name}", config.LogVerbosity); + } + catch (Exception ex) + { + LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnEffectDispatch : CurrentState = {subscribeEventEngine.CurrentState.GetType().Name} => EXCEPTION = {ex}", config.LogVerbosity); + } } private void SubscribeEventEngine_OnEventQueued(IEvent @event) { - unit?.EventTypeList.Add(new KeyValuePair("event", @event?.Name)); - int attempts = 0; - if (subscribeEventEngine.CurrentState is HandshakeReconnectingState handshakeReconnectingState) + try { - attempts = handshakeReconnectingState.AttemptedRetries; + unit?.EventTypeList.Add(new KeyValuePair("event", @event?.Name)); + int attempts = 0; + if (subscribeEventEngine.CurrentState is HandshakeReconnectingState handshakeReconnectingState) + { + attempts = handshakeReconnectingState.AttemptedRetries; + } + else if (subscribeEventEngine.CurrentState is ReceiveReconnectingState receiveReconnectingState) + { + attempts = receiveReconnectingState.AttemptedRetries; + } + LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnEventQueued : CurrentState: {subscribeEventEngine.CurrentState.GetType().Name}; Event = {@event.GetType().Name}; Attempt = {attempts} of {config.ConnectionMaxRetries}", config.LogVerbosity); } - else if (subscribeEventEngine.CurrentState is ReceiveReconnectingState receiveReconnectingState) + catch(Exception ex) { - attempts = receiveReconnectingState.AttemptedRetries; + LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnEventQueued : CurrentState = {subscribeEventEngine.CurrentState.GetType().Name} => EXCEPTION = {ex}", config.LogVerbosity); } - LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnEventQueued : CurrentState: {subscribeEventEngine.CurrentState.GetType().Name}; Event = {@event.GetType().Name}; Attempt = {attempts} of {config.ConnectionMaxRetries}", config.LogVerbosity); } private void SubscribeEventEngine_OnStateTransition(EventEngine.Core.TransitionResult obj) { - LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnStateTransition : CurrentState = {subscribeEventEngine.CurrentState.GetType().Name} => Transition State = {obj?.State.GetType().Name}", config.LogVerbosity); + try + { + LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnStateTransition : CurrentState = {subscribeEventEngine.CurrentState.GetType().Name} => Transition State = {obj?.State.GetType().Name}", config.LogVerbosity); + } + catch(Exception ex) + { + LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, EE OnStateTransition : CurrentState = {subscribeEventEngine.CurrentState.GetType().Name} => EXCEPTION = {ex}", config.LogVerbosity); + } } private void MessageEmitter(Pubnub pubnubInstance, PNMessageResult messageResult) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs index d467db3ae..d3267b38e 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs @@ -310,7 +310,10 @@ internal protected async Task> UrlProcessRequest(Uri jsonString = await pubnubHttp.SendRequestAndGetJsonResponse(requestUri, pubnubRequestState, request).ConfigureAwait(false); } #endif - + if (pubnubLog != null && config != null) + { + LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, JSON= {jsonString} for request={requestUri}", config.LogVerbosity); + } PNStatus errStatus = GetStatusIfError(pubnubRequestState, jsonString); return new Tuple((errStatus == null) ? jsonString : "", errStatus); } diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs index 8c4b29432..dda186af9 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/EmitMessagesHandler.cs @@ -36,7 +36,7 @@ public EmitMessagesHandler(Pubnub pubnubInstance, public async override Task Run(EmitMessagesInvocation invocation) { - var processedMessages = invocation.Messages?.Messages.Select(m => + var processedMessages = invocation.Messages?.Messages?.Select(m => { var msgResult = new PNMessageResult() { diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs index 23e8dcd9d..1a8d27c20 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs @@ -11,6 +11,7 @@ using PubnubApi.EventEngine.Subscribe.Events; using PubnubApi.EventEngine.Subscribe.Invocations; using PubnubApi.EventEngine.Subscribe.Common; +using System.Diagnostics; namespace PubnubApi.EventEngine.Subscribe.Effects { @@ -55,7 +56,7 @@ public override async Task Run(HandshakeInvocation invocation) eventQueue.Enqueue(new Events.HandshakeReconnectSuccessEvent() { Cursor = cursor, Status = response.Item2 }); break; case { } when response.Item2.Error: - eventQueue.Enqueue(new Events.HandshakeFailureEvent() { Status = response.Item2}); + eventQueue.Enqueue(new Events.HandshakeFailureEvent() { Status = response.Item2, Channels = invocation.Channels, ChannelGroups = invocation.ChannelGroups}); break; case { }: eventQueue.Enqueue(new Events.HandshakeSuccessEvent() { Cursor = cursor, Status = response.Item2 }); @@ -107,16 +108,23 @@ internal HandshakeReconnectEffectHandler(SubscribeManager2 manager, EventQueue e public override async Task Run(HandshakeReconnectInvocation invocation) { - if (!ReconnectionDelayUtil.shouldRetry(invocation.ReconnectionConfiguration, invocation.AttemptedRetries)) + try { - eventQueue.Enqueue(new HandshakeReconnectGiveUpEvent() { Status = new PNStatus(PNStatusCategory.PNCancelledCategory) }); + if (!ReconnectionDelayUtil.shouldRetry(invocation.ReconnectionConfiguration, invocation.AttemptedRetries)) + { + eventQueue.Enqueue(new HandshakeReconnectGiveUpEvent() { Status = new PNStatus(new Exception(""), PNOperationType.PNSubscribeOperation, PNStatusCategory.PNCancelledCategory, invocation.Channels, invocation.ChannelGroups ) }); + } + else + { + retryDelay = new Delay(ReconnectionDelayUtil.CalculateDelay(invocation.ReconnectionConfiguration.ReconnectionPolicy, invocation.AttemptedRetries)); + await retryDelay.Start(); + if (!retryDelay.Cancelled) + await handshakeEffectHandler.Run(invocation as HandshakeInvocation); + } } - else + catch (Exception ex) { - retryDelay = new Delay(ReconnectionDelayUtil.CalculateDelay(invocation.ReconnectionConfiguration.ReconnectionPolicy, invocation.AttemptedRetries)); - await retryDelay.Start(); - if (!retryDelay.Cancelled) - await handshakeEffectHandler.Run(invocation as HandshakeInvocation); + Debug.WriteLine(ex); } } diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs index 48db70577..5a0df5e77 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs @@ -45,7 +45,7 @@ public override async Task Run(ReceiveMessagesInvocation invocation) eventQueue.Enqueue(new Events.ReceiveReconnectFailureEvent() { AttemptedRetries = (reconnectInvocation.AttemptedRetries + 1) % int.MaxValue, Status = response.Item2}); break; case Invocations.ReceiveReconnectInvocation reconnectInvocation: - eventQueue.Enqueue(new Events.ReceiveReconnectSuccessEvent() { Channels = invocation?.Channels, ChannelGroups = invocation?.ChannelGroups, Cursor = cursor, Status = response.Item2 }); + eventQueue.Enqueue(new Events.ReceiveReconnectSuccessEvent() { Channels = invocation?.Channels, ChannelGroups = invocation?.ChannelGroups, Cursor = cursor, Status = response.Item2, Messages = response.Item1 }); break; case { } when response.Item2.Error: eventQueue.Enqueue(new Events.ReceiveFailureEvent() { Cursor = invocation.Cursor, Status = response.Item2}); diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs index c7cca0e55..aaefd1fa4 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs @@ -22,7 +22,7 @@ public class SubscriptionRestoredEvent : Core.IEvent { public class HandshakeSuccessEvent : Core.IEvent { public SubscriptionCursor Cursor; public PNStatus Status; - public string Name { get; set; } = "HANDSHAKE_SUCCESS"; + public virtual string Name { get; set; } = "HANDSHAKE_SUCCESS"; } public class HandshakeFailureEvent : Core.IEvent { @@ -30,20 +30,20 @@ public class HandshakeFailureEvent : Core.IEvent { public IEnumerable ChannelGroups; public PNStatus Status; public int AttemptedRetries; - public string Name { get; set; } = "HANDSHAKE_FAILURE"; + public virtual string Name { get; set; } = "HANDSHAKE_FAILURE"; } public class HandshakeReconnectSuccessEvent : HandshakeSuccessEvent { public PNStatus Status; public SubscriptionCursor Cursor; - public new string Name { get; set; } = "HANDSHAKE_RECONNECT_SUCCESS"; + public override string Name { get; set; } = "HANDSHAKE_RECONNECT_SUCCESS"; } public class HandshakeReconnectFailureEvent : HandshakeFailureEvent { public IEnumerable Channels; public IEnumerable ChannelGroups; - public new string Name { get; set; } = "HANDSHAKE_RECONNECT_FAILURE"; + public override string Name { get; set; } = "HANDSHAKE_RECONNECT_FAILURE"; } public class HandshakeReconnectGiveUpEvent : Core.IEvent { @@ -57,22 +57,22 @@ public class ReceiveSuccessEvent : Core.IEvent { public ReceivingResponse Messages; public SubscriptionCursor Cursor; public PNStatus Status; - public string Name { get; set; } = "RECEIVE_SUCCESS"; + public virtual string Name { get; set; } = "RECEIVE_SUCCESS"; } public class ReceiveFailureEvent : Core.IEvent { public PNStatus Status; public int AttemptedRetries; public SubscriptionCursor Cursor; - public string Name { get; set; } = "RECEIVE_FAILURE"; + public virtual string Name { get; set; } = "RECEIVE_FAILURE"; } public class ReceiveReconnectSuccessEvent : ReceiveSuccessEvent { - public new string Name { get; set; } = "RECEIVE_RECONNECT_SUCCESS"; + public override string Name { get; set; } = "RECEIVE_RECONNECT_SUCCESS"; } public class ReceiveReconnectFailureEvent : ReceiveFailureEvent { - public new string Name { get; set; } = "RECEIVE_RECONNECT_FAILURE"; + public override string Name { get; set; } = "RECEIVE_RECONNECT_FAILURE"; } public class ReceiveReconnectGiveUpEvent : Core.IEvent { diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs index a011d86aa..840f7fac6 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs @@ -47,7 +47,7 @@ public class HandshakeInvocation : Core.IEffectInvocation { // TODO if we need these, figure out how to pass them. public Dictionary InitialSubscribeQueryParams = new Dictionary(); public Dictionary ExternalQueryParams = new Dictionary(); - public string Name { get; set; } = "HANDSHAKE"; + public virtual string Name { get; set; } = "HANDSHAKE"; } public class ReceiveMessagesInvocation : Core.IEffectInvocation @@ -57,32 +57,40 @@ public class ReceiveMessagesInvocation : Core.IEffectInvocation public SubscriptionCursor Cursor; public Dictionary InitialSubscribeQueryParams = new Dictionary(); public Dictionary ExternalQueryParams = new Dictionary(); - public string Name { get; set; } = "RECEIVE_MESSAGES"; + public virtual string Name { get; set; } = "RECEIVE_MESSAGES"; } public class CancelReceiveMessagesInvocation : ReceiveMessagesInvocation, Core.IEffectCancelInvocation { - public new string Name { get; set; } = "CANCEL_RECEIVE_MESSAGES"; + public override string Name { get; set; } = "CANCEL_RECEIVE_MESSAGES"; } public class CancelHandshakeInvocation : HandshakeInvocation, Core.IEffectCancelInvocation { - public new string Name { get; set; } = "CANCEL_HANDSHAKE"; + public override string Name { get; set; } = "CANCEL_HANDSHAKE"; } public class HandshakeReconnectInvocation: HandshakeInvocation { public ReconnectionConfiguration ReconnectionConfiguration; public int AttemptedRetries; + public override string Name { get; set; } = "HANDSHAKE_RECONNECT"; } - public class CancelHandshakeReconnectInvocation: HandshakeReconnectInvocation, Core.IEffectCancelInvocation { } + public class CancelHandshakeReconnectInvocation: HandshakeReconnectInvocation, Core.IEffectCancelInvocation + { + public override string Name { get; set; } = "CANCEL_HANDSHAKE_RECONNECT"; + } public class ReceiveReconnectInvocation: ReceiveMessagesInvocation { public ReconnectionConfiguration ReconnectionConfiguration; public int AttemptedRetries; + public override string Name { get; set; } = "RECEIVE_RECONNECT"; } - public class CancelReceiveReconnectInvocation: ReceiveReconnectInvocation, Core.IEffectCancelInvocation { } + public class CancelReceiveReconnectInvocation: ReceiveReconnectInvocation, Core.IEffectCancelInvocation + { + public override string Name { get; set; } = "CANCEL_RECEIVE_RECONNECT"; + } } \ No newline at end of file diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs index cac50df4f..e86c9d9cc 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs @@ -59,7 +59,7 @@ public override TransitionResult Transition(IEvent e) ChannelGroups = this.ChannelGroups, ReconnectionConfiguration = this.ReconnectionConfiguration, AttemptedRetries = (this.AttemptedRetries + 1) % int.MaxValue - }.With(new EmitStatusInvocation(handshakeReconnectFailure.Status)), + }, Events.HandshakeReconnectSuccessEvent handshakeReconnectSuccess => new ReceivingState() { diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs index b0c7ba8c3..acd2a30ad 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs @@ -63,7 +63,10 @@ public override TransitionResult Transition(IEvent e) ChannelGroups = receiveReconnectSuccess.ChannelGroups, Cursor = receiveReconnectSuccess.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration - }.With(new EmitStatusInvocation(receiveReconnectSuccess.Status)), + }.With( + new EmitMessagesInvocation(receiveReconnectSuccess.Cursor, receiveReconnectSuccess.Messages), + new EmitStatusInvocation(receiveReconnectSuccess.Status) + ), Events.ReceiveReconnectFailureEvent receiveReconnectFailure => new ReceiveReconnectingState() { diff --git a/src/Api/PubnubApi/PNConfiguration.cs b/src/Api/PubnubApi/PNConfiguration.cs index b9ebeffc0..f4eb3620c 100644 --- a/src/Api/PubnubApi/PNConfiguration.cs +++ b/src/Api/PubnubApi/PNConfiguration.cs @@ -184,7 +184,7 @@ private void ConstructorInit(UserId currentUserId) UseRandomInitializationVector = true; FileMessagePublishRetryLimit = 5; _userId = currentUserId; - EnableEventEngine = true; + EnableEventEngine = false; ConnectionMaxRetries = -1; } public PNConfiguration SetPresenceTimeoutWithCustomInterval(int timeout, int interval) diff --git a/src/UnitTests/AcceptanceTests/Features/event-engine/happy-path.feature b/src/UnitTests/AcceptanceTests/Features/event-engine/happy-path.feature index 386935a3b..d9e953149 100644 --- a/src/UnitTests/AcceptanceTests/Features/event-engine/happy-path.feature +++ b/src/UnitTests/AcceptanceTests/Features/event-engine/happy-path.feature @@ -1,33 +1,33 @@ -@featureSet=eventEngine +@featureSet=eventEngine @beta Feature: Event Engine This is a description of the feature Background: Given the demo keyset with event engine enabled - @contract=simpleSubscribe @beta + @contract=simpleSubscribe Scenario: Successfully receive messages When I subscribe - When I publish a message Then I receive the message in my subscribe response And I observe the following: - | type | name | - | event | SUBSCRIPTION_CHANGED | - | invocation | HANDSHAKE | - | event | HANDSHAKE_SUCCESS | - | invocation | CANCEL_HANDSHAKE | - | invocation | EMIT_STATUS | - | invocation | RECEIVE_EVENTS | - | event | RECEIVE_SUCCESS | - | invocation | CANCEL_RECEIVE_EVENTS | - | invocation | EMIT_STATUS | - | invocation | EMIT_EVENTS | + | type | name | + | event | SUBSCRIPTION_CHANGED | + | invocation | HANDSHAKE | + | event | HANDSHAKE_SUCCESS | + | invocation | CANCEL_HANDSHAKE | + | invocation | EMIT_STATUS | + | invocation | RECEIVE_MESSAGES | + | event | RECEIVE_SUCCESS | + | invocation | CANCEL_RECEIVE_MESSAGES | + | invocation | EMIT_MESSAGES | + | invocation | EMIT_STATUS | + | invocation | RECEIVE_MESSAGES | - @contract=subscribeHandshakeFailure @beta + @contract=subscribeHandshakeFailure Scenario: Complete handshake failure Given a linear reconnection policy with 3 retries When I subscribe - Then I receive an error + Then I receive an error in my subscribe response And I observe the following: | type | name | | event | SUBSCRIPTION_CHANGED | @@ -48,7 +48,7 @@ Feature: Event Engine | invocation | CANCEL_HANDSHAKE_RECONNECT | | invocation | EMIT_STATUS | - @contract=subscribeHandshakeRecovery @beta + @contract=subscribeHandshakeRecovery Scenario: Handshake failure recovery Given a linear reconnection policy with 3 retries When I subscribe @@ -66,14 +66,16 @@ Feature: Event Engine | event | HANDSHAKE_RECONNECT_SUCCESS | | invocation | CANCEL_HANDSHAKE_RECONNECT | | invocation | EMIT_STATUS | - | invocation | RECEIVE_EVENTS | + | invocation | RECEIVE_MESSAGES | | event | RECEIVE_SUCCESS | - | invocation | CANCEL_RECEIVE_EVENTS | + | invocation | CANCEL_RECEIVE_MESSAGES | + | invocation | EMIT_MESSAGES | | invocation | EMIT_STATUS | - | invocation | EMIT_EVENTS | + | invocation | RECEIVE_MESSAGES | - @contract=subscribeReceivingRecovery @beta + @contract=subscribeReceivingRecovery Scenario: Receiving failure recovery + Given a linear reconnection policy with 3 retries When I subscribe Then I receive the message in my subscribe response And I observe the following: @@ -83,12 +85,12 @@ Feature: Event Engine | event | HANDSHAKE_SUCCESS | | invocation | CANCEL_HANDSHAKE | | invocation | EMIT_STATUS | - | invocation | RECEIVE_EVENTS | + | invocation | RECEIVE_MESSAGES | | event | RECEIVE_FAILURE | - | invocation | CANCEL_RECEIVE_EVENTS | + | invocation | CANCEL_RECEIVE_MESSAGES | | invocation | RECEIVE_RECONNECT | | event | RECEIVE_RECONNECT_SUCCESS | | invocation | CANCEL_RECEIVE_RECONNECT | + | invocation | EMIT_MESSAGES | | invocation | EMIT_STATUS | - | invocation | EMIT_EVENTS | - | invocation | RECEIVE_EVENTS | \ No newline at end of file + | invocation | RECEIVE_MESSAGES | \ No newline at end of file diff --git a/src/UnitTests/AcceptanceTests/Features/event-engine/happy-path.feature.cs b/src/UnitTests/AcceptanceTests/Features/event-engine/happy-path.feature.cs index 841b19aba..0089df0fa 100644 --- a/src/UnitTests/AcceptanceTests/Features/event-engine/happy-path.feature.cs +++ b/src/UnitTests/AcceptanceTests/Features/event-engine/happy-path.feature.cs @@ -22,13 +22,15 @@ namespace AcceptanceTests.Features.Event_Engine [NUnit.Framework.TestFixtureAttribute()] [NUnit.Framework.DescriptionAttribute("Event Engine")] [NUnit.Framework.CategoryAttribute("featureSet=eventEngine")] + [NUnit.Framework.CategoryAttribute("beta")] public partial class EventEngineFeature { private TechTalk.SpecFlow.ITestRunner testRunner; private static string[] featureTags = new string[] { - "featureSet=eventEngine"}; + "featureSet=eventEngine", + "beta"}; #line 1 "happy-path.feature" #line hidden @@ -87,12 +89,10 @@ public virtual void FeatureBackground() [NUnit.Framework.TestAttribute()] [NUnit.Framework.DescriptionAttribute("Successfully receive messages")] [NUnit.Framework.CategoryAttribute("contract=simpleSubscribe")] - [NUnit.Framework.CategoryAttribute("beta")] public void SuccessfullyReceiveMessages() { string[] tagsOfScenario = new string[] { - "contract=simpleSubscribe", - "beta"}; + "contract=simpleSubscribe"}; System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Successfully receive messages", null, tagsOfScenario, argumentsOfScenario, featureTags); #line 9 @@ -112,9 +112,6 @@ public void SuccessfullyReceiveMessages() testRunner.When("I subscribe", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden #line 11 - testRunner.When("I publish a message", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); -#line hidden -#line 12 testRunner.Then("I receive the message in my subscribe response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden TechTalk.SpecFlow.Table table1 = new TechTalk.SpecFlow.Table(new string[] { @@ -137,20 +134,23 @@ public void SuccessfullyReceiveMessages() "EMIT_STATUS"}); table1.AddRow(new string[] { "invocation", - "RECEIVE_EVENTS"}); + "RECEIVE_MESSAGES"}); table1.AddRow(new string[] { "event", "RECEIVE_SUCCESS"}); table1.AddRow(new string[] { "invocation", - "CANCEL_RECEIVE_EVENTS"}); + "CANCEL_RECEIVE_MESSAGES"}); + table1.AddRow(new string[] { + "invocation", + "EMIT_MESSAGES"}); table1.AddRow(new string[] { "invocation", "EMIT_STATUS"}); table1.AddRow(new string[] { "invocation", - "EMIT_EVENTS"}); -#line 13 + "RECEIVE_MESSAGES"}); +#line 12 testRunner.And("I observe the following:", ((string)(null)), table1, "And "); #line hidden } @@ -160,12 +160,10 @@ public void SuccessfullyReceiveMessages() [NUnit.Framework.TestAttribute()] [NUnit.Framework.DescriptionAttribute("Complete handshake failure")] [NUnit.Framework.CategoryAttribute("contract=subscribeHandshakeFailure")] - [NUnit.Framework.CategoryAttribute("beta")] public void CompleteHandshakeFailure() { string[] tagsOfScenario = new string[] { - "contract=subscribeHandshakeFailure", - "beta"}; + "contract=subscribeHandshakeFailure"}; System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Complete handshake failure", null, tagsOfScenario, argumentsOfScenario, featureTags); #line 27 @@ -188,7 +186,7 @@ public void CompleteHandshakeFailure() testRunner.When("I subscribe", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden #line 30 - testRunner.Then("I receive an error", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); + testRunner.Then("I receive an error in my subscribe response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] { "type", @@ -254,12 +252,10 @@ public void CompleteHandshakeFailure() [NUnit.Framework.TestAttribute()] [NUnit.Framework.DescriptionAttribute("Handshake failure recovery")] [NUnit.Framework.CategoryAttribute("contract=subscribeHandshakeRecovery")] - [NUnit.Framework.CategoryAttribute("beta")] public void HandshakeFailureRecovery() { string[] tagsOfScenario = new string[] { - "contract=subscribeHandshakeRecovery", - "beta"}; + "contract=subscribeHandshakeRecovery"}; System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Handshake failure recovery", null, tagsOfScenario, argumentsOfScenario, featureTags); #line 52 @@ -322,19 +318,22 @@ public void HandshakeFailureRecovery() "EMIT_STATUS"}); table3.AddRow(new string[] { "invocation", - "RECEIVE_EVENTS"}); + "RECEIVE_MESSAGES"}); table3.AddRow(new string[] { "event", "RECEIVE_SUCCESS"}); table3.AddRow(new string[] { "invocation", - "CANCEL_RECEIVE_EVENTS"}); + "CANCEL_RECEIVE_MESSAGES"}); + table3.AddRow(new string[] { + "invocation", + "EMIT_MESSAGES"}); table3.AddRow(new string[] { "invocation", "EMIT_STATUS"}); table3.AddRow(new string[] { "invocation", - "EMIT_EVENTS"}); + "RECEIVE_MESSAGES"}); #line 56 testRunner.And("I observe the following:", ((string)(null)), table3, "And "); #line hidden @@ -345,15 +344,13 @@ public void HandshakeFailureRecovery() [NUnit.Framework.TestAttribute()] [NUnit.Framework.DescriptionAttribute("Receiving failure recovery")] [NUnit.Framework.CategoryAttribute("contract=subscribeReceivingRecovery")] - [NUnit.Framework.CategoryAttribute("beta")] public void ReceivingFailureRecovery() { string[] tagsOfScenario = new string[] { - "contract=subscribeReceivingRecovery", - "beta"}; + "contract=subscribeReceivingRecovery"}; System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Receiving failure recovery", null, tagsOfScenario, argumentsOfScenario, featureTags); -#line 76 +#line 77 this.ScenarioInitialize(scenarioInfo); #line hidden if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) @@ -366,10 +363,13 @@ public void ReceivingFailureRecovery() #line 5 this.FeatureBackground(); #line hidden -#line 77 +#line 78 + testRunner.Given("a linear reconnection policy with 3 retries", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line hidden +#line 79 testRunner.When("I subscribe", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden -#line 78 +#line 80 testRunner.Then("I receive the message in my subscribe response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden TechTalk.SpecFlow.Table table4 = new TechTalk.SpecFlow.Table(new string[] { @@ -392,13 +392,13 @@ public void ReceivingFailureRecovery() "EMIT_STATUS"}); table4.AddRow(new string[] { "invocation", - "RECEIVE_EVENTS"}); + "RECEIVE_MESSAGES"}); table4.AddRow(new string[] { "event", "RECEIVE_FAILURE"}); table4.AddRow(new string[] { "invocation", - "CANCEL_RECEIVE_EVENTS"}); + "CANCEL_RECEIVE_MESSAGES"}); table4.AddRow(new string[] { "invocation", "RECEIVE_RECONNECT"}); @@ -410,14 +410,14 @@ public void ReceivingFailureRecovery() "CANCEL_RECEIVE_RECONNECT"}); table4.AddRow(new string[] { "invocation", - "EMIT_STATUS"}); + "EMIT_MESSAGES"}); table4.AddRow(new string[] { "invocation", - "EMIT_EVENTS"}); + "EMIT_STATUS"}); table4.AddRow(new string[] { "invocation", - "RECEIVE_EVENTS"}); -#line 79 + "RECEIVE_MESSAGES"}); +#line 81 testRunner.And("I observe the following:", ((string)(null)), table4, "And "); #line hidden } diff --git a/src/UnitTests/AcceptanceTests/Steps/EventEngineSteps.cs b/src/UnitTests/AcceptanceTests/Steps/EventEngineSteps.cs index 8123a7b15..e03b13e13 100644 --- a/src/UnitTests/AcceptanceTests/Steps/EventEngineSteps.cs +++ b/src/UnitTests/AcceptanceTests/Steps/EventEngineSteps.cs @@ -13,6 +13,7 @@ using System.Threading; using TechTalk.SpecFlow.Assist; using System.Net.Http; +using System.Diagnostics; namespace AcceptanceTests.Steps { @@ -31,10 +32,6 @@ public class EventEngineSteps private string channel = "my_channel"; private string channelGroup = "my_channelgroup"; private string publishMsg = "hello_world"; - //private UuidMetadataPersona uuidMetadataPersona = null; - //private PNGetUuidMetadataResult getUuidMetadataResult = null; - //private PNSetUuidMetadataResult setUuidMetadataResult = null; - //private PNGetAllUuidMetadataResult getAllUuidMetadataResult = null; PNPublishResult publishResult = null; SubscribeCallback subscribeCallback = null; private PNMessageResult messageResult = null; @@ -44,6 +41,11 @@ public class EventEngineSteps PubnubError pnError = null; IPubnubUnitTest unitTest; + static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e) + { + Debug.WriteLine("Unhandled exception occured inside EventEngine. Exiting the test. Please try again."); + System.Environment.Exit(1); + } public class PubnubUnitTest : IPubnubUnitTest { long IPubnubUnitTest.Timetoken @@ -135,6 +137,7 @@ public class SubscribeResponseRow } public EventEngineSteps(ScenarioContext scenarioContext) { + AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper; _scenarioContext = scenarioContext; } @@ -207,6 +210,7 @@ public void AfterScenario() System.Diagnostics.Debug.WriteLine(mockExpectResponse); } } + [Given(@"the demo keyset with event engine enabled")] public void GivenTheDemoKeysetWithEventEngineEnabled() { @@ -235,7 +239,6 @@ public void GivenTheDemoKeysetWithEventEngineEnabled() } config.EnableEventEngine = true; - messageReceivedEvent = new ManualResetEvent(false); statusReceivedEvent = new ManualResetEvent(false); @@ -338,8 +341,8 @@ public void ThenIObserveTheFollowing(Table table) { Assert.Fail(); } - System.Diagnostics.Debug.WriteLine($"COUNT = {pn.PubnubUnitTest.EventTypeList.Count} "); - for (int i = 0; i < pn.PubnubUnitTest.EventTypeList.Count(); i++) + System.Diagnostics.Debug.WriteLine($"COUNT = {pn.PubnubUnitTest.EventTypeList?.Count} "); + for (int i = 0; i < pn.PubnubUnitTest.EventTypeList?.Count(); i++) { System.Diagnostics.Debug.WriteLine($"{pn.PubnubUnitTest.EventTypeList[i].Key} - {pn.PubnubUnitTest.EventTypeList[i].Value} "); } @@ -371,6 +374,12 @@ public void GivenALinearReconnectionPolicyWithRetries(int retryCount) config.ConnectionMaxRetries = retryCount; } + [Then(@"I receive an error in my subscribe response")] + public void ThenIReceiveAnErrorInMySubscribeResponse() + { + Assert.True(pnStatus != null && pnStatus.Error); + } + [Then(@"I receive an error")] public void ThenIReceiveAnError() { From e011854f6afe083d968fc9cbabc1c7abe87aed69 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Thu, 24 Aug 2023 11:50:06 +0530 Subject: [PATCH 48/56] subscribe with timetoken and remove status for Receive(reconnect) --- .../EndPoint/PubSub/SubscribeEndpoint.cs | 12 +- .../EndPoint/PubSub/SubscribeManager2.cs | 5 + .../Subscribe/Events/SubscriptionEvents.cs | 1 + .../States/ReceiveReconnectingState.cs | 3 +- .../Subscribe/States/ReceivingState.cs | 9 +- .../Subscribe/States/UnsubscribedState.cs | 1 + .../Subscribe/SubscribeEventEngine.cs | 15 +- .../Features/event-engine/happy-path.feature | 39 ++- .../event-engine/happy-path.feature.cs | 291 +++++++++++++----- .../AcceptanceTests/Steps/EventEngineSteps.cs | 33 +- 10 files changed, 314 insertions(+), 95 deletions(-) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs index b1b2bd101..3f1891ef2 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs @@ -122,11 +122,15 @@ public void Execute() string[] channelNames = this.subscribeChannelNames != null ? this.subscribeChannelNames.ToArray() : null; string[] channelGroupNames = this.subscribeChannelGroupNames != null ? this.subscribeChannelGroupNames.ToArray() : null; - - Subscribe(channelNames, channelGroupNames, this.queryParam); + SubscriptionCursor cursor = null; + if (subscribeTimetoken >= 0) + { + cursor = new SubscriptionCursor { Timetoken = subscribeTimetoken, Region = 0 }; + } + Subscribe(channelNames, channelGroupNames, cursor, this.queryParam); } - private void Subscribe(string[] channels, string[] channelGroups, Dictionary externalQueryParam) + private void Subscribe(string[] channels, string[] channelGroups, SubscriptionCursor cursor, Dictionary externalQueryParam) { if ((channels == null || channels.Length == 0) && (channelGroups == null || channelGroups.Length == 0)) { @@ -145,7 +149,7 @@ private void Subscribe(string[] channels, string[] channelGroups, Dictionary(channels, channelGroups); + subscribeEventEngine.Subscribe(channels, channelGroups, cursor); } private void SubscribeEventEngine_OnEffectDispatch(IEffectInvocation obj) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs index d3267b38e..e8bd852a6 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs @@ -517,6 +517,11 @@ private PNStatus GetStatusIfError(RequestState asyncRequestState, string j PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, statusMessage); status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, category, asyncRequestState, statusCode, new PNException(jsonString)); } + else if (statusCode != 200) + { + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, errorMessageJson); + status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, category, asyncRequestState, statusCode, new PNException(jsonString)); + } } else if (deserializeStatus.Count >= 1 && deserializeStatus.ContainsKey("status") && string.Equals(deserializeStatus["status"].ToString(), "error", StringComparison.OrdinalIgnoreCase) && deserializeStatus.ContainsKey("error")) { diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs index aaefd1fa4..37e65f7ac 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs @@ -9,6 +9,7 @@ public class UnsubscribeAllEvent : Core.IEvent { public class SubscriptionChangedEvent : Core.IEvent { public IEnumerable Channels; public IEnumerable ChannelGroups; + public SubscriptionCursor Cursor; public string Name { get; set; } = "SUBSCRIPTION_CHANGED"; } diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs index acd2a30ad..8cd6fc4ca 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs @@ -64,8 +64,7 @@ public override TransitionResult Transition(IEvent e) Cursor = receiveReconnectSuccess.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration }.With( - new EmitMessagesInvocation(receiveReconnectSuccess.Cursor, receiveReconnectSuccess.Messages), - new EmitStatusInvocation(receiveReconnectSuccess.Status) + new EmitMessagesInvocation(receiveReconnectSuccess.Cursor, receiveReconnectSuccess.Messages) ), Events.ReceiveReconnectFailureEvent receiveReconnectFailure => new ReceiveReconnectingState() diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs index 217718dbe..2c681c7b1 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs @@ -31,15 +31,14 @@ public override TransitionResult Transition(IEvent e) Cursor = receiveSuccess.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration }.With( - new EmitMessagesInvocation(receiveSuccess.Cursor, receiveSuccess.Messages), - new EmitStatusInvocation(receiveSuccess.Status) + new EmitMessagesInvocation(receiveSuccess.Cursor, receiveSuccess.Messages) ), Events.SubscriptionChangedEvent subscriptionChanged => new ReceivingState() { Channels = (Channels ?? Enumerable.Empty()).Union(subscriptionChanged.Channels), ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(subscriptionChanged.ChannelGroups), - Cursor = this.Cursor, + Cursor = subscriptionChanged.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration }, @@ -55,7 +54,7 @@ public override TransitionResult Transition(IEvent e) { Channels = this.Channels, ChannelGroups = this.ChannelGroups, - Cursor = this.Cursor, + Cursor = disconnect.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration }.With(new EmitStatusInvocation(PNStatusCategory.PNDisconnectedCategory)), @@ -63,7 +62,7 @@ public override TransitionResult Transition(IEvent e) { Channels = this.Channels, ChannelGroups = this.ChannelGroups, - Cursor = this.Cursor, + Cursor = receiveFailure.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration, AttemptedRetries = 1 }, diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs index 4338e7adc..14195561d 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs @@ -18,6 +18,7 @@ public override TransitionResult Transition(Core.IEvent e) { Channels = (Channels ?? Enumerable.Empty()).Union(subscriptionChanged.Channels), ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(subscriptionChanged.ChannelGroups), + Cursor = subscriptionChanged.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration }, diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs index 63c204483..b01eedcee 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs @@ -53,7 +53,7 @@ internal SubscribeEventEngine(Pubnub pubnubInstance, currentState = new UnsubscribedState() { ReconnectionConfiguration = new Context.ReconnectionConfiguration(pubnubConfiguration.ReconnectionPolicy, pubnubConfiguration.ConnectionMaxRetries) }; } - public void Subscribe(string[] channels, string[] channelGroups) + public void Subscribe(string[] channels, string[] channelGroups, SubscriptionCursor cursor) { foreach (var c in channels) { @@ -63,12 +63,19 @@ public void Subscribe(string[] channels, string[] channelGroups) { channelGroupTypeMap[c] = typeof(T); } - this.EventQueue.Enqueue(new SubscriptionChangedEvent() { Channels = channels, ChannelGroups = channelGroups }); + if (cursor != null) + { + this.EventQueue.Enqueue(new SubscriptionRestoredEvent() { Channels = channels, ChannelGroups = channelGroups, Cursor = cursor }); + } + else + { + this.EventQueue.Enqueue(new SubscriptionChangedEvent() { Channels = channels, ChannelGroups = channelGroups }); + } } - public void Subscribe(string[] channels, string[] channelGroups) + public void Subscribe(string[] channels, string[] channelGroups, SubscriptionCursor cursor) { - Subscribe(channels, channelGroups); + Subscribe(channels, channelGroups, cursor); } public void UnsubscribeAll() diff --git a/src/UnitTests/AcceptanceTests/Features/event-engine/happy-path.feature b/src/UnitTests/AcceptanceTests/Features/event-engine/happy-path.feature index d9e953149..2ff925f57 100644 --- a/src/UnitTests/AcceptanceTests/Features/event-engine/happy-path.feature +++ b/src/UnitTests/AcceptanceTests/Features/event-engine/happy-path.feature @@ -20,8 +20,45 @@ Feature: Event Engine | event | RECEIVE_SUCCESS | | invocation | CANCEL_RECEIVE_MESSAGES | | invocation | EMIT_MESSAGES | + | invocation | RECEIVE_MESSAGES | + + @contract=restoringSubscribe + Scenario: Successfully restore subscribe + When I subscribe with timetoken 42 + Then I receive the message in my subscribe response + And I observe the following: + | type | name | + | event | SUBSCRIPTION_RESTORED | + | invocation | HANDSHAKE | + | event | HANDSHAKE_SUCCESS | + | invocation | CANCEL_HANDSHAKE | | invocation | EMIT_STATUS | | invocation | RECEIVE_MESSAGES | + | event | RECEIVE_SUCCESS | + | invocation | CANCEL_RECEIVE_MESSAGES | + | invocation | EMIT_MESSAGES | + | invocation | RECEIVE_MESSAGES | + + @contract=restoringSubscribeWithFailures + Scenario: Successfully restore subscribe with failures + Given a linear reconnection policy with 3 retries + When I subscribe with timetoken 42 + Then I receive the message in my subscribe response + And I observe the following: + | type | name | + | event | SUBSCRIPTION_RESTORED | + | invocation | HANDSHAKE | + | event | HANDSHAKE_FAILURE | + | invocation | CANCEL_HANDSHAKE | + | invocation | HANDSHAKE_RECONNECT | + | event | HANDSHAKE_RECONNECT_SUCCESS | + | invocation | CANCEL_HANDSHAKE_RECONNECT | + | invocation | EMIT_STATUS | + | invocation | RECEIVE_MESSAGES | + | event | RECEIVE_SUCCESS | + | invocation | CANCEL_RECEIVE_MESSAGES | + | invocation | EMIT_MESSAGES | + | invocation | RECEIVE_MESSAGES | @contract=subscribeHandshakeFailure Scenario: Complete handshake failure @@ -70,7 +107,6 @@ Feature: Event Engine | event | RECEIVE_SUCCESS | | invocation | CANCEL_RECEIVE_MESSAGES | | invocation | EMIT_MESSAGES | - | invocation | EMIT_STATUS | | invocation | RECEIVE_MESSAGES | @contract=subscribeReceivingRecovery @@ -92,5 +128,4 @@ Feature: Event Engine | event | RECEIVE_RECONNECT_SUCCESS | | invocation | CANCEL_RECEIVE_RECONNECT | | invocation | EMIT_MESSAGES | - | invocation | EMIT_STATUS | | invocation | RECEIVE_MESSAGES | \ No newline at end of file diff --git a/src/UnitTests/AcceptanceTests/Features/event-engine/happy-path.feature.cs b/src/UnitTests/AcceptanceTests/Features/event-engine/happy-path.feature.cs index 0089df0fa..c5f4e54a6 100644 --- a/src/UnitTests/AcceptanceTests/Features/event-engine/happy-path.feature.cs +++ b/src/UnitTests/AcceptanceTests/Features/event-engine/happy-path.feature.cs @@ -144,9 +144,6 @@ public void SuccessfullyReceiveMessages() table1.AddRow(new string[] { "invocation", "EMIT_MESSAGES"}); - table1.AddRow(new string[] { - "invocation", - "EMIT_STATUS"}); table1.AddRow(new string[] { "invocation", "RECEIVE_MESSAGES"}); @@ -157,6 +154,154 @@ public void SuccessfullyReceiveMessages() this.ScenarioCleanup(); } + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Successfully restore subscribe")] + [NUnit.Framework.CategoryAttribute("contract=restoringSubscribe")] + public void SuccessfullyRestoreSubscribe() + { + string[] tagsOfScenario = new string[] { + "contract=restoringSubscribe"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Successfully restore subscribe", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 26 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 5 + this.FeatureBackground(); +#line hidden +#line 27 + testRunner.When("I subscribe with timetoken 42", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 28 + testRunner.Then("I receive the message in my subscribe response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] { + "type", + "name"}); + table2.AddRow(new string[] { + "event", + "SUBSCRIPTION_RESTORED"}); + table2.AddRow(new string[] { + "invocation", + "HANDSHAKE"}); + table2.AddRow(new string[] { + "event", + "HANDSHAKE_SUCCESS"}); + table2.AddRow(new string[] { + "invocation", + "CANCEL_HANDSHAKE"}); + table2.AddRow(new string[] { + "invocation", + "EMIT_STATUS"}); + table2.AddRow(new string[] { + "invocation", + "RECEIVE_MESSAGES"}); + table2.AddRow(new string[] { + "event", + "RECEIVE_SUCCESS"}); + table2.AddRow(new string[] { + "invocation", + "CANCEL_RECEIVE_MESSAGES"}); + table2.AddRow(new string[] { + "invocation", + "EMIT_MESSAGES"}); + table2.AddRow(new string[] { + "invocation", + "RECEIVE_MESSAGES"}); +#line 29 + testRunner.And("I observe the following:", ((string)(null)), table2, "And "); +#line hidden + } + this.ScenarioCleanup(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Successfully restore subscribe with failures")] + [NUnit.Framework.CategoryAttribute("contract=restoringSubscribeWithFailures")] + public void SuccessfullyRestoreSubscribeWithFailures() + { + string[] tagsOfScenario = new string[] { + "contract=restoringSubscribeWithFailures"}; + System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Successfully restore subscribe with failures", null, tagsOfScenario, argumentsOfScenario, featureTags); +#line 43 + this.ScenarioInitialize(scenarioInfo); +#line hidden + if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); +#line 5 + this.FeatureBackground(); +#line hidden +#line 44 + testRunner.Given("a linear reconnection policy with 3 retries", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line hidden +#line 45 + testRunner.When("I subscribe with timetoken 42", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 46 + testRunner.Then("I receive the message in my subscribe response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + TechTalk.SpecFlow.Table table3 = new TechTalk.SpecFlow.Table(new string[] { + "type", + "name"}); + table3.AddRow(new string[] { + "event", + "SUBSCRIPTION_RESTORED"}); + table3.AddRow(new string[] { + "invocation", + "HANDSHAKE"}); + table3.AddRow(new string[] { + "event", + "HANDSHAKE_FAILURE"}); + table3.AddRow(new string[] { + "invocation", + "CANCEL_HANDSHAKE"}); + table3.AddRow(new string[] { + "invocation", + "HANDSHAKE_RECONNECT"}); + table3.AddRow(new string[] { + "event", + "HANDSHAKE_RECONNECT_SUCCESS"}); + table3.AddRow(new string[] { + "invocation", + "CANCEL_HANDSHAKE_RECONNECT"}); + table3.AddRow(new string[] { + "invocation", + "EMIT_STATUS"}); + table3.AddRow(new string[] { + "invocation", + "RECEIVE_MESSAGES"}); + table3.AddRow(new string[] { + "event", + "RECEIVE_SUCCESS"}); + table3.AddRow(new string[] { + "invocation", + "CANCEL_RECEIVE_MESSAGES"}); + table3.AddRow(new string[] { + "invocation", + "EMIT_MESSAGES"}); + table3.AddRow(new string[] { + "invocation", + "RECEIVE_MESSAGES"}); +#line 47 + testRunner.And("I observe the following:", ((string)(null)), table3, "And "); +#line hidden + } + this.ScenarioCleanup(); + } + [NUnit.Framework.TestAttribute()] [NUnit.Framework.DescriptionAttribute("Complete handshake failure")] [NUnit.Framework.CategoryAttribute("contract=subscribeHandshakeFailure")] @@ -166,7 +311,7 @@ public void CompleteHandshakeFailure() "contract=subscribeHandshakeFailure"}; System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Complete handshake failure", null, tagsOfScenario, argumentsOfScenario, featureTags); -#line 27 +#line 64 this.ScenarioInitialize(scenarioInfo); #line hidden if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) @@ -179,71 +324,71 @@ public void CompleteHandshakeFailure() #line 5 this.FeatureBackground(); #line hidden -#line 28 +#line 65 testRunner.Given("a linear reconnection policy with 3 retries", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line hidden -#line 29 +#line 66 testRunner.When("I subscribe", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden -#line 30 +#line 67 testRunner.Then("I receive an error in my subscribe response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden - TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] { + TechTalk.SpecFlow.Table table4 = new TechTalk.SpecFlow.Table(new string[] { "type", "name"}); - table2.AddRow(new string[] { + table4.AddRow(new string[] { "event", "SUBSCRIPTION_CHANGED"}); - table2.AddRow(new string[] { + table4.AddRow(new string[] { "invocation", "HANDSHAKE"}); - table2.AddRow(new string[] { + table4.AddRow(new string[] { "event", "HANDSHAKE_FAILURE"}); - table2.AddRow(new string[] { + table4.AddRow(new string[] { "invocation", "CANCEL_HANDSHAKE"}); - table2.AddRow(new string[] { + table4.AddRow(new string[] { "invocation", "HANDSHAKE_RECONNECT"}); - table2.AddRow(new string[] { + table4.AddRow(new string[] { "event", "HANDSHAKE_RECONNECT_FAILURE"}); - table2.AddRow(new string[] { + table4.AddRow(new string[] { "invocation", "CANCEL_HANDSHAKE_RECONNECT"}); - table2.AddRow(new string[] { + table4.AddRow(new string[] { "invocation", "HANDSHAKE_RECONNECT"}); - table2.AddRow(new string[] { + table4.AddRow(new string[] { "event", "HANDSHAKE_RECONNECT_FAILURE"}); - table2.AddRow(new string[] { + table4.AddRow(new string[] { "invocation", "CANCEL_HANDSHAKE_RECONNECT"}); - table2.AddRow(new string[] { + table4.AddRow(new string[] { "invocation", "HANDSHAKE_RECONNECT"}); - table2.AddRow(new string[] { + table4.AddRow(new string[] { "event", "HANDSHAKE_RECONNECT_FAILURE"}); - table2.AddRow(new string[] { + table4.AddRow(new string[] { "invocation", "CANCEL_HANDSHAKE_RECONNECT"}); - table2.AddRow(new string[] { + table4.AddRow(new string[] { "invocation", "HANDSHAKE_RECONNECT"}); - table2.AddRow(new string[] { + table4.AddRow(new string[] { "event", "HANDSHAKE_RECONNECT_GIVEUP"}); - table2.AddRow(new string[] { + table4.AddRow(new string[] { "invocation", "CANCEL_HANDSHAKE_RECONNECT"}); - table2.AddRow(new string[] { + table4.AddRow(new string[] { "invocation", "EMIT_STATUS"}); -#line 31 - testRunner.And("I observe the following:", ((string)(null)), table2, "And "); +#line 68 + testRunner.And("I observe the following:", ((string)(null)), table4, "And "); #line hidden } this.ScenarioCleanup(); @@ -258,7 +403,7 @@ public void HandshakeFailureRecovery() "contract=subscribeHandshakeRecovery"}; System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Handshake failure recovery", null, tagsOfScenario, argumentsOfScenario, featureTags); -#line 52 +#line 89 this.ScenarioInitialize(scenarioInfo); #line hidden if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) @@ -271,71 +416,68 @@ public void HandshakeFailureRecovery() #line 5 this.FeatureBackground(); #line hidden -#line 53 +#line 90 testRunner.Given("a linear reconnection policy with 3 retries", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line hidden -#line 54 +#line 91 testRunner.When("I subscribe", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden -#line 55 +#line 92 testRunner.Then("I receive the message in my subscribe response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden - TechTalk.SpecFlow.Table table3 = new TechTalk.SpecFlow.Table(new string[] { + TechTalk.SpecFlow.Table table5 = new TechTalk.SpecFlow.Table(new string[] { "type", "name"}); - table3.AddRow(new string[] { + table5.AddRow(new string[] { "event", "SUBSCRIPTION_CHANGED"}); - table3.AddRow(new string[] { + table5.AddRow(new string[] { "invocation", "HANDSHAKE"}); - table3.AddRow(new string[] { + table5.AddRow(new string[] { "event", "HANDSHAKE_FAILURE"}); - table3.AddRow(new string[] { + table5.AddRow(new string[] { "invocation", "CANCEL_HANDSHAKE"}); - table3.AddRow(new string[] { + table5.AddRow(new string[] { "invocation", "HANDSHAKE_RECONNECT"}); - table3.AddRow(new string[] { + table5.AddRow(new string[] { "event", "HANDSHAKE_RECONNECT_FAILURE"}); - table3.AddRow(new string[] { + table5.AddRow(new string[] { "invocation", "CANCEL_HANDSHAKE_RECONNECT"}); - table3.AddRow(new string[] { + table5.AddRow(new string[] { "invocation", "HANDSHAKE_RECONNECT"}); - table3.AddRow(new string[] { + table5.AddRow(new string[] { "event", "HANDSHAKE_RECONNECT_SUCCESS"}); - table3.AddRow(new string[] { + table5.AddRow(new string[] { "invocation", "CANCEL_HANDSHAKE_RECONNECT"}); - table3.AddRow(new string[] { + table5.AddRow(new string[] { "invocation", "EMIT_STATUS"}); - table3.AddRow(new string[] { + table5.AddRow(new string[] { "invocation", "RECEIVE_MESSAGES"}); - table3.AddRow(new string[] { + table5.AddRow(new string[] { "event", "RECEIVE_SUCCESS"}); - table3.AddRow(new string[] { + table5.AddRow(new string[] { "invocation", "CANCEL_RECEIVE_MESSAGES"}); - table3.AddRow(new string[] { + table5.AddRow(new string[] { "invocation", "EMIT_MESSAGES"}); - table3.AddRow(new string[] { - "invocation", - "EMIT_STATUS"}); - table3.AddRow(new string[] { + table5.AddRow(new string[] { "invocation", "RECEIVE_MESSAGES"}); -#line 56 - testRunner.And("I observe the following:", ((string)(null)), table3, "And "); +#line 93 + testRunner.And("I observe the following:", ((string)(null)), table5, "And "); #line hidden } this.ScenarioCleanup(); @@ -350,7 +492,7 @@ public void ReceivingFailureRecovery() "contract=subscribeReceivingRecovery"}; System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary(); TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Receiving failure recovery", null, tagsOfScenario, argumentsOfScenario, featureTags); -#line 77 +#line 113 this.ScenarioInitialize(scenarioInfo); #line hidden if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags))) @@ -363,62 +505,59 @@ public void ReceivingFailureRecovery() #line 5 this.FeatureBackground(); #line hidden -#line 78 +#line 114 testRunner.Given("a linear reconnection policy with 3 retries", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); #line hidden -#line 79 +#line 115 testRunner.When("I subscribe", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden -#line 80 +#line 116 testRunner.Then("I receive the message in my subscribe response", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden - TechTalk.SpecFlow.Table table4 = new TechTalk.SpecFlow.Table(new string[] { + TechTalk.SpecFlow.Table table6 = new TechTalk.SpecFlow.Table(new string[] { "type", "name"}); - table4.AddRow(new string[] { + table6.AddRow(new string[] { "event", "SUBSCRIPTION_CHANGED"}); - table4.AddRow(new string[] { + table6.AddRow(new string[] { "invocation", "HANDSHAKE"}); - table4.AddRow(new string[] { + table6.AddRow(new string[] { "event", "HANDSHAKE_SUCCESS"}); - table4.AddRow(new string[] { + table6.AddRow(new string[] { "invocation", "CANCEL_HANDSHAKE"}); - table4.AddRow(new string[] { + table6.AddRow(new string[] { "invocation", "EMIT_STATUS"}); - table4.AddRow(new string[] { + table6.AddRow(new string[] { "invocation", "RECEIVE_MESSAGES"}); - table4.AddRow(new string[] { + table6.AddRow(new string[] { "event", "RECEIVE_FAILURE"}); - table4.AddRow(new string[] { + table6.AddRow(new string[] { "invocation", "CANCEL_RECEIVE_MESSAGES"}); - table4.AddRow(new string[] { + table6.AddRow(new string[] { "invocation", "RECEIVE_RECONNECT"}); - table4.AddRow(new string[] { + table6.AddRow(new string[] { "event", "RECEIVE_RECONNECT_SUCCESS"}); - table4.AddRow(new string[] { + table6.AddRow(new string[] { "invocation", "CANCEL_RECEIVE_RECONNECT"}); - table4.AddRow(new string[] { + table6.AddRow(new string[] { "invocation", "EMIT_MESSAGES"}); - table4.AddRow(new string[] { - "invocation", - "EMIT_STATUS"}); - table4.AddRow(new string[] { + table6.AddRow(new string[] { "invocation", "RECEIVE_MESSAGES"}); -#line 81 - testRunner.And("I observe the following:", ((string)(null)), table4, "And "); +#line 117 + testRunner.And("I observe the following:", ((string)(null)), table6, "And "); #line hidden } this.ScenarioCleanup(); diff --git a/src/UnitTests/AcceptanceTests/Steps/EventEngineSteps.cs b/src/UnitTests/AcceptanceTests/Steps/EventEngineSteps.cs index e03b13e13..0a6b235df 100644 --- a/src/UnitTests/AcceptanceTests/Steps/EventEngineSteps.cs +++ b/src/UnitTests/AcceptanceTests/Steps/EventEngineSteps.cs @@ -20,7 +20,7 @@ namespace AcceptanceTests.Steps [Binding] public class EventEngineSteps { - public static bool enableIntenalPubnubLogging = false; + public static bool enableIntenalPubnubLogging = true; public static string currentFeature = string.Empty; public static string currentContract = string.Empty; public static bool betaVersion = false; @@ -315,6 +315,36 @@ public void WhenISubscribe() } } + [When(@"I subscribe with timetoken (.*)")] + public void WhenISubscribeWithTimetoken(int p0) + { + pn = new Pubnub(config); + pn.PubnubUnitTest = unitTest; + pn.PubnubUnitTest.EventTypeList?.Clear(); + + messageReceivedEvent = new ManualResetEvent(false); + statusReceivedEvent = new ManualResetEvent(false); + + pn.AddListener(subscribeCallback); + pn.Subscribe() + .Channels(channel.Split(',')) + .ChannelGroups(channelGroup.Split(',')) + .WithTimetoken(p0) + .Execute(); + statusReceivedEvent.WaitOne (60*1000); + if (pnStatus != null && pnStatus.Category == PNStatusCategory.PNConnectedCategory) + { + //All good. + } + else + { + if (currentContract == "simpleSubscribe") + { + Assert.Fail("WhenISubscribe failed."); + } + } + } + [When(@"I publish a message")] public async Task WhenIPublishAMessage() { @@ -385,6 +415,5 @@ public void ThenIReceiveAnError() { Assert.True(pnStatus != null && pnStatus.Error); } - } } From 29e86f731893cf668d603d3eca2884bc520f3bad Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Thu, 24 Aug 2023 13:14:33 +0530 Subject: [PATCH 49/56] Unsub state sub retstore event transition --- src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs | 2 +- .../PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs index 3f1891ef2..caf39d606 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs @@ -123,7 +123,7 @@ public void Execute() string[] channelNames = this.subscribeChannelNames != null ? this.subscribeChannelNames.ToArray() : null; string[] channelGroupNames = this.subscribeChannelGroupNames != null ? this.subscribeChannelGroupNames.ToArray() : null; SubscriptionCursor cursor = null; - if (subscribeTimetoken >= 0) + if (subscribeTimetoken >= 1) { cursor = new SubscriptionCursor { Timetoken = subscribeTimetoken, Region = 0 }; } diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs index 14195561d..30a98ec21 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs @@ -22,7 +22,7 @@ public override TransitionResult Transition(Core.IEvent e) ReconnectionConfiguration = this.ReconnectionConfiguration }, - Events.SubscriptionRestoredEvent subscriptionRestored => new States.ReceivingState() + Events.SubscriptionRestoredEvent subscriptionRestored => new States.HandshakingState() { Channels = subscriptionRestored.Channels, ChannelGroups = subscriptionRestored.ChannelGroups, From f961f96470740430a2db2e2457e206b5ceefc395 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Thu, 24 Aug 2023 16:00:47 +0530 Subject: [PATCH 50/56] fixes for sub with tt amid failures --- .../Subscribe/Effects/HandshakeEffectHandler.cs | 9 ++++++++- .../EventEngine/Subscribe/Events/SubscriptionEvents.cs | 1 + .../Subscribe/States/HandshakeReconnectingState.cs | 1 + .../EventEngine/Subscribe/States/HandshakingState.cs | 1 + .../EventEngine/Subscribe/States/UnsubscribedState.cs | 1 + 5 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs index 1a8d27c20..7503dbfa0 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs @@ -46,6 +46,13 @@ public override async Task Run(HandshakeInvocation invocation) }; } } + else + { + if (invocation.Cursor != null && invocation.Cursor.Timetoken != null) + { + cursor = invocation.Cursor; + } + } switch (invocation) { @@ -56,7 +63,7 @@ public override async Task Run(HandshakeInvocation invocation) eventQueue.Enqueue(new Events.HandshakeReconnectSuccessEvent() { Cursor = cursor, Status = response.Item2 }); break; case { } when response.Item2.Error: - eventQueue.Enqueue(new Events.HandshakeFailureEvent() { Status = response.Item2, Channels = invocation.Channels, ChannelGroups = invocation.ChannelGroups}); + eventQueue.Enqueue(new Events.HandshakeFailureEvent() { Status = response.Item2, Cursor = cursor, Channels = invocation.Channels, ChannelGroups = invocation.ChannelGroups}); break; case { }: eventQueue.Enqueue(new Events.HandshakeSuccessEvent() { Cursor = cursor, Status = response.Item2 }); diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs index 37e65f7ac..a9776544a 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Events/SubscriptionEvents.cs @@ -29,6 +29,7 @@ public class HandshakeSuccessEvent : Core.IEvent { public class HandshakeFailureEvent : Core.IEvent { public IEnumerable Channels; public IEnumerable ChannelGroups; + public SubscriptionCursor Cursor; public PNStatus Status; public int AttemptedRetries; public virtual string Name { get; set; } = "HANDSHAKE_FAILURE"; diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs index e86c9d9cc..1cc6dfa25 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs @@ -16,6 +16,7 @@ public class HandshakeReconnectingState : SubscriptionState { Channels = this.Channels, ChannelGroups = this.ChannelGroups, + Cursor = this.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration, AttemptedRetries = this.AttemptedRetries }.AsArray(); diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs index f127709fb..c08b43b3c 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs @@ -43,6 +43,7 @@ public override TransitionResult Transition(IEvent e) { Channels = handshakeFailure.Channels, ChannelGroups = handshakeFailure.ChannelGroups, + Cursor = handshakeFailure.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration, AttemptedRetries = 1 }, diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs index 30a98ec21..00ff5137c 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs @@ -34,6 +34,7 @@ public override TransitionResult Transition(Core.IEvent e) { Channels = handshakeFailure.Channels, ChannelGroups = handshakeFailure.ChannelGroups, + Cursor = handshakeFailure.Cursor, ReconnectionConfiguration = this.ReconnectionConfiguration }, _ => null From 602157cfbb3c0502ba70747831f506b605c4a7ed Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Thu, 24 Aug 2023 16:06:44 +0530 Subject: [PATCH 51/56] specflow auto generated --- .../AcceptanceTests/Features/grant-token.feature.cs | 6 +++--- .../AcceptanceTests/Features/revoke-token.feature.cs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/UnitTests/AcceptanceTests/Features/grant-token.feature.cs b/src/UnitTests/AcceptanceTests/Features/grant-token.feature.cs index c8bb56301..a1aaaf549 100644 --- a/src/UnitTests/AcceptanceTests/Features/grant-token.feature.cs +++ b/src/UnitTests/AcceptanceTests/Features/grant-token.feature.cs @@ -37,9 +37,9 @@ public partial class GrantAnAccessTokenFeature public virtual void FeatureSetup() { testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); - TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Features", "Grant an access token", " As a PubNub customer I want to restrict and allow access to\n specific PubNub r" + - "esources (channels, channel groups, uuids)\n by my user base (both people and de" + - "vices) which are each\n identified by a unique UUID.", ProgrammingLanguage.CSharp, featureTags); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Features", "Grant an access token", " As a PubNub customer I want to restrict and allow access to\r\n specific PubNub " + + "resources (channels, channel groups, uuids)\r\n by my user base (both people and " + + "devices) which are each\r\n identified by a unique UUID.", ProgrammingLanguage.CSharp, featureTags); testRunner.OnFeatureStart(featureInfo); } diff --git a/src/UnitTests/AcceptanceTests/Features/revoke-token.feature.cs b/src/UnitTests/AcceptanceTests/Features/revoke-token.feature.cs index f98f833b4..d5a85c045 100644 --- a/src/UnitTests/AcceptanceTests/Features/revoke-token.feature.cs +++ b/src/UnitTests/AcceptanceTests/Features/revoke-token.feature.cs @@ -39,8 +39,8 @@ public partial class RevokeAnAccessTokenFeature public virtual void FeatureSetup() { testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); - TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Features", "Revoke an access token", " As a PubNub customer I want to withdraw existing permission for\n specific PubN" + - "ub resources by revoking corresponding tokens.", ProgrammingLanguage.CSharp, featureTags); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Features", "Revoke an access token", " As a PubNub customer I want to withdraw existing permission for\r\n specific Pub" + + "Nub resources by revoking corresponding tokens.", ProgrammingLanguage.CSharp, featureTags); testRunner.OnFeatureStart(featureInfo); } From 793d9d41c705182247c90871c28ba1191da618b6 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Tue, 29 Aug 2023 22:06:07 +0530 Subject: [PATCH 52/56] Presence States WIP --- .../Context/ReconnectionConfiguration.cs | 9 ++- .../Context/ReconnectionDelayUtil.cs | 9 ++- .../Presence/Common/CommonPresenceTypes.cs | 16 +++++ .../Presence/Events/PresenceEvents.cs | 39 +++++++++++ .../Invocations/PresenceInvocations.cs | 47 +++++++++++++ .../Presence/PresenceEventEngine.cs | 11 +++ .../Presence/PresenceEventEngineFactory.cs | 11 +++ .../Presence/States/HeartbeatCooldownState.cs | 17 +++++ .../Presence/States/HeartbeatInactiveState.cs | 17 +++++ .../States/HeartbeatReconnectingState.cs | 17 +++++ .../Presence/States/HeartbeatStoppedState.cs | 17 +++++ .../Presence/States/HeartbeatingState.cs | 67 +++++++++++++++++++ .../Subscribe/Common/CommonSubscribeTypes.cs | 2 +- .../Effects/HandshakeEffectHandler.cs | 2 +- .../Effects/ReceivingEffectHandler.cs | 5 +- .../Invocations/SubscriptionInvocations.cs | 2 +- .../Subscribe/States/HandshakeFailedState.cs | 2 +- .../States/HandshakeReconnectingState.cs | 2 +- .../Subscribe/States/HandshakeStoppedState.cs | 2 +- .../Subscribe/States/HandshakingState.cs | 2 +- .../Subscribe/States/ReceiveFailedState.cs | 2 +- .../States/ReceiveReconnectingState.cs | 2 +- .../Subscribe/States/ReceiveStoppedState.cs | 2 +- .../Subscribe/States/ReceivingState.cs | 2 +- .../Subscribe/States/UnsubscribedState.cs | 2 +- src/Api/PubnubApi/PubnubApi.csproj | 4 ++ src/Api/PubnubApiPCL/PubnubApiPCL.csproj | 7 +- src/Api/PubnubApiUWP/PubnubApiUWP.csproj | 7 +- .../HandshakeReconnectingStateTransition.cs | 2 +- .../EventEngine/HandshakingStateTransition.cs | 2 +- .../ReceiveFailedStateTransition.cs | 2 +- .../ReceiveReconnectingStateTransition.cs | 2 +- .../ReceiveStoppedStateTransition.cs | 2 +- .../EventEngine/ReceivingStateTransition.cs | 2 +- .../UnsubscribedStateTransition.cs | 2 +- 35 files changed, 306 insertions(+), 32 deletions(-) rename src/Api/PubnubApi/EventEngine/{Subscribe => }/Context/ReconnectionConfiguration.cs (70%) rename src/Api/PubnubApi/EventEngine/{Subscribe => }/Context/ReconnectionDelayUtil.cs (84%) create mode 100644 src/Api/PubnubApi/EventEngine/Presence/Common/CommonPresenceTypes.cs create mode 100644 src/Api/PubnubApi/EventEngine/Presence/Events/PresenceEvents.cs create mode 100644 src/Api/PubnubApi/EventEngine/Presence/Invocations/PresenceInvocations.cs create mode 100644 src/Api/PubnubApi/EventEngine/Presence/PresenceEventEngine.cs create mode 100644 src/Api/PubnubApi/EventEngine/Presence/PresenceEventEngineFactory.cs create mode 100644 src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatCooldownState.cs create mode 100644 src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatInactiveState.cs create mode 100644 src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatReconnectingState.cs create mode 100644 src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatStoppedState.cs create mode 100644 src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatingState.cs diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Context/ReconnectionConfiguration.cs b/src/Api/PubnubApi/EventEngine/Context/ReconnectionConfiguration.cs similarity index 70% rename from src/Api/PubnubApi/EventEngine/Subscribe/Context/ReconnectionConfiguration.cs rename to src/Api/PubnubApi/EventEngine/Context/ReconnectionConfiguration.cs index 7134c2891..43c0baabc 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Context/ReconnectionConfiguration.cs +++ b/src/Api/PubnubApi/EventEngine/Context/ReconnectionConfiguration.cs @@ -1,7 +1,11 @@ using System; -namespace PubnubApi.EventEngine.Subscribe.Context +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PubnubApi.EventEngine.Context { - public class ReconnectionConfiguration + public class ReconnectionConfiguration { public PNReconnectionPolicy ReconnectionPolicy { get; set; } public int MaximumReconnectionRetries { get; set; } @@ -13,4 +17,3 @@ public ReconnectionConfiguration(PNReconnectionPolicy policy, int maximumReconne } } } - diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Context/ReconnectionDelayUtil.cs b/src/Api/PubnubApi/EventEngine/Context/ReconnectionDelayUtil.cs similarity index 84% rename from src/Api/PubnubApi/EventEngine/Subscribe/Context/ReconnectionDelayUtil.cs rename to src/Api/PubnubApi/EventEngine/Context/ReconnectionDelayUtil.cs index 92fe9f5ac..d5ada3198 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Context/ReconnectionDelayUtil.cs +++ b/src/Api/PubnubApi/EventEngine/Context/ReconnectionDelayUtil.cs @@ -1,7 +1,11 @@ using System; -namespace PubnubApi.EventEngine.Subscribe.Context +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PubnubApi.EventEngine.Context { - public static class ReconnectionDelayUtil + public static class ReconnectionDelayUtil { public static int CalculateDelay(PNReconnectionPolicy policy, int attempts) { @@ -27,4 +31,3 @@ public static bool shouldRetry(ReconnectionConfiguration reconnectionConfigurati } } } - diff --git a/src/Api/PubnubApi/EventEngine/Presence/Common/CommonPresenceTypes.cs b/src/Api/PubnubApi/EventEngine/Presence/Common/CommonPresenceTypes.cs new file mode 100644 index 000000000..d6f7b5c28 --- /dev/null +++ b/src/Api/PubnubApi/EventEngine/Presence/Common/CommonPresenceTypes.cs @@ -0,0 +1,16 @@ +using PubnubApi.EventEngine.Context; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PubnubApi.EventEngine.Presence.Common +{ + public abstract class PresenceState : Core.State + { + public IEnumerable Channels { get; set;} + public IEnumerable ChannelGroups { get; set;} + //public SubscriptionCursor Cursor; + public ReconnectionConfiguration ReconnectionConfiguration; + } +} diff --git a/src/Api/PubnubApi/EventEngine/Presence/Events/PresenceEvents.cs b/src/Api/PubnubApi/EventEngine/Presence/Events/PresenceEvents.cs new file mode 100644 index 000000000..45d1be930 --- /dev/null +++ b/src/Api/PubnubApi/EventEngine/Presence/Events/PresenceEvents.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PubnubApi.EventEngine.Presence.Events +{ + public class JoinedEvent : Core.IEvent { + public IEnumerable Channels{ get; set; } + public IEnumerable ChannelGroups{ get; set; } + public string Name { get; set; } = "JOINED"; + } + public class LeftEvent : Core.IEvent { + public IEnumerable Channels{ get; set; } + public IEnumerable ChannelGroups{ get; set; } + public string Name { get; set; } = "LEFT"; + } + public class StateSetEvent : Core.IEvent { + public IEnumerable Channels{ get; set; } + public IEnumerable ChannelGroups{ get; set; } + public string Name { get; set; } = "STATE_SET"; + } + public class LeftAllEvent : Core.IEvent { + public string Name { get; set; } = "LEFT_ALL"; + } + public class HeartbeatSuccessEvent : Core.IEvent { + public PNStatus Status { get; set; } + public virtual string Name { get; set; } = "HEARTBEAT_SUCCESS"; + } + public class HeartbeatFailureEvent : Core.IEvent { + public PNStatus Status { get; set; } + public virtual string Name { get; set; } = "HEARTBEAT_FAILURE"; + } + public class DisconnectEvent : Core.IEvent { + public IEnumerable Channels{ get; set; } + public IEnumerable ChannelGroups{ get; set; } + public string Name { get; set; } = "DISCONNECT"; + } +} diff --git a/src/Api/PubnubApi/EventEngine/Presence/Invocations/PresenceInvocations.cs b/src/Api/PubnubApi/EventEngine/Presence/Invocations/PresenceInvocations.cs new file mode 100644 index 000000000..a96f5c8b3 --- /dev/null +++ b/src/Api/PubnubApi/EventEngine/Presence/Invocations/PresenceInvocations.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PubnubApi.EventEngine.Presence.Invocations +{ + //TODO: Bring EmitStatusInvocation into common folder for both presence and subscribe + public class EmitStatusInvocation : Core.IEffectInvocation { + // TODO merge status variables into one? + public PNStatusCategory StatusCategory; + public PNStatus Status; + public string Name { get; set; } = "EMIT_STATUS"; + + public EmitStatusInvocation(PNStatus status) + { + this.Status = status; + if (status != null) + { + this.StatusCategory = status.Category; + } + } + + public EmitStatusInvocation(PNStatusCategory category) + { + this.StatusCategory = category; + this.Status = new PNStatus() + { + Category = category, + }; + } + } + public class HeartbeatInvocation : Core.IEffectInvocation { + public IEnumerable Channels; + public IEnumerable ChannelGroups; + //public SubscriptionCursor Cursor; + // TODO if we need these, figure out how to pass them. + public Dictionary InitialSubscribeQueryParams = new Dictionary(); + public Dictionary ExternalQueryParams = new Dictionary(); + public virtual string Name { get; set; } = "HEARTBEAT"; + } + public class CancelHeartbeatInvocation : HeartbeatInvocation, Core.IEffectCancelInvocation + { + public override string Name { get; set; } = "CANCEL_HANDSHAKE"; + } + +} diff --git a/src/Api/PubnubApi/EventEngine/Presence/PresenceEventEngine.cs b/src/Api/PubnubApi/EventEngine/Presence/PresenceEventEngine.cs new file mode 100644 index 000000000..79f900efb --- /dev/null +++ b/src/Api/PubnubApi/EventEngine/Presence/PresenceEventEngine.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PubnubApi.EventEngine.Presence +{ + internal class PresenceEventEngine + { + } +} diff --git a/src/Api/PubnubApi/EventEngine/Presence/PresenceEventEngineFactory.cs b/src/Api/PubnubApi/EventEngine/Presence/PresenceEventEngineFactory.cs new file mode 100644 index 000000000..3723e71d2 --- /dev/null +++ b/src/Api/PubnubApi/EventEngine/Presence/PresenceEventEngineFactory.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PubnubApi.EventEngine.Presence +{ + internal class PresenceEventEngineFactory + { + } +} diff --git a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatCooldownState.cs b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatCooldownState.cs new file mode 100644 index 000000000..c14268a03 --- /dev/null +++ b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatCooldownState.cs @@ -0,0 +1,17 @@ +using PubnubApi.EventEngine.Core; +using PubnubApi.EventEngine.Presence.Common; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PubnubApi.EventEngine.Presence.States +{ + public class HeartbeatCooldownState : PresenceState + { + public override TransitionResult Transition(IEvent e) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatInactiveState.cs b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatInactiveState.cs new file mode 100644 index 000000000..cd7abaa54 --- /dev/null +++ b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatInactiveState.cs @@ -0,0 +1,17 @@ +using PubnubApi.EventEngine.Core; +using PubnubApi.EventEngine.Presence.Common; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PubnubApi.EventEngine.Presence.States +{ + public class HeartbeatInactiveState : PresenceState + { + public override TransitionResult Transition(IEvent e) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatReconnectingState.cs b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatReconnectingState.cs new file mode 100644 index 000000000..8048cc6ca --- /dev/null +++ b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatReconnectingState.cs @@ -0,0 +1,17 @@ +using PubnubApi.EventEngine.Core; +using PubnubApi.EventEngine.Presence.Common; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PubnubApi.EventEngine.Presence.States +{ + public class HeartbeatReconnectingState : PresenceState + { + public override TransitionResult Transition(IEvent e) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatStoppedState.cs b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatStoppedState.cs new file mode 100644 index 000000000..2f583fe76 --- /dev/null +++ b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatStoppedState.cs @@ -0,0 +1,17 @@ +using PubnubApi.EventEngine.Core; +using PubnubApi.EventEngine.Presence.Common; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PubnubApi.EventEngine.Presence.States +{ + public class HeartbeatStoppedState : PresenceState + { + public override TransitionResult Transition(IEvent e) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatingState.cs b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatingState.cs new file mode 100644 index 000000000..e96b3e343 --- /dev/null +++ b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatingState.cs @@ -0,0 +1,67 @@ +using PubnubApi.EventEngine.Core; +using PubnubApi.EventEngine.Presence.Common; +using PubnubApi.EventEngine.Presence.Invocations; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PubnubApi.EventEngine.Presence.States +{ + public class HeartbeatingState : PresenceState + { + public override IEnumerable OnEntry => new HeartbeatInvocation() + { Channels = this.Channels, ChannelGroups = this.ChannelGroups }.AsArray(); + + public override IEnumerable OnExit { get; } = new CancelHeartbeatInvocation().AsArray(); + + public override TransitionResult Transition(IEvent e) + { + return e switch + { + Events.LeftAllEvent leftAll => new HeartbeatInactiveState() + { + ReconnectionConfiguration = this.ReconnectionConfiguration + }.With(new EmitStatusInvocation(PNStatusCategory.PNDisconnectedCategory)), //TODO: Do we need PNLeaveCategory?, + + Events.JoinedEvent joined => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(joined.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(joined.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.LeftEvent left => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(left.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(left.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration + }.With(new EmitStatusInvocation(PNStatusCategory.PNDisconnectedCategory)), //TODO: Do we need PNLeaveCategory? + + Events.StateSetEvent stateSet => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(stateSet.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(stateSet.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.HeartbeatSuccessEvent heartbeatSuccess => new States.HeartbeatCooldownState() + { + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.HeartbeatFailureEvent heartbeatFailure => new States.HeartbeatReconnectingState() + { + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.DisconnectEvent disconnect => new States.HeartbeatStoppedState() + { + ReconnectionConfiguration = this.ReconnectionConfiguration, + }.With(new EmitStatusInvocation(PNStatusCategory.PNDisconnectedCategory)), //TODO: Do we need PNLeaveCategory?, + + _ => null + }; + } + } +} diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs index e9b56ffe8..2b27ff3e4 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Common/CommonSubscribeTypes.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; using System.Collections.Generic; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; namespace PubnubApi.EventEngine.Subscribe.Common { diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs index 7503dbfa0..0cc601f28 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/HandshakeEffectHandler.cs @@ -7,7 +7,7 @@ using PubnubApi.EndPoint; using PubnubApi.EventEngine.Common; using PubnubApi.EventEngine.Core; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using PubnubApi.EventEngine.Subscribe.Events; using PubnubApi.EventEngine.Subscribe.Invocations; using PubnubApi.EventEngine.Subscribe.Common; diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs index 5a0df5e77..84094878a 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs @@ -7,7 +7,7 @@ using PubnubApi.EndPoint; using PubnubApi.EventEngine.Common; using PubnubApi.EventEngine.Core; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using PubnubApi.EventEngine.Subscribe.Events; using PubnubApi.EventEngine.Subscribe.Invocations; using PubnubApi.EventEngine.Subscribe.Common; @@ -47,6 +47,9 @@ public override async Task Run(ReceiveMessagesInvocation invocation) case Invocations.ReceiveReconnectInvocation reconnectInvocation: eventQueue.Enqueue(new Events.ReceiveReconnectSuccessEvent() { Channels = invocation?.Channels, ChannelGroups = invocation?.ChannelGroups, Cursor = cursor, Status = response.Item2, Messages = response.Item1 }); break; + case { } when response.Item2.Error && response.Item2.StatusCode == 403: + eventQueue.Enqueue(new Events.ReceiveReconnectGiveUpEvent { Channels = invocation?.Channels, ChannelGroups = invocation?.ChannelGroups, Cursor = cursor, Status = response.Item2 }); + break; case { } when response.Item2.Error: eventQueue.Enqueue(new Events.ReceiveFailureEvent() { Cursor = invocation.Cursor, Status = response.Item2}); break; diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs index 840f7fac6..801eba604 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Invocations/SubscriptionInvocations.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; namespace PubnubApi.EventEngine.Subscribe.Invocations { public class EmitMessagesInvocation : Core.IEffectInvocation { diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeFailedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeFailedState.cs index 33d2c02c7..fa0ef9614 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeFailedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeFailedState.cs @@ -3,7 +3,7 @@ using System.Linq; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using PubnubApi.EventEngine.Subscribe.Invocations; namespace PubnubApi.EventEngine.Subscribe.States diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs index 1cc6dfa25..1be3fe93d 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeReconnectingState.cs @@ -3,7 +3,7 @@ using System.Linq; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using PubnubApi.EventEngine.Subscribe.Invocations; namespace PubnubApi.EventEngine.Subscribe.States diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeStoppedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeStoppedState.cs index 827a16f14..38aa5db57 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeStoppedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakeStoppedState.cs @@ -3,7 +3,7 @@ using System.Linq; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using PubnubApi.EventEngine.Subscribe.Invocations; namespace PubnubApi.EventEngine.Subscribe.States diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs index c08b43b3c..16c99a392 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/HandshakingState.cs @@ -3,7 +3,7 @@ using System.Linq; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using PubnubApi.EventEngine.Subscribe.Invocations; namespace PubnubApi.EventEngine.Subscribe.States diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveFailedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveFailedState.cs index 53ee6560d..2a2f11579 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveFailedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveFailedState.cs @@ -3,7 +3,7 @@ using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Invocations; using PubnubApi.EventEngine.Subscribe.Common; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using System.Linq; namespace PubnubApi.EventEngine.Subscribe.States diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs index 8cd6fc4ca..9b5629cf1 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveReconnectingState.cs @@ -3,7 +3,7 @@ using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Invocations; using PubnubApi.EventEngine.Subscribe.Common; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using System.Linq; namespace PubnubApi.EventEngine.Subscribe.States diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveStoppedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveStoppedState.cs index 23c1428f2..49494ede2 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveStoppedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceiveStoppedState.cs @@ -3,7 +3,7 @@ using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Invocations; using PubnubApi.EventEngine.Subscribe.Common; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using System.Linq; namespace PubnubApi.EventEngine.Subscribe.States diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs index 2c681c7b1..277168866 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/ReceivingState.cs @@ -3,7 +3,7 @@ using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Invocations; using PubnubApi.EventEngine.Subscribe.Common; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using System.Linq; namespace PubnubApi.EventEngine.Subscribe.States diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs b/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs index 00ff5137c..90e2072a6 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/States/UnsubscribedState.cs @@ -3,7 +3,7 @@ using System.Linq; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using PubnubApi.EventEngine.Subscribe.Invocations; namespace PubnubApi.EventEngine.Subscribe.States diff --git a/src/Api/PubnubApi/PubnubApi.csproj b/src/Api/PubnubApi/PubnubApi.csproj index b1ebf5097..b307b3763 100644 --- a/src/Api/PubnubApi/PubnubApi.csproj +++ b/src/Api/PubnubApi/PubnubApi.csproj @@ -142,4 +142,8 @@ + + + + diff --git a/src/Api/PubnubApiPCL/PubnubApiPCL.csproj b/src/Api/PubnubApiPCL/PubnubApiPCL.csproj index fbe8574ee..3b62b0059 100644 --- a/src/Api/PubnubApiPCL/PubnubApiPCL.csproj +++ b/src/Api/PubnubApiPCL/PubnubApiPCL.csproj @@ -215,14 +215,14 @@ Enum\ResponseType.cs + + - - @@ -918,11 +918,12 @@ + + - diff --git a/src/Api/PubnubApiUWP/PubnubApiUWP.csproj b/src/Api/PubnubApiUWP/PubnubApiUWP.csproj index 6b64e24a4..76124ec94 100644 --- a/src/Api/PubnubApiUWP/PubnubApiUWP.csproj +++ b/src/Api/PubnubApiUWP/PubnubApiUWP.csproj @@ -334,14 +334,14 @@ Enum\ResponseType.cs + + - - @@ -731,11 +731,12 @@ + + - diff --git a/src/UnitTests/PubnubApi.Tests/EventEngine/HandshakeReconnectingStateTransition.cs b/src/UnitTests/PubnubApi.Tests/EventEngine/HandshakeReconnectingStateTransition.cs index 9d214e61a..ac110ddf2 100644 --- a/src/UnitTests/PubnubApi.Tests/EventEngine/HandshakeReconnectingStateTransition.cs +++ b/src/UnitTests/PubnubApi.Tests/EventEngine/HandshakeReconnectingStateTransition.cs @@ -1,7 +1,7 @@ using NUnit.Framework; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using PubnubApi.EventEngine.Subscribe.Events; using PubnubApi.EventEngine.Subscribe.Invocations; using PubnubApi.EventEngine.Subscribe.States; diff --git a/src/UnitTests/PubnubApi.Tests/EventEngine/HandshakingStateTransition.cs b/src/UnitTests/PubnubApi.Tests/EventEngine/HandshakingStateTransition.cs index 55e75a9af..c9242b2b0 100644 --- a/src/UnitTests/PubnubApi.Tests/EventEngine/HandshakingStateTransition.cs +++ b/src/UnitTests/PubnubApi.Tests/EventEngine/HandshakingStateTransition.cs @@ -1,7 +1,7 @@ using NUnit.Framework; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using PubnubApi.EventEngine.Subscribe.Events; using PubnubApi.EventEngine.Subscribe.Invocations; using PubnubApi.EventEngine.Subscribe.States; diff --git a/src/UnitTests/PubnubApi.Tests/EventEngine/ReceiveFailedStateTransition.cs b/src/UnitTests/PubnubApi.Tests/EventEngine/ReceiveFailedStateTransition.cs index e4f85e7a8..b64ba5db1 100644 --- a/src/UnitTests/PubnubApi.Tests/EventEngine/ReceiveFailedStateTransition.cs +++ b/src/UnitTests/PubnubApi.Tests/EventEngine/ReceiveFailedStateTransition.cs @@ -1,7 +1,7 @@ using NUnit.Framework; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using PubnubApi.EventEngine.Subscribe.Events; using PubnubApi.EventEngine.Subscribe.States; using System.Linq; diff --git a/src/UnitTests/PubnubApi.Tests/EventEngine/ReceiveReconnectingStateTransition.cs b/src/UnitTests/PubnubApi.Tests/EventEngine/ReceiveReconnectingStateTransition.cs index 3b265a847..26ce07fd7 100644 --- a/src/UnitTests/PubnubApi.Tests/EventEngine/ReceiveReconnectingStateTransition.cs +++ b/src/UnitTests/PubnubApi.Tests/EventEngine/ReceiveReconnectingStateTransition.cs @@ -1,7 +1,7 @@ using NUnit.Framework; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using PubnubApi.EventEngine.Subscribe.Events; using PubnubApi.EventEngine.Subscribe.Invocations; using PubnubApi.EventEngine.Subscribe.States; diff --git a/src/UnitTests/PubnubApi.Tests/EventEngine/ReceiveStoppedStateTransition.cs b/src/UnitTests/PubnubApi.Tests/EventEngine/ReceiveStoppedStateTransition.cs index f560f8a14..11bc89c35 100644 --- a/src/UnitTests/PubnubApi.Tests/EventEngine/ReceiveStoppedStateTransition.cs +++ b/src/UnitTests/PubnubApi.Tests/EventEngine/ReceiveStoppedStateTransition.cs @@ -1,7 +1,7 @@ using NUnit.Framework; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using PubnubApi.EventEngine.Subscribe.Events; using PubnubApi.EventEngine.Subscribe.States; using System.Linq; diff --git a/src/UnitTests/PubnubApi.Tests/EventEngine/ReceivingStateTransition.cs b/src/UnitTests/PubnubApi.Tests/EventEngine/ReceivingStateTransition.cs index e908e0087..16d759f04 100644 --- a/src/UnitTests/PubnubApi.Tests/EventEngine/ReceivingStateTransition.cs +++ b/src/UnitTests/PubnubApi.Tests/EventEngine/ReceivingStateTransition.cs @@ -1,7 +1,7 @@ using NUnit.Framework; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using PubnubApi.EventEngine.Subscribe.Events; using PubnubApi.EventEngine.Subscribe.Invocations; using PubnubApi.EventEngine.Subscribe.States; diff --git a/src/UnitTests/PubnubApi.Tests/EventEngine/UnsubscribedStateTransition.cs b/src/UnitTests/PubnubApi.Tests/EventEngine/UnsubscribedStateTransition.cs index 6147eec88..c3cf81119 100644 --- a/src/UnitTests/PubnubApi.Tests/EventEngine/UnsubscribedStateTransition.cs +++ b/src/UnitTests/PubnubApi.Tests/EventEngine/UnsubscribedStateTransition.cs @@ -1,7 +1,7 @@ using NUnit.Framework; using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Subscribe.Common; -using PubnubApi.EventEngine.Subscribe.Context; +using PubnubApi.EventEngine.Context; using PubnubApi.EventEngine.Subscribe.Events; using PubnubApi.EventEngine.Subscribe.States; using System.Linq; From dedcee2dddad07e2cc5621965fa1e9efef19c6a7 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Thu, 31 Aug 2023 12:22:03 +0530 Subject: [PATCH 53/56] removed status check --- .../EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs index 84094878a..c0d7169aa 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs @@ -47,9 +47,6 @@ public override async Task Run(ReceiveMessagesInvocation invocation) case Invocations.ReceiveReconnectInvocation reconnectInvocation: eventQueue.Enqueue(new Events.ReceiveReconnectSuccessEvent() { Channels = invocation?.Channels, ChannelGroups = invocation?.ChannelGroups, Cursor = cursor, Status = response.Item2, Messages = response.Item1 }); break; - case { } when response.Item2.Error && response.Item2.StatusCode == 403: - eventQueue.Enqueue(new Events.ReceiveReconnectGiveUpEvent { Channels = invocation?.Channels, ChannelGroups = invocation?.ChannelGroups, Cursor = cursor, Status = response.Item2 }); - break; case { } when response.Item2.Error: eventQueue.Enqueue(new Events.ReceiveFailureEvent() { Cursor = invocation.Cursor, Status = response.Item2}); break; From 1617f6b6ed95acca6b435d9e842615f73dfc1fe3 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Thu, 31 Aug 2023 13:24:55 +0530 Subject: [PATCH 54/56] removed emit status from presence --- .../Invocations/PresenceInvocations.cs | 25 ------------------- .../Presence/States/HeartbeatingState.cs | 6 ++--- 2 files changed, 3 insertions(+), 28 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Presence/Invocations/PresenceInvocations.cs b/src/Api/PubnubApi/EventEngine/Presence/Invocations/PresenceInvocations.cs index a96f5c8b3..25dc4c42e 100644 --- a/src/Api/PubnubApi/EventEngine/Presence/Invocations/PresenceInvocations.cs +++ b/src/Api/PubnubApi/EventEngine/Presence/Invocations/PresenceInvocations.cs @@ -5,31 +5,6 @@ namespace PubnubApi.EventEngine.Presence.Invocations { - //TODO: Bring EmitStatusInvocation into common folder for both presence and subscribe - public class EmitStatusInvocation : Core.IEffectInvocation { - // TODO merge status variables into one? - public PNStatusCategory StatusCategory; - public PNStatus Status; - public string Name { get; set; } = "EMIT_STATUS"; - - public EmitStatusInvocation(PNStatus status) - { - this.Status = status; - if (status != null) - { - this.StatusCategory = status.Category; - } - } - - public EmitStatusInvocation(PNStatusCategory category) - { - this.StatusCategory = category; - this.Status = new PNStatus() - { - Category = category, - }; - } - } public class HeartbeatInvocation : Core.IEffectInvocation { public IEnumerable Channels; public IEnumerable ChannelGroups; diff --git a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatingState.cs b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatingState.cs index e96b3e343..95d448d48 100644 --- a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatingState.cs +++ b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatingState.cs @@ -22,7 +22,7 @@ public override TransitionResult Transition(IEvent e) Events.LeftAllEvent leftAll => new HeartbeatInactiveState() { ReconnectionConfiguration = this.ReconnectionConfiguration - }.With(new EmitStatusInvocation(PNStatusCategory.PNDisconnectedCategory)), //TODO: Do we need PNLeaveCategory?, + }, Events.JoinedEvent joined => new States.HeartbeatingState() { @@ -36,7 +36,7 @@ public override TransitionResult Transition(IEvent e) Channels = (Channels ?? Enumerable.Empty()).Union(left.Channels), ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(left.ChannelGroups), ReconnectionConfiguration = this.ReconnectionConfiguration - }.With(new EmitStatusInvocation(PNStatusCategory.PNDisconnectedCategory)), //TODO: Do we need PNLeaveCategory? + }, Events.StateSetEvent stateSet => new States.HeartbeatingState() { @@ -58,7 +58,7 @@ public override TransitionResult Transition(IEvent e) Events.DisconnectEvent disconnect => new States.HeartbeatStoppedState() { ReconnectionConfiguration = this.ReconnectionConfiguration, - }.With(new EmitStatusInvocation(PNStatusCategory.PNDisconnectedCategory)), //TODO: Do we need PNLeaveCategory?, + }, _ => null }; From 0b8c0d1d5c0fa2ef089c13020cb055b15bb54aba Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Fri, 1 Sep 2023 21:20:28 +0530 Subject: [PATCH 55/56] Presence States --- .../Presence/Events/PresenceEvents.cs | 10 ++++ .../Invocations/PresenceInvocations.cs | 29 ++++++++++ .../Presence/States/HeartbeatCooldownState.cs | 47 +++++++++++++++- .../Presence/States/HeartbeatFailedState.cs | 17 ++++++ .../States/HeartbeatReconnectingState.cs | 55 ++++++++++++++++++- 5 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatFailedState.cs diff --git a/src/Api/PubnubApi/EventEngine/Presence/Events/PresenceEvents.cs b/src/Api/PubnubApi/EventEngine/Presence/Events/PresenceEvents.cs index 45d1be930..5cc4c5c4d 100644 --- a/src/Api/PubnubApi/EventEngine/Presence/Events/PresenceEvents.cs +++ b/src/Api/PubnubApi/EventEngine/Presence/Events/PresenceEvents.cs @@ -31,9 +31,19 @@ public class HeartbeatFailureEvent : Core.IEvent { public PNStatus Status { get; set; } public virtual string Name { get; set; } = "HEARTBEAT_FAILURE"; } + public class HeartbeatGiveUpEvent : Core.IEvent { + public PNStatus Status { get; set; } + public virtual string Name { get; set; } + } public class DisconnectEvent : Core.IEvent { public IEnumerable Channels{ get; set; } public IEnumerable ChannelGroups{ get; set; } public string Name { get; set; } = "DISCONNECT"; } + public class TimesUpEvent : Core.IEvent + { + public IEnumerable Channels{ get; set; } + public IEnumerable ChannelGroups{ get; set; } + public string Name { get; set; } = "TIMES_UP"; + } } diff --git a/src/Api/PubnubApi/EventEngine/Presence/Invocations/PresenceInvocations.cs b/src/Api/PubnubApi/EventEngine/Presence/Invocations/PresenceInvocations.cs index 25dc4c42e..6376229bc 100644 --- a/src/Api/PubnubApi/EventEngine/Presence/Invocations/PresenceInvocations.cs +++ b/src/Api/PubnubApi/EventEngine/Presence/Invocations/PresenceInvocations.cs @@ -19,4 +19,33 @@ public class CancelHeartbeatInvocation : HeartbeatInvocation, Core.IEffectCancel public override string Name { get; set; } = "CANCEL_HANDSHAKE"; } + public class WaitInvocation : Core.IEffectInvocation + { + public IEnumerable Channels; + public IEnumerable ChannelGroups; + public virtual string Name { get; set; } = "WAIT"; + } + public class CancelWaitInvocation : WaitInvocation, Core.IEffectCancelInvocation + { + public override string Name { get; set; } = "CANCEL_WAIT"; + } + + public class LeaveInvocation : Core.IEffectInvocation + { + public IEnumerable Channels; + public IEnumerable ChannelGroups; + public virtual string Name { get; set; } = "LEAVE"; + } + + public class DelayedHeartbeatInvocation : Core.IEffectInvocation + { + public IEnumerable Channels; + public IEnumerable ChannelGroups; + public virtual string Name { get; set; } = "DELAYED_HEARTBEAT"; + } + public class CancelDelayedHeartbeatInvocation : DelayedHeartbeatInvocation, Core.IEffectCancelInvocation + { + public override string Name { get; set; } = "CANCEL_DELAYED_HEARTBEAT"; + } } + diff --git a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatCooldownState.cs b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatCooldownState.cs index c14268a03..cfc5ac694 100644 --- a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatCooldownState.cs +++ b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatCooldownState.cs @@ -1,5 +1,6 @@ using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Presence.Common; +using PubnubApi.EventEngine.Presence.Invocations; using System; using System.Collections.Generic; using System.Linq; @@ -9,9 +10,53 @@ namespace PubnubApi.EventEngine.Presence.States { public class HeartbeatCooldownState : PresenceState { + public override IEnumerable OnEntry => new WaitInvocation() + { Channels = this.Channels, ChannelGroups = this.ChannelGroups }.AsArray(); + public override IEnumerable OnExit { get; } = new CancelWaitInvocation().AsArray(); public override TransitionResult Transition(IEvent e) { - throw new NotImplementedException(); + return e switch + { + Events.LeftAllEvent leftAll => new HeartbeatInactiveState() + { + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.JoinedEvent joined => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(joined.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(joined.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.LeftEvent left => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(left.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(left.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.StateSetEvent stateSet => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(stateSet.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(stateSet.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.TimesUpEvent timesUp => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(timesUp.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(timesUp.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.DisconnectEvent disconnect => new States.HeartbeatStoppedState() + { + ReconnectionConfiguration = this.ReconnectionConfiguration, + }, + + _ => null + }; } } } diff --git a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatFailedState.cs b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatFailedState.cs new file mode 100644 index 000000000..2c0a83881 --- /dev/null +++ b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatFailedState.cs @@ -0,0 +1,17 @@ +using PubnubApi.EventEngine.Core; +using PubnubApi.EventEngine.Presence.Common; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PubnubApi.EventEngine.Presence.States +{ + public class HeartbeatFailedState : PresenceState + { + public override TransitionResult Transition(IEvent e) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatReconnectingState.cs b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatReconnectingState.cs index 8048cc6ca..a04a5fa2a 100644 --- a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatReconnectingState.cs +++ b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatReconnectingState.cs @@ -1,5 +1,6 @@ using PubnubApi.EventEngine.Core; using PubnubApi.EventEngine.Presence.Common; +using PubnubApi.EventEngine.Presence.Invocations; using System; using System.Collections.Generic; using System.Linq; @@ -9,9 +10,61 @@ namespace PubnubApi.EventEngine.Presence.States { public class HeartbeatReconnectingState : PresenceState { + public override IEnumerable OnEntry => new DelayedHeartbeatInvocation() + { Channels = this.Channels, ChannelGroups = this.ChannelGroups }.AsArray(); + public override IEnumerable OnExit { get; } = new CancelDelayedHeartbeatInvocation().AsArray(); public override TransitionResult Transition(IEvent e) { - throw new NotImplementedException(); + return e switch + { + Events.LeftAllEvent leftAll => new HeartbeatInactiveState() + { + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.HeartbeatFailureEvent heartbeatFailure => new States.HeartbeatReconnectingState() + { + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.JoinedEvent joined => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(joined.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(joined.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.LeftEvent left => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(left.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(left.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.StateSetEvent stateSet => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(stateSet.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(stateSet.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.HeartbeatSuccessEvent heartbeatSuccess => new States.HeartbeatCooldownState() + { + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.HeartbeatGiveUpEvent heartbeatGiveup => new States.HeartbeatFailedState() + { + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.DisconnectEvent disconnect => new States.HeartbeatStoppedState() + { + ReconnectionConfiguration = this.ReconnectionConfiguration, + }, + + _ => null + }; } } } From e942f2db367105011d537b9703c2fd9e2a37aa71 Mon Sep 17 00:00:00 2001 From: Pandu Masabathula Date: Fri, 1 Sep 2023 22:27:14 +0530 Subject: [PATCH 56/56] Updated Presence States --- .../Presence/Events/PresenceEvents.cs | 12 +++++ .../Presence/States/HeartbeatCooldownState.cs | 2 + .../Presence/States/HeartbeatFailedState.cs | 45 ++++++++++++++++++- .../Presence/States/HeartbeatInactiveState.cs | 11 ++++- .../States/HeartbeatReconnectingState.cs | 8 ++++ .../Presence/States/HeartbeatStoppedState.cs | 38 +++++++++++++++- .../Presence/States/HeartbeatingState.cs | 6 +++ 7 files changed, 119 insertions(+), 3 deletions(-) diff --git a/src/Api/PubnubApi/EventEngine/Presence/Events/PresenceEvents.cs b/src/Api/PubnubApi/EventEngine/Presence/Events/PresenceEvents.cs index 5cc4c5c4d..d0b8b6c42 100644 --- a/src/Api/PubnubApi/EventEngine/Presence/Events/PresenceEvents.cs +++ b/src/Api/PubnubApi/EventEngine/Presence/Events/PresenceEvents.cs @@ -24,14 +24,20 @@ public class LeftAllEvent : Core.IEvent { public string Name { get; set; } = "LEFT_ALL"; } public class HeartbeatSuccessEvent : Core.IEvent { + public IEnumerable Channels{ get; set; } + public IEnumerable ChannelGroups{ get; set; } public PNStatus Status { get; set; } public virtual string Name { get; set; } = "HEARTBEAT_SUCCESS"; } public class HeartbeatFailureEvent : Core.IEvent { + public IEnumerable Channels{ get; set; } + public IEnumerable ChannelGroups{ get; set; } public PNStatus Status { get; set; } public virtual string Name { get; set; } = "HEARTBEAT_FAILURE"; } public class HeartbeatGiveUpEvent : Core.IEvent { + public IEnumerable Channels{ get; set; } + public IEnumerable ChannelGroups{ get; set; } public PNStatus Status { get; set; } public virtual string Name { get; set; } } @@ -40,6 +46,12 @@ public class DisconnectEvent : Core.IEvent { public IEnumerable ChannelGroups{ get; set; } public string Name { get; set; } = "DISCONNECT"; } + public class ReconnectEvent : Core.IEvent + { + public IEnumerable Channels{ get; set; } + public IEnumerable ChannelGroups{ get; set; } + public string Name { get; set; } + } public class TimesUpEvent : Core.IEvent { public IEnumerable Channels{ get; set; } diff --git a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatCooldownState.cs b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatCooldownState.cs index cfc5ac694..dc1d2828e 100644 --- a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatCooldownState.cs +++ b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatCooldownState.cs @@ -52,6 +52,8 @@ public override TransitionResult Transition(IEvent e) Events.DisconnectEvent disconnect => new States.HeartbeatStoppedState() { + Channels = (Channels ?? Enumerable.Empty()).Union(disconnect.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(disconnect.ChannelGroups), ReconnectionConfiguration = this.ReconnectionConfiguration, }, diff --git a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatFailedState.cs b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatFailedState.cs index 2c0a83881..21eeb9f4e 100644 --- a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatFailedState.cs +++ b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatFailedState.cs @@ -11,7 +11,50 @@ public class HeartbeatFailedState : PresenceState { public override TransitionResult Transition(IEvent e) { - throw new NotImplementedException(); + return e switch + { + Events.LeftAllEvent leftAll => new HeartbeatInactiveState() + { + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.JoinedEvent joined => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(joined.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(joined.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.LeftEvent left => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(left.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(left.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.StateSetEvent stateSet => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(stateSet.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(stateSet.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.ReconnectEvent reconnect => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(reconnect.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(reconnect.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration, + }, + + Events.DisconnectEvent disconnect => new States.HeartbeatStoppedState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(disconnect.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(disconnect.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration, + }, + + _ => null + }; } } } diff --git a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatInactiveState.cs b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatInactiveState.cs index cd7abaa54..bb7a88562 100644 --- a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatInactiveState.cs +++ b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatInactiveState.cs @@ -11,7 +11,16 @@ public class HeartbeatInactiveState : PresenceState { public override TransitionResult Transition(IEvent e) { - throw new NotImplementedException(); + return e switch + { + Events.JoinedEvent joined => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(joined.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(joined.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + _ => null + }; } } } diff --git a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatReconnectingState.cs b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatReconnectingState.cs index a04a5fa2a..17e4bbcec 100644 --- a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatReconnectingState.cs +++ b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatReconnectingState.cs @@ -24,6 +24,8 @@ public override TransitionResult Transition(IEvent e) Events.HeartbeatFailureEvent heartbeatFailure => new States.HeartbeatReconnectingState() { + Channels = (Channels ?? Enumerable.Empty()).Union(heartbeatFailure.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(heartbeatFailure.ChannelGroups), ReconnectionConfiguration = this.ReconnectionConfiguration }, @@ -50,16 +52,22 @@ public override TransitionResult Transition(IEvent e) Events.HeartbeatSuccessEvent heartbeatSuccess => new States.HeartbeatCooldownState() { + Channels = (Channels ?? Enumerable.Empty()).Union(heartbeatSuccess.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(heartbeatSuccess.ChannelGroups), ReconnectionConfiguration = this.ReconnectionConfiguration }, Events.HeartbeatGiveUpEvent heartbeatGiveup => new States.HeartbeatFailedState() { + Channels = (Channels ?? Enumerable.Empty()).Union(heartbeatGiveup.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(heartbeatGiveup.ChannelGroups), ReconnectionConfiguration = this.ReconnectionConfiguration }, Events.DisconnectEvent disconnect => new States.HeartbeatStoppedState() { + Channels = (Channels ?? Enumerable.Empty()).Union(disconnect.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(disconnect.ChannelGroups), ReconnectionConfiguration = this.ReconnectionConfiguration, }, diff --git a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatStoppedState.cs b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatStoppedState.cs index 2f583fe76..b3f0868e0 100644 --- a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatStoppedState.cs +++ b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatStoppedState.cs @@ -11,7 +11,43 @@ public class HeartbeatStoppedState : PresenceState { public override TransitionResult Transition(IEvent e) { - throw new NotImplementedException(); + return e switch + { + Events.LeftAllEvent leftAll => new HeartbeatInactiveState() + { + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.JoinedEvent joined => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(joined.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(joined.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.LeftEvent left => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(left.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(left.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.StateSetEvent stateSet => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(stateSet.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(stateSet.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration + }, + + Events.ReconnectEvent reconnect => new States.HeartbeatingState() + { + Channels = (Channels ?? Enumerable.Empty()).Union(reconnect.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(reconnect.ChannelGroups), + ReconnectionConfiguration = this.ReconnectionConfiguration, + }, + + _ => null + }; } } } diff --git a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatingState.cs b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatingState.cs index 95d448d48..82209b47a 100644 --- a/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatingState.cs +++ b/src/Api/PubnubApi/EventEngine/Presence/States/HeartbeatingState.cs @@ -47,16 +47,22 @@ public override TransitionResult Transition(IEvent e) Events.HeartbeatSuccessEvent heartbeatSuccess => new States.HeartbeatCooldownState() { + Channels = (Channels ?? Enumerable.Empty()).Union(heartbeatSuccess.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(heartbeatSuccess.ChannelGroups), ReconnectionConfiguration = this.ReconnectionConfiguration }, Events.HeartbeatFailureEvent heartbeatFailure => new States.HeartbeatReconnectingState() { + Channels = (Channels ?? Enumerable.Empty()).Union(heartbeatFailure.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(heartbeatFailure.ChannelGroups), ReconnectionConfiguration = this.ReconnectionConfiguration }, Events.DisconnectEvent disconnect => new States.HeartbeatStoppedState() { + Channels = (Channels ?? Enumerable.Empty()).Union(disconnect.Channels), + ChannelGroups = (ChannelGroups ?? Enumerable.Empty()).Union(disconnect.ChannelGroups), ReconnectionConfiguration = this.ReconnectionConfiguration, },