From dbc59aa536e1955b878b591705dbb4827f11caa3 Mon Sep 17 00:00:00 2001 From: sacOO7 Date: Mon, 19 Feb 2024 23:21:59 +0530 Subject: [PATCH 01/15] Updated channelMessageProcessor to handle presence on channel attached --- src/IO.Ably.Shared/Realtime/ChannelMessageProcessor.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/IO.Ably.Shared/Realtime/ChannelMessageProcessor.cs b/src/IO.Ably.Shared/Realtime/ChannelMessageProcessor.cs index 001dac60b..6165282b6 100644 --- a/src/IO.Ably.Shared/Realtime/ChannelMessageProcessor.cs +++ b/src/IO.Ably.Shared/Realtime/ChannelMessageProcessor.cs @@ -70,10 +70,13 @@ public Task MessageReceived(ProtocolMessage protocolMessage, RealtimeState } // RTL12 - if (channel.State == ChannelState.Attached && !protocolMessage.HasFlag(ProtocolMessage.Flag.Resumed)) + if (channel.State == ChannelState.Attached) { - channel.Presence.ChannelAttached(protocolMessage, false); - channel.EmitErrorUpdate(protocolMessage.Error, false, protocolMessage); + if (!protocolMessage.HasFlag(ProtocolMessage.Flag.Resumed)) + { + channel.Presence.ChannelAttached(protocolMessage, false); + channel.EmitErrorUpdate(protocolMessage.Error, false, protocolMessage); + } } else { From 7d9148d7ace240d54098dfd951e9d4590362db5e Mon Sep 17 00:00:00 2001 From: sacOO7 Date: Mon, 19 Feb 2024 23:24:43 +0530 Subject: [PATCH 02/15] removed unnecessary argument for presence channel attach --- src/IO.Ably.Shared/Realtime/ChannelMessageProcessor.cs | 2 +- src/IO.Ably.Shared/Realtime/Presence.cs | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/IO.Ably.Shared/Realtime/ChannelMessageProcessor.cs b/src/IO.Ably.Shared/Realtime/ChannelMessageProcessor.cs index 6165282b6..0ab81cf07 100644 --- a/src/IO.Ably.Shared/Realtime/ChannelMessageProcessor.cs +++ b/src/IO.Ably.Shared/Realtime/ChannelMessageProcessor.cs @@ -74,7 +74,7 @@ public Task MessageReceived(ProtocolMessage protocolMessage, RealtimeState { if (!protocolMessage.HasFlag(ProtocolMessage.Flag.Resumed)) { - channel.Presence.ChannelAttached(protocolMessage, false); + channel.Presence.ChannelAttached(protocolMessage); channel.EmitErrorUpdate(protocolMessage.Error, false, protocolMessage); } } diff --git a/src/IO.Ably.Shared/Realtime/Presence.cs b/src/IO.Ably.Shared/Realtime/Presence.cs index 90faf4edb..7cacb7c11 100644 --- a/src/IO.Ably.Shared/Realtime/Presence.cs +++ b/src/IO.Ably.Shared/Realtime/Presence.cs @@ -721,7 +721,7 @@ internal void ChannelSuspended(ErrorInfo error) FailQueuedMessages(error); } - internal void ChannelAttached(ProtocolMessage attachedMessage, bool isAttachWithoutMessageLoss = true) + internal void ChannelAttached(ProtocolMessage attachedMessage) { // RTP19 StartSync(); @@ -747,10 +747,7 @@ internal void ChannelAttached(ProtocolMessage attachedMessage, bool isAttachWith SendQueuedMessages(); // RTP17f - if (isAttachWithoutMessageLoss) - { - EnterMembersFromInternalPresenceMap(); - } + EnterMembersFromInternalPresenceMap(); } private void SendQueuedMessages() From 21137c00c5ffa647a08e9398fa4c92ef1b249c28 Mon Sep 17 00:00:00 2001 From: sacOO7 Date: Mon, 19 Feb 2024 23:37:54 +0530 Subject: [PATCH 03/15] Updated code to enter presence message along with message id --- src/IO.Ably.Shared/Realtime/Presence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/IO.Ably.Shared/Realtime/Presence.cs b/src/IO.Ably.Shared/Realtime/Presence.cs index 7cacb7c11..9e01ee697 100644 --- a/src/IO.Ably.Shared/Realtime/Presence.cs +++ b/src/IO.Ably.Shared/Realtime/Presence.cs @@ -647,7 +647,7 @@ private void EnterMembersFromInternalPresenceMap() { try { - var itemToSend = new PresenceMessage(PresenceAction.Enter, item.ClientId, item.Data); + var itemToSend = new PresenceMessage(PresenceAction.Enter, item.ClientId, item.Data, item.Id); UpdatePresence(itemToSend, (success, info) => { if (!success) From f2d8d72c771a68982d82b5fbbd32f26976e55912 Mon Sep 17 00:00:00 2001 From: sacOO7 Date: Wed, 21 Feb 2024 18:36:35 +0530 Subject: [PATCH 04/15] Updated test for RTL12 enter member presence --- .../Realtime/PresenceSandboxSpecs.cs | 34 ++++++------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs b/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs index f940e9221..14eed9a2e 100644 --- a/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs +++ b/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs @@ -406,7 +406,6 @@ async Task WaitForNoPresenceOnChannel(IRestChannel rChannel) // let the library know the transport is really dead testTransport.Listener?.OnTransportEvent(testTransport.Id, TransportState.Closed); - await realtimeClient.WaitForState(ConnectionState.Disconnected); await realtimeClient.WaitForState(ConnectionState.Connected); await realtimeChannel.WaitForAttachedState(); @@ -452,43 +451,35 @@ public async Task OnAttach_ShouldEnterMembersFromInternalMap(Protocol protocol) presence.InternalMembersMap.Members.Should().HaveCount(1); List leaveMessages = new List(); - PresenceMessage updateMessage = null; - PresenceMessage enterMessage = null; + PresenceMessage enteredMember = null; await WaitForMultiple(2, partialDone => { presence.Subscribe(PresenceAction.Leave, message => { leaveMessages.Add(message); }); - presence.Subscribe(PresenceAction.Update, message => - { - updateMessage = message; - partialDone(); // 1 call - }); - presence.Subscribe(PresenceAction.Enter, message => + client.GetTestTransport().BeforeMessageSend = message => { - enterMessage = message; // not expected to hit - }); + enteredMember = message.Presence.First(); + client.GetTestTransport().BeforeMessageSend = _ => { }; + partialDone(); + }; client.GetTestTransport().AfterDataReceived = message => { if (message.Action == ProtocolMessage.MessageAction.Attached) { bool hasPresence = message.HasFlag(ProtocolMessage.Flag.HasPresence); hasPresence.Should().BeFalse(); - bool resumed = message.HasFlag(ProtocolMessage.Flag.Resumed); - resumed.Should().BeTrue(); client.GetTestTransport().AfterDataReceived = _ => { }; partialDone(); // 1 call } }; - // inject duplicate attached message with resume flag ( no RTL12 message loss event) + // inject duplicate attached message without resume flag var protocolMessage = new ProtocolMessage(ProtocolMessage.MessageAction.Attached) { Channel = channelName, Flags = 0, }; - protocolMessage.SetFlag(ProtocolMessage.Flag.Resumed); - protocolMessage.HasFlag(ProtocolMessage.Flag.Resumed).Should().BeTrue(); client.GetTestTransport().FakeReceivedMessage(protocolMessage); }); @@ -498,15 +489,12 @@ await WaitForMultiple(2, partialDone => msg.ClientId.Should().BeOneOf("member_0", "member_1", "member_2", "local"); } - updateMessage.Should().NotBeNull(); - updateMessage.ClientId.Should().Be("local"); - enterMessage.Should().BeNull(); - + enteredMember.Should().NotBeNull(); + enteredMember.Action.Should().Be(PresenceAction.Enter); + enteredMember.ClientId.Should().Be("local"); presence.Unsubscribe(); - var remainingMembers = await presence.GetAsync(); - remainingMembers.Should().HaveCount(1); - remainingMembers.First().ClientId.Should().Be("local"); + client.Close(); } [Theory] From a324736c51bf1f18e93aeeb560525c12e19ca30e Mon Sep 17 00:00:00 2001 From: sacOO7 Date: Mon, 11 Mar 2024 14:07:41 +0530 Subject: [PATCH 05/15] Getting channel serials only for attached channels for recovery key --- src/IO.Ably.Shared/Realtime/RealtimeChannels.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/IO.Ably.Shared/Realtime/RealtimeChannels.cs b/src/IO.Ably.Shared/Realtime/RealtimeChannels.cs index ae08cca24..eb7601a99 100644 --- a/src/IO.Ably.Shared/Realtime/RealtimeChannels.cs +++ b/src/IO.Ably.Shared/Realtime/RealtimeChannels.cs @@ -264,7 +264,10 @@ internal IDictionary GetChannelSerials() var channelSerials = new Dictionary(); foreach (var realtimeChannel in this) { - channelSerials[realtimeChannel.Name] = realtimeChannel.Properties.ChannelSerial; + if (realtimeChannel.State == ChannelState.Attached) + { + channelSerials[realtimeChannel.Name] = realtimeChannel.Properties.ChannelSerial; + } } return channelSerials; From d09ac0dbebdbe19e838e41a796e361be2f7bde0c Mon Sep 17 00:00:00 2001 From: sacOO7 Date: Mon, 11 Mar 2024 14:36:33 +0530 Subject: [PATCH 06/15] refactored channel attached method inside presence --- src/IO.Ably.Shared/Realtime/Presence.cs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/IO.Ably.Shared/Realtime/Presence.cs b/src/IO.Ably.Shared/Realtime/Presence.cs index 9e01ee697..82968829f 100644 --- a/src/IO.Ably.Shared/Realtime/Presence.cs +++ b/src/IO.Ably.Shared/Realtime/Presence.cs @@ -723,22 +723,13 @@ internal void ChannelSuspended(ErrorInfo error) internal void ChannelAttached(ProtocolMessage attachedMessage) { - // RTP19 - StartSync(); - // RTP1 var hasPresence = attachedMessage != null && attachedMessage.HasFlag(ProtocolMessage.Flag.HasPresence); - if (hasPresence) - { - if (Logger.IsDebug) - { - Logger.Debug( - $"Protocol message has presence flag. Starting Presence SYNC. Flag: {attachedMessage.Flags}"); - } - StartSync(); - } - else + // RTP19 + StartSync(); + + if (!hasPresence) { EndSync(); // RTP19 } From 131ea1cd5fb585a46d4dc413599c600a7435c0e5 Mon Sep 17 00:00:00 2001 From: sacOO7 Date: Fri, 19 Apr 2024 16:39:48 +0530 Subject: [PATCH 07/15] Added msg id check for entered messages after channel attach --- src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs b/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs index 14eed9a2e..e7619360c 100644 --- a/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs +++ b/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs @@ -449,6 +449,7 @@ public async Task OnAttach_ShouldEnterMembersFromInternalMap(Protocol protocol) await Task.Delay(250); presence.MembersMap.Members.Should().HaveCount(4); presence.InternalMembersMap.Members.Should().HaveCount(1); + var internalMemberId = presence.InternalMembersMap.Members.Values.First().Id; List leaveMessages = new List(); PresenceMessage enteredMember = null; @@ -490,6 +491,7 @@ await WaitForMultiple(2, partialDone => } enteredMember.Should().NotBeNull(); + enteredMember.Id.Should().Be(internalMemberId); enteredMember.Action.Should().Be(PresenceAction.Enter); enteredMember.ClientId.Should().Be("local"); presence.Unsubscribe(); From 177131837d4c57c6cf74149fb0eb48768b5e878f Mon Sep 17 00:00:00 2001 From: sacOO7 Date: Fri, 19 Apr 2024 16:55:33 +0530 Subject: [PATCH 08/15] Fixed newer presencemessage checks and decoding recovery key --- src/IO.Ably.Shared/Extensions/PresenceExtensions.cs | 4 ++-- src/IO.Ably.Shared/Realtime/RecoveryKeyContext.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/IO.Ably.Shared/Extensions/PresenceExtensions.cs b/src/IO.Ably.Shared/Extensions/PresenceExtensions.cs index 49d13126b..1229674b9 100644 --- a/src/IO.Ably.Shared/Extensions/PresenceExtensions.cs +++ b/src/IO.Ably.Shared/Extensions/PresenceExtensions.cs @@ -13,7 +13,7 @@ public static bool IsNewerThan(this PresenceMessage thisMessage, PresenceMessage // RTP2b1 if (thisMessage.IsSynthesized() || thatMessage.IsSynthesized()) { - return thisMessage.Timestamp > thatMessage.Timestamp; + return thisMessage.Timestamp >= thatMessage.Timestamp; } // RTP2b2 @@ -35,7 +35,7 @@ public static bool IsNewerThan(this PresenceMessage thisMessage, PresenceMessage if (msgSerialThis == msgSerialThat) { - return indexThis > indexThat; + return indexThis >= indexThat; } return msgSerialThis > msgSerialThat; diff --git a/src/IO.Ably.Shared/Realtime/RecoveryKeyContext.cs b/src/IO.Ably.Shared/Realtime/RecoveryKeyContext.cs index db1da65ac..d55ec9427 100644 --- a/src/IO.Ably.Shared/Realtime/RecoveryKeyContext.cs +++ b/src/IO.Ably.Shared/Realtime/RecoveryKeyContext.cs @@ -26,9 +26,9 @@ public static RecoveryKeyContext Decode(string recover, ILogger logger = null) { return JsonHelper.Deserialize(recover); } - catch (Exception) + catch (Exception e) { - logger?.Warning($"Error deserializing recover - {recover}, setting it as null"); + logger?.Warning($"Error deserializing recover - {recover}, setting it as null", e); return null; } } From 54ebec36f5f455ceedc45f187cf3c8a5306983e0 Mon Sep 17 00:00:00 2001 From: sacOO7 Date: Fri, 19 Apr 2024 16:59:28 +0530 Subject: [PATCH 09/15] Marked unintended IsSyncInProgress method as internal --- src/IO.Ably.Shared/Realtime/Presence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/IO.Ably.Shared/Realtime/Presence.cs b/src/IO.Ably.Shared/Realtime/Presence.cs index 82968829f..69f677702 100644 --- a/src/IO.Ably.Shared/Realtime/Presence.cs +++ b/src/IO.Ably.Shared/Realtime/Presence.cs @@ -46,7 +46,7 @@ internal Presence(IConnectionManager connection, RealtimeChannel channel, string /// /// Indicates whether there is currently a sync in progress. /// - public bool IsSyncInProgress => MembersMap.SyncInProgress; + internal bool IsSyncInProgress => MembersMap.SyncInProgress; /// /// Indicates all members present on the channel. From 332d95411529245e2854fba7571f6ba7c94cfb4a Mon Sep 17 00:00:00 2001 From: sacOO7 Date: Fri, 19 Apr 2024 17:05:23 +0530 Subject: [PATCH 10/15] Deprecated IsSyncComplete property, added SyncComplete property as per spec --- src/IO.Ably.Shared/Realtime/Presence.cs | 14 ++++++++++++-- .../Realtime/PresenceSandboxSpecs.cs | 12 ++++++------ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/IO.Ably.Shared/Realtime/Presence.cs b/src/IO.Ably.Shared/Realtime/Presence.cs index 69f677702..c098c15f1 100644 --- a/src/IO.Ably.Shared/Realtime/Presence.cs +++ b/src/IO.Ably.Shared/Realtime/Presence.cs @@ -40,8 +40,18 @@ internal Presence(IConnectionManager connection, RealtimeChannel channel, string /// /// Has the sync completed. + /// RTP13 /// - public bool IsSyncComplete => MembersMap.SyncCompleted && !IsSyncInProgress; + /// + [Obsolete("This property is deprecated, use SyncComplete instead")] + public bool IsSyncComplete => SyncComplete; + + /// + /// Checks if sync has completed + /// RTP13 + /// + /// + public bool SyncComplete => MembersMap.SyncCompleted && !IsSyncInProgress; /// /// Indicates whether there is currently a sync in progress. @@ -153,7 +163,7 @@ private async Task WaitForSyncAsync() // The InternalSync should be completed and the channels Attached or Attaching void CheckAndSet() { - if (IsSyncComplete + if (SyncComplete && (_channel.State == ChannelState.Attached || _channel.State == ChannelState.Attaching)) { tsc.TrySetResult(true); diff --git a/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs b/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs index e7619360c..c8d904496 100644 --- a/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs +++ b/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs @@ -81,7 +81,7 @@ public async Task WhenAttachingToAChannelWithNoMembers_PresenceShouldBeConsidere await channel.WaitForAttachedState(); channel.State.Should().Be(ChannelState.Attached); - channel.Presence.IsSyncComplete.Should().BeTrue(); + channel.Presence.SyncComplete.Should().BeTrue(); } [Theory] @@ -110,7 +110,7 @@ public async Task WhenAttachingToAChannelWithMembers_PresenceShouldBeInProgress( { Logger.Debug("Test: Setting inSync to - " + channel2.Presence.MembersMap.SyncInProgress); syncInProgress = channel2.Presence.IsSyncInProgress; - syncComplete = channel2.Presence.IsSyncComplete; + syncComplete = channel2.Presence.SyncComplete; awaiter.SetCompleted(); } }; @@ -741,7 +741,7 @@ public async Task PresenceMap_WhenNotSyncingAndLeaveActionArrivesMemberKeyShould // sync should not be in progress and initial an sync should have completed channel.Presence.IsSyncInProgress.Should().BeFalse("sync should have completed"); - channel.Presence.IsSyncComplete.Should().BeTrue(); + channel.Presence.SyncComplete.Should().BeTrue(); // pull a random member key from the presence map var memberNumber = new Random().Next(0, 19); @@ -1504,19 +1504,19 @@ await WaitForMultiple(2, partialDone => presence2.Subscribe(PresenceAction.Enter, msg => { - presence2.MembersMap.Members.Should().HaveCount(presence2.IsSyncComplete ? 2 : 1); + presence2.MembersMap.Members.Should().HaveCount(presence2.SyncComplete ? 2 : 1); presence2.Unsubscribe(); partialDone(); }); presence2.PendingPresenceQueue.Should().HaveCount(1); - presence2.IsSyncComplete.Should().BeFalse(); + presence2.SyncComplete.Should().BeFalse(); presence2.MembersMap.Members.Should().HaveCount(0); taskCountWaiter.Tick(); }); var transport = client2.GetTestTransport(); - await new ConditionalAwaiter(() => presence2.IsSyncComplete); + await new ConditionalAwaiter(() => presence2.SyncComplete); transport.ProtocolMessagesReceived.Any(m => m.Action == ProtocolMessage.MessageAction.Sync). Should().BeTrue("Should receive sync message"); presence2.MembersMap.Members.Should().HaveCount(2); From 8be657f7b36f7fb0ebf2a4ef8c30bbd7231d776b Mon Sep 17 00:00:00 2001 From: sacOO7 Date: Fri, 19 Apr 2024 17:09:14 +0530 Subject: [PATCH 11/15] Updated documentation comments for Presence#SyncComplete property --- src/IO.Ably.Shared/Realtime/Presence.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/IO.Ably.Shared/Realtime/Presence.cs b/src/IO.Ably.Shared/Realtime/Presence.cs index c098c15f1..5ed2d952e 100644 --- a/src/IO.Ably.Shared/Realtime/Presence.cs +++ b/src/IO.Ably.Shared/Realtime/Presence.cs @@ -39,19 +39,17 @@ internal Presence(IConnectionManager connection, RealtimeChannel channel, string internal ILogger Logger { get; private set; } /// - /// Has the sync completed. - /// RTP13 + /// Checks if presence sync has ended. /// /// [Obsolete("This property is deprecated, use SyncComplete instead")] - public bool IsSyncComplete => SyncComplete; + public bool IsSyncComplete => SyncComplete; // RTP13 /// - /// Checks if sync has completed - /// RTP13 + /// Checks if presence sync has ended. /// /// - public bool SyncComplete => MembersMap.SyncCompleted && !IsSyncInProgress; + public bool SyncComplete => MembersMap.SyncCompleted && !IsSyncInProgress; // RTP13 /// /// Indicates whether there is currently a sync in progress. From 9c8f3956818542a2d1a61ddece9722466c2c7e91 Mon Sep 17 00:00:00 2001 From: sacOO7 Date: Fri, 19 Apr 2024 17:19:30 +0530 Subject: [PATCH 12/15] Marked IsSyncInProgress as a public deprecated method --- src/IO.Ably.Shared/Realtime/Presence.cs | 18 ++++++++++++------ .../Realtime/PresenceSandboxSpecs.cs | 4 ++-- .../Rest/SandboxSpecExtension.cs | 2 +- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/IO.Ably.Shared/Realtime/Presence.cs b/src/IO.Ably.Shared/Realtime/Presence.cs index 5ed2d952e..68784ae69 100644 --- a/src/IO.Ably.Shared/Realtime/Presence.cs +++ b/src/IO.Ably.Shared/Realtime/Presence.cs @@ -43,18 +43,24 @@ internal Presence(IConnectionManager connection, RealtimeChannel channel, string /// /// [Obsolete("This property is deprecated, use SyncComplete instead")] - public bool IsSyncComplete => SyncComplete; // RTP13 + public bool IsSyncComplete => SyncComplete; // RTP13. /// /// Checks if presence sync has ended. /// /// - public bool SyncComplete => MembersMap.SyncCompleted && !IsSyncInProgress; // RTP13 + public bool SyncComplete => MembersMap.SyncCompleted && !SyncInProgress; // RTP13 /// /// Indicates whether there is currently a sync in progress. /// - internal bool IsSyncInProgress => MembersMap.SyncInProgress; + [Obsolete("This property is internal, will be removed in the future")] + public bool IsSyncInProgress => SyncInProgress; + + /// + /// Indicates whether there is currently a sync in progress. + /// + internal bool SyncInProgress => MembersMap.SyncInProgress; /// /// Indicates all members present on the channel. @@ -540,7 +546,7 @@ internal void OnSyncMessage(ProtocolMessage protocolMessage) /* If a new sequence identifier is sent from Ably, then the client library * must consider that to be the start of a new sync sequence * and any previous in-flight sync should be discarded. (part of RTP18)*/ - if (IsSyncInProgress && _currentSyncChannelSerial.IsNotEmpty() && _currentSyncChannelSerial != syncSequenceId) + if (SyncInProgress && _currentSyncChannelSerial.IsNotEmpty() && _currentSyncChannelSerial != syncSequenceId) { EndSync(); } @@ -621,7 +627,7 @@ internal void OnPresence(PresenceMessage[] messages) internal void StartSync() { - if (!IsSyncInProgress) + if (!SyncInProgress) { MembersMap.StartSync(); } @@ -629,7 +635,7 @@ internal void StartSync() private void EndSync() { - if (!IsSyncInProgress) + if (!SyncInProgress) { return; } diff --git a/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs b/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs index c8d904496..2ba561ae9 100644 --- a/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs +++ b/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs @@ -109,7 +109,7 @@ public async Task WhenAttachingToAChannelWithMembers_PresenceShouldBeInProgress( if (args.Current == ChannelState.Attached) { Logger.Debug("Test: Setting inSync to - " + channel2.Presence.MembersMap.SyncInProgress); - syncInProgress = channel2.Presence.IsSyncInProgress; + syncInProgress = channel2.Presence.SyncInProgress; syncComplete = channel2.Presence.SyncComplete; awaiter.SetCompleted(); } @@ -740,7 +740,7 @@ public async Task PresenceMap_WhenNotSyncingAndLeaveActionArrivesMemberKeyShould members.Should().HaveCount(20); // sync should not be in progress and initial an sync should have completed - channel.Presence.IsSyncInProgress.Should().BeFalse("sync should have completed"); + channel.Presence.SyncInProgress.Should().BeFalse("sync should have completed"); channel.Presence.SyncComplete.Should().BeTrue(); // pull a random member key from the presence map diff --git a/src/IO.Ably.Tests.Shared/Rest/SandboxSpecExtension.cs b/src/IO.Ably.Tests.Shared/Rest/SandboxSpecExtension.cs index db9a4c3d5..4ba5374af 100644 --- a/src/IO.Ably.Tests.Shared/Rest/SandboxSpecExtension.cs +++ b/src/IO.Ably.Tests.Shared/Rest/SandboxSpecExtension.cs @@ -47,7 +47,7 @@ internal static async Task WaitForAttachedState(this IRealtimeChannel channel, T internal static async Task WaitSync(this Presence presence, TimeSpan? waitSpan = null) { TaskCompletionSource taskCompletionSource = new TaskCompletionSource(); - var inProgress = presence.IsSyncInProgress; + var inProgress = presence.SyncInProgress; if (inProgress == false) { return true; From 5c77955e253355fe5beb79ae3ed2b7a126379622 Mon Sep 17 00:00:00 2001 From: sacOO7 Date: Fri, 19 Apr 2024 18:41:15 +0530 Subject: [PATCH 13/15] Refactored presence extension method isnewer than according to review comment --- .../Extensions/PresenceExtensions.cs | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/IO.Ably.Shared/Extensions/PresenceExtensions.cs b/src/IO.Ably.Shared/Extensions/PresenceExtensions.cs index 1229674b9..f5f4f6b23 100644 --- a/src/IO.Ably.Shared/Extensions/PresenceExtensions.cs +++ b/src/IO.Ably.Shared/Extensions/PresenceExtensions.cs @@ -8,37 +8,37 @@ public static bool IsSynthesized(this PresenceMessage msg) } // RTP2b, RTP2c - public static bool IsNewerThan(this PresenceMessage thisMessage, PresenceMessage thatMessage) + public static bool IsNewerThan(this PresenceMessage existingMsg, PresenceMessage incomingMsg) { // RTP2b1 - if (thisMessage.IsSynthesized() || thatMessage.IsSynthesized()) + if (existingMsg.IsSynthesized() || incomingMsg.IsSynthesized()) { - return thisMessage.Timestamp >= thatMessage.Timestamp; + return existingMsg.Timestamp > incomingMsg.Timestamp; } // RTP2b2 - var thisValues = thisMessage.Id.Split(':'); - var thatValues = thatMessage.Id.Split(':'); + var thisValues = existingMsg.Id.Split(':'); + var thatValues = incomingMsg.Id.Split(':'); // if any part of the message serial fails to parse then throw an exception if (thisValues.Length != 3 || - !(int.TryParse(thisValues[1], out int msgSerialThis) | int.TryParse(thisValues[2], out int indexThis))) + !(int.TryParse(thisValues[1], out int existingMsgSerial) | int.TryParse(thisValues[2], out int existingMsgIndex))) { - throw new AblyException($"Parsing error. The Presence Message has an invalid Id '{thisMessage.Id}'."); + throw new AblyException($"Parsing error. The Presence Message has an invalid Id '{existingMsg.Id}'."); } if (thatValues.Length != 3 || - !(int.TryParse(thatValues[1], out int msgSerialThat) | int.TryParse(thatValues[2], out int indexThat))) + !(int.TryParse(thatValues[1], out int incomingMsgSerial) | int.TryParse(thatValues[2], out int incomingMsgIndex))) { - throw new AblyException($"Parsing error. The Presence Message has an invalid Id '{thatMessage.Id}'."); + throw new AblyException($"Parsing error. The Presence Message has an invalid Id '{incomingMsg.Id}'."); } - if (msgSerialThis == msgSerialThat) + if (existingMsgSerial == incomingMsgSerial) { - return indexThis >= indexThat; + return existingMsgIndex > incomingMsgIndex; } - return msgSerialThis > msgSerialThat; + return existingMsgSerial > incomingMsgSerial; } } } From fd911563399ced2de72f67d66aa8a8cfe91ff3c8 Mon Sep 17 00:00:00 2001 From: sacOO7 Date: Fri, 19 Apr 2024 18:43:36 +0530 Subject: [PATCH 14/15] Refactored msg synthesize, renamed to serverSynthesized --- src/IO.Ably.Shared/Extensions/PresenceExtensions.cs | 4 ++-- src/IO.Ably.Shared/Realtime/Presence.cs | 2 +- src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/IO.Ably.Shared/Extensions/PresenceExtensions.cs b/src/IO.Ably.Shared/Extensions/PresenceExtensions.cs index f5f4f6b23..64c6f97dc 100644 --- a/src/IO.Ably.Shared/Extensions/PresenceExtensions.cs +++ b/src/IO.Ably.Shared/Extensions/PresenceExtensions.cs @@ -2,7 +2,7 @@ { internal static class PresenceExtensions { - public static bool IsSynthesized(this PresenceMessage msg) + public static bool IsServerSynthesized(this PresenceMessage msg) { return msg.Id == null || !msg.Id.StartsWith(msg.ConnectionId); } @@ -11,7 +11,7 @@ public static bool IsSynthesized(this PresenceMessage msg) public static bool IsNewerThan(this PresenceMessage existingMsg, PresenceMessage incomingMsg) { // RTP2b1 - if (existingMsg.IsSynthesized() || incomingMsg.IsSynthesized()) + if (existingMsg.IsServerSynthesized() || incomingMsg.IsServerSynthesized()) { return existingMsg.Timestamp > incomingMsg.Timestamp; } diff --git a/src/IO.Ably.Shared/Realtime/Presence.cs b/src/IO.Ably.Shared/Realtime/Presence.cs index 68784ae69..42358fd7c 100644 --- a/src/IO.Ably.Shared/Realtime/Presence.cs +++ b/src/IO.Ably.Shared/Realtime/Presence.cs @@ -596,7 +596,7 @@ internal void OnPresence(PresenceMessage[] messages) // RTP2e case PresenceAction.Leave: broadcast &= MembersMap.Remove(message); - if (updateInternalPresence && !message.IsSynthesized()) + if (updateInternalPresence && !message.IsServerSynthesized()) { InternalMembersMap.Remove(message); } diff --git a/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs b/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs index 2ba561ae9..c1926a260 100644 --- a/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs +++ b/src/IO.Ably.Tests.Shared/Realtime/PresenceSandboxSpecs.cs @@ -636,7 +636,7 @@ await WaitForMultiple(2, partialDone => msgA = null; msgB = null; var synthesizedMsg = new PresenceMessage(PresenceAction.Leave, clientB.ClientId) { ConnectionId = null }; - synthesizedMsg.IsSynthesized().Should().BeTrue(); + synthesizedMsg.IsServerSynthesized().Should().BeTrue(); channelB.Presence.OnPresence(new[] { synthesizedMsg }); msgB.Should().BeNull(); From ca859293a53076fae8e8808dc42334eb76d6430b Mon Sep 17 00:00:00 2001 From: sacOO7 Date: Fri, 19 Apr 2024 19:26:46 +0530 Subject: [PATCH 15/15] Refactored README with supported platforms --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 06e0a190b..19eaf5ab2 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ This is a .NET client library for Ably which targets the 2.0 client library spec ## Supported platforms * [.NET Standard 2.0+](https://learn.microsoft.com/en-us/dotnet/standard/net-standard?tabs=net-standard-2-0) -* .NET 6.x, 7.x, MAUI, check [MAUI config](#maui-configuration). +* .NET 6.0+, MAUI, check [MAUI config](#maui-configuration). * .NET Framework 4.6.2+ * .NET (Core) 2.0+ * Mono 5.4+ @@ -424,7 +424,6 @@ var options = new ClientOptions { AuthCallback = async tokenParams => { - // Return serialized jwttokenstring returned from server string jwtToken = await getJwtTokenFromServer(tokenParams); int expiresIn = 3600; // assuming jwtToken has 1 hr expiry return new TokenDetails(jwtToken) {