From ef437c9724792efbb60e604e52c6fca27084eb4c Mon Sep 17 00:00:00 2001 From: DJGosnell Date: Wed, 13 Dec 2023 18:25:34 -0500 Subject: [PATCH 1/7] Added proxy invocations for all clients in groups except for the currently invoking session. Added tests. --- .../NexusServerTests_NexusInvocations.cs | 107 ++++++++++++++++++ src/NexNet/Invocation/IProxyBase.cs | 16 +++ src/NexNet/Invocation/ProxyInvocationBase.cs | 20 ++-- src/NexNet/Invocation/ProxyInvocationMode.cs | 1 + src/NexNet/Invocation/ServerNexusContext.cs | 27 +++++ src/NexNet/Invocation/ServerSessionContext.cs | 26 +++++ src/NexNet/Invocation/SessionManager.cs | 19 +++- 7 files changed, 202 insertions(+), 14 deletions(-) diff --git a/src/NexNet.IntegrationTests/NexusServerTests_NexusInvocations.cs b/src/NexNet.IntegrationTests/NexusServerTests_NexusInvocations.cs index e2b9bbfa..5d6ed720 100644 --- a/src/NexNet.IntegrationTests/NexusServerTests_NexusInvocations.cs +++ b/src/NexNet.IntegrationTests/NexusServerTests_NexusInvocations.cs @@ -1,5 +1,6 @@ using System.Buffers; using System.Collections; +using NexNet.IntegrationTests.Pipes; using NexNet.IntegrationTests.TestInterfaces; using NUnit.Framework; #pragma warning disable VSTHRD200 @@ -261,6 +262,112 @@ public async Task NexusInvokesOnGroups(Type type) await tcs2.Task.Timeout(1); } + [TestCase(Type.Uds)] + [TestCase(Type.Tcp)] + [TestCase(Type.TcpTls)] + [TestCase(Type.Quic)] + public async Task NexusInvokesOnGroupExceptCurrent(Type type) + { + var invocationCount = 0; + var tcs1 = new TaskCompletionSource(); + int connectedCount = 0; + + var (client1, clientNexus1) = CreateClient(CreateClientConfig(type)); + var (client2, clientNexus2) = CreateClient(CreateClientConfig(type)); + + var server = CreateServer(CreateServerConfig(type), connectedNexus => + { + connectedNexus.OnConnectedEvent = async nexus => + { + Interlocked.Increment(ref connectedCount); + nexus.Context.Groups.Add("group"); + + if (connectedCount == 1) + { + _ = client2.ConnectAsync().Timeout(1); + } + else if (connectedCount == 2) + { + await nexus.Context.Clients.GroupExceptCaller("group").ClientTask(); + } + }; + }); + +#pragma warning disable CS1998 + clientNexus1.ClientTaskEvent = async _ => + { + Interlocked.Increment(ref invocationCount); + tcs1.TrySetResult(); + }; + clientNexus2.ClientTaskEvent = async _ => + { + Interlocked.Increment(ref invocationCount); + }; + +#pragma warning restore CS1998 + await server.StartAsync().Timeout(1); + + await client1.ConnectAsync().Timeout(1); + + await tcs1.Task.Timeout(1); + Assert.AreEqual(1, invocationCount); + } + + [TestCase(Type.Uds)] + [TestCase(Type.Tcp)] + [TestCase(Type.TcpTls)] + [TestCase(Type.Quic)] + public async Task NexusInvokesOnGroupsExceptCurrent(Type type) + { + var invocationCount = 0; + var tcs1 = new TaskCompletionSource(); + int connectedCount = 0; + var invocationOnFirstClient = 0; + + var (client1, clientNexus1) = CreateClient(CreateClientConfig(type)); + var (client2, clientNexus2) = CreateClient(CreateClientConfig(type)); + + var server = CreateServer(CreateServerConfig(type), connectedNexus => + { + connectedNexus.OnConnectedEvent = async nexus => + { + Interlocked.Increment(ref connectedCount); + nexus.Context.Groups.Add("group"); + nexus.Context.Groups.Add("group2"); + + if (connectedCount == 1) + { + _ = client2.ConnectAsync().Timeout(1); + } + else if (connectedCount == 2) + { + await nexus.Context.Clients.GroupsExceptCaller(new[] { "group", "group2" }).ClientTask(); + } + }; + }); + +#pragma warning disable CS1998 + clientNexus1.ClientTaskEvent = async _ => + { + Interlocked.Increment(ref invocationCount); + + if (++invocationOnFirstClient == 2) + tcs1.TrySetResult(); + }; + clientNexus2.ClientTaskEvent = async _ => + { + Interlocked.Increment(ref invocationCount); + }; + +#pragma warning restore CS1998 + await server.StartAsync().Timeout(1); + + await client1.ConnectAsync().Timeout(1); + + await tcs1.Task.Timeout(1); + Assert.AreEqual(2, invocationCount); + } + [TestCase(Type.Uds)] [TestCase(Type.Tcp)] [TestCase(Type.TcpTls)] diff --git a/src/NexNet/Invocation/IProxyBase.cs b/src/NexNet/Invocation/IProxyBase.cs index 83dde397..6c0624e3 100644 --- a/src/NexNet/Invocation/IProxyBase.cs +++ b/src/NexNet/Invocation/IProxyBase.cs @@ -35,6 +35,14 @@ public interface IProxyBase /// Proxy TProxy Group(string groupName); + /// + /// Proxy for all clients part of the specified group. + /// Will not send the invocation to the current calling session. + /// + /// Group name to get the proxy for. + /// Proxy + TProxy GroupExceptCaller(string groupName); + /// /// Proxy for all clients part of the specified groups. /// @@ -42,6 +50,14 @@ public interface IProxyBase /// Proxy TProxy Groups(string[] groupName); + /// + /// Proxy for all clients part of the specified groups. + /// Will not send the invocation to the current calling session. + /// + /// Group names to get the proxies for. + /// Proxy + TProxy GroupsExceptCaller(string[] groupName); + /// /// Gets all the connected client ids. /// diff --git a/src/NexNet/Invocation/ProxyInvocationBase.cs b/src/NexNet/Invocation/ProxyInvocationBase.cs index d9824557..7d01fbf0 100644 --- a/src/NexNet/Invocation/ProxyInvocationBase.cs +++ b/src/NexNet/Invocation/ProxyInvocationBase.cs @@ -61,6 +61,7 @@ void IProxyInvoker.Configure( // break; case ProxyInvocationMode.Groups: + case ProxyInvocationMode.GroupsExceptCaller: _modeGroupArguments = Unsafe.As(modeArguments!); break; @@ -240,6 +241,7 @@ protected async ValueTask __ProxyInvokeMethodCore(ushort methodId, ITuple? argum // }, message); // break; case ProxyInvocationMode.Groups: + case ProxyInvocationMode.GroupsExceptCaller: { if (flags.HasFlag(InvocationFlags.DuplexPipe)) throw new InvalidOperationException( @@ -251,18 +253,11 @@ protected async ValueTask __ProxyInvokeMethodCore(ushort methodId, ITuple? argum for (int i = 0; i < _modeGroupArguments!.Length; i++) { - await _sessionManager.GroupChannelIterator(_modeGroupArguments[i], - static async (session, message) => - { - try - { - await session.SendMessage(message).ConfigureAwait(false); - } - catch - { - // Don't care if we can't invoke on another session here. - } - }, message).ConfigureAwait(false); + await _sessionManager.GroupChannelIterator( + _modeGroupArguments[i], + static (session, message) => session.SendMessage(message), + message, + _mode == ProxyInvocationMode.GroupsExceptCaller ? _session?.Id : null).ConfigureAwait(false); } break; @@ -395,6 +390,7 @@ private void ReturnState(RegisteredInvocationState state) // on the results on this proxy invocation. if (_mode == ProxyInvocationMode.All || _mode == ProxyInvocationMode.Groups + || _mode == ProxyInvocationMode.GroupsExceptCaller || _mode == ProxyInvocationMode.AllExcept || _mode == ProxyInvocationMode.Clients || _mode == ProxyInvocationMode.Others) diff --git a/src/NexNet/Invocation/ProxyInvocationMode.cs b/src/NexNet/Invocation/ProxyInvocationMode.cs index 15559708..7293dba1 100644 --- a/src/NexNet/Invocation/ProxyInvocationMode.cs +++ b/src/NexNet/Invocation/ProxyInvocationMode.cs @@ -10,4 +10,5 @@ internal enum ProxyInvocationMode Clients, //Group, Groups, + GroupsExceptCaller, } diff --git a/src/NexNet/Invocation/ServerNexusContext.cs b/src/NexNet/Invocation/ServerNexusContext.cs index 9b3d73cd..8c8150c3 100644 --- a/src/NexNet/Invocation/ServerNexusContext.cs +++ b/src/NexNet/Invocation/ServerNexusContext.cs @@ -95,6 +95,20 @@ public TClientProxy Group(string groupName) return proxy; } + public TClientProxy GroupExceptCaller(string groupName) + { + var proxy = _cacheManager.ProxyCache.Rent( + null, + _sessionManager, + _cacheManager, + ProxyInvocationMode.Groups, + new[] { groupName }); + _instancedProxies.Push(proxy); + + return proxy; + } + + public TClientProxy Groups(string[] groupName) { var proxy = _cacheManager.ProxyCache.Rent( @@ -108,6 +122,19 @@ public TClientProxy Groups(string[] groupName) return proxy; } + public TClientProxy GroupsExceptCaller(string[] groupName) + { + var proxy = _cacheManager.ProxyCache.Rent( + null, + _sessionManager, + _cacheManager, + ProxyInvocationMode.Groups, + groupName); + _instancedProxies.Push(proxy); + + return proxy; + } + public IEnumerable GetIds() { return _sessionManager.Sessions.Keys; diff --git a/src/NexNet/Invocation/ServerSessionContext.cs b/src/NexNet/Invocation/ServerSessionContext.cs index 360c7667..94226ee3 100644 --- a/src/NexNet/Invocation/ServerSessionContext.cs +++ b/src/NexNet/Invocation/ServerSessionContext.cs @@ -130,6 +130,19 @@ public TClientProxy Group(string groupName) return proxy; } + public TClientProxy GroupExceptCaller(string groupName) + { + var proxy = _cacheManager.ProxyCache.Rent( + _context.Session, + _context.SessionManager, + _context.Session.CacheManager, + ProxyInvocationMode.GroupsExceptCaller, + new[] { groupName }); + _instancedProxies.Push(proxy); + + return proxy; + } + public TClientProxy Groups(string[] groupName) { var proxy = _cacheManager.ProxyCache.Rent( @@ -143,6 +156,19 @@ public TClientProxy Groups(string[] groupName) return proxy; } + public TClientProxy GroupsExceptCaller(string[] groupName) + { + var proxy = _cacheManager.ProxyCache.Rent( + _context.Session, + _context.SessionManager, + _context.Session.CacheManager, + ProxyInvocationMode.GroupsExceptCaller, + groupName); + _instancedProxies.Push(proxy); + + return proxy; + } + public IEnumerable GetIds() { return _context.SessionManager?.Sessions.Keys ?? Array.Empty(); diff --git a/src/NexNet/Invocation/SessionManager.cs b/src/NexNet/Invocation/SessionManager.cs index e3775a3f..5adf7039 100644 --- a/src/NexNet/Invocation/SessionManager.cs +++ b/src/NexNet/Invocation/SessionManager.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using NexNet.Internals; +using static System.Collections.Specialized.BitVector32; namespace NexNet.Invocation; /// @@ -94,7 +95,11 @@ public void RegisterSessionGroup(string[] groupNames, INexusSession session) } } - public async ValueTask GroupChannelIterator(string groupName, Func channelIterator, T state) + public async ValueTask GroupChannelIterator( + string groupName, + Func channelIterator, + T state, + long? excludeSessionId) { if (!_groupIdDictionary.TryGetValue(groupName, out int id)) return; @@ -104,7 +109,17 @@ public async ValueTask GroupChannelIterator(string groupName, Func Date: Wed, 13 Dec 2023 18:29:15 -0500 Subject: [PATCH 2/7] Simplified invocations for ServerSessionContext. --- src/NexNet/Invocation/ServerSessionContext.cs | 30 ++----------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/src/NexNet/Invocation/ServerSessionContext.cs b/src/NexNet/Invocation/ServerSessionContext.cs index 94226ee3..c7bde07b 100644 --- a/src/NexNet/Invocation/ServerSessionContext.cs +++ b/src/NexNet/Invocation/ServerSessionContext.cs @@ -119,28 +119,12 @@ public TClientProxy Clients(long[] ids) public TClientProxy Group(string groupName) { - var proxy = _cacheManager.ProxyCache.Rent( - _context.Session, - _context.SessionManager, - _context.Session.CacheManager, - ProxyInvocationMode.Groups, - new[] { groupName }); - _instancedProxies.Push(proxy); - - return proxy; + return Groups(new []{ groupName }); } public TClientProxy GroupExceptCaller(string groupName) { - var proxy = _cacheManager.ProxyCache.Rent( - _context.Session, - _context.SessionManager, - _context.Session.CacheManager, - ProxyInvocationMode.GroupsExceptCaller, - new[] { groupName }); - _instancedProxies.Push(proxy); - - return proxy; + return Groups(new[] { groupName }); } public TClientProxy Groups(string[] groupName) @@ -158,15 +142,7 @@ public TClientProxy Groups(string[] groupName) public TClientProxy GroupsExceptCaller(string[] groupName) { - var proxy = _cacheManager.ProxyCache.Rent( - _context.Session, - _context.SessionManager, - _context.Session.CacheManager, - ProxyInvocationMode.GroupsExceptCaller, - groupName); - _instancedProxies.Push(proxy); - - return proxy; + return Groups(groupName); } public IEnumerable GetIds() From 489123a7b22ff32a4e3211b6cf5e377324a838a9 Mon Sep 17 00:00:00 2001 From: DJGosnell Date: Thu, 11 Jan 2024 18:04:01 -0500 Subject: [PATCH 3/7] Updated year. Started reworking tests for stability. --- .../NexusServerTests_NexusInvocations.cs | 44 ++++++++++--------- src/NexNet.props | 2 +- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/NexNet.IntegrationTests/NexusServerTests_NexusInvocations.cs b/src/NexNet.IntegrationTests/NexusServerTests_NexusInvocations.cs index 5d6ed720..f8b86549 100644 --- a/src/NexNet.IntegrationTests/NexusServerTests_NexusInvocations.cs +++ b/src/NexNet.IntegrationTests/NexusServerTests_NexusInvocations.cs @@ -268,49 +268,51 @@ public async Task NexusInvokesOnGroups(Type type) [TestCase(Type.Quic)] public async Task NexusInvokesOnGroupExceptCurrent(Type type) { - var invocationCount = 0; - var tcs1 = new TaskCompletionSource(); + var groupInvokedCount = 0; + var voidInvokedCount = 0; int connectedCount = 0; + var tcs1 = new TaskCompletionSource(); - var (client1, clientNexus1) = CreateClient(CreateClientConfig(type)); - var (client2, clientNexus2) = CreateClient(CreateClientConfig(type)); + var (client1, clientNexus1) = CreateClient(CreateClientConfig(type, BasePipeTests.LogMode.Always)); + var (client2, clientNexus2) = CreateClient(CreateClientConfig(type, BasePipeTests.LogMode.Always)); - var server = CreateServer(CreateServerConfig(type), connectedNexus => + var server = CreateServer(CreateServerConfig(type, BasePipeTests.LogMode.Always), connectedNexus => { connectedNexus.OnConnectedEvent = async nexus => { Interlocked.Increment(ref connectedCount); nexus.Context.Groups.Add("group"); - - if (connectedCount == 1) - { - _ = client2.ConnectAsync().Timeout(1); - } - else if (connectedCount == 2) + + if (connectedCount == 2) { await nexus.Context.Clients.GroupExceptCaller("group").ClientTask(); + nexus.Context.Clients.Group("group").ClientVoid(); } }; }); -#pragma warning disable CS1998 - clientNexus1.ClientTaskEvent = async _ => + clientNexus1.ClientTaskEvent = clientNexus2.ClientTaskEvent = async _ => { - Interlocked.Increment(ref invocationCount); - tcs1.TrySetResult(); + Interlocked.Increment(ref groupInvokedCount); }; - clientNexus2.ClientTaskEvent = async _ => + + clientNexus1.ClientVoidEvent = clientNexus2.ClientVoidEvent = async _ => { - Interlocked.Increment(ref invocationCount); + Interlocked.Increment(ref voidInvokedCount); + + if (voidInvokedCount == 2) + { + tcs1.SetResult(); + } }; -#pragma warning restore CS1998 await server.StartAsync().Timeout(1); - - await client1.ConnectAsync().Timeout(1); + + await client1.ConnectAsync(); + await client2.ConnectAsync(); await tcs1.Task.Timeout(1); - Assert.AreEqual(1, invocationCount); + Assert.AreEqual(1, groupInvokedCount); } [TestCase(Type.Uds)] diff --git a/src/NexNet.props b/src/NexNet.props index 42418df1..11344a9a 100644 --- a/src/NexNet.props +++ b/src/NexNet.props @@ -8,7 +8,7 @@ snupkg Dtronix NexNet - Copyright © Dtronix 2023 + Copyright © Dtronix 2024 DJGosnell https://github.com/Dtronix/NexNet https://github.com/Dtronix/NexNet From d4e248f700b8b677f5754619781c9dab56b5af79 Mon Sep 17 00:00:00 2001 From: DJGosnell Date: Fri, 12 Jan 2024 13:41:55 -0500 Subject: [PATCH 4/7] Fixed group "except" invocations. Updated tests. --- .../NexusServerTests_NexusInvocations.cs | 92 +++++++++---------- src/NexNet/Invocation/ServerSessionContext.cs | 14 ++- 2 files changed, 57 insertions(+), 49 deletions(-) diff --git a/src/NexNet.IntegrationTests/NexusServerTests_NexusInvocations.cs b/src/NexNet.IntegrationTests/NexusServerTests_NexusInvocations.cs index f8b86549..5be73b4b 100644 --- a/src/NexNet.IntegrationTests/NexusServerTests_NexusInvocations.cs +++ b/src/NexNet.IntegrationTests/NexusServerTests_NexusInvocations.cs @@ -270,46 +270,47 @@ public async Task NexusInvokesOnGroupExceptCurrent(Type type) { var groupInvokedCount = 0; var voidInvokedCount = 0; - int connectedCount = 0; var tcs1 = new TaskCompletionSource(); - var (client1, clientNexus1) = CreateClient(CreateClientConfig(type, BasePipeTests.LogMode.Always)); - var (client2, clientNexus2) = CreateClient(CreateClientConfig(type, BasePipeTests.LogMode.Always)); + var (client1, clientNexus1) = CreateClient(CreateClientConfig(type)); + var (client2, clientNexus2) = CreateClient(CreateClientConfig(type)); - var server = CreateServer(CreateServerConfig(type, BasePipeTests.LogMode.Always), connectedNexus => + var server = CreateServer(CreateServerConfig(type), connectedNexus => { - connectedNexus.OnConnectedEvent = async nexus => + connectedNexus.ServerTaskEvent = async nexus => + { + await nexus.Context.Clients.GroupExceptCaller("group").ClientTask(); + + // Delay to ensure the method has time to invoke on the client sessions. + await Task.Delay(50); + nexus.Context.Clients.Group("group").ClientVoid(); + }; + + connectedNexus.OnConnectedEvent = nexus => { - Interlocked.Increment(ref connectedCount); nexus.Context.Groups.Add("group"); - - if (connectedCount == 2) - { - await nexus.Context.Clients.GroupExceptCaller("group").ClientTask(); - nexus.Context.Clients.Group("group").ClientVoid(); - } + return ValueTask.CompletedTask; }; }); - clientNexus1.ClientTaskEvent = clientNexus2.ClientTaskEvent = async _ => + clientNexus1.ClientTaskEvent = clientNexus2.ClientTaskEvent = _ => { Interlocked.Increment(ref groupInvokedCount); + return ValueTask.CompletedTask; }; - clientNexus1.ClientVoidEvent = clientNexus2.ClientVoidEvent = async _ => + clientNexus1.ClientVoidEvent = clientNexus2.ClientVoidEvent = _ => { - Interlocked.Increment(ref voidInvokedCount); - - if (voidInvokedCount == 2) - { + if (Interlocked.Increment(ref voidInvokedCount) == 2) tcs1.SetResult(); - } }; await server.StartAsync().Timeout(1); - await client1.ConnectAsync(); - await client2.ConnectAsync(); + await client1.ConnectAsync().Timeout(1); + await client2.ConnectAsync().Timeout(1); + + await client1.Proxy.ServerTask(); await tcs1.Task.Timeout(1); Assert.AreEqual(1, groupInvokedCount); @@ -321,53 +322,52 @@ public async Task NexusInvokesOnGroupExceptCurrent(Type type) [TestCase(Type.Quic)] public async Task NexusInvokesOnGroupsExceptCurrent(Type type) { - var invocationCount = 0; + var groupInvokedCount = 0; + var voidInvokedCount = 0; var tcs1 = new TaskCompletionSource(); - int connectedCount = 0; - var invocationOnFirstClient = 0; var (client1, clientNexus1) = CreateClient(CreateClientConfig(type)); var (client2, clientNexus2) = CreateClient(CreateClientConfig(type)); var server = CreateServer(CreateServerConfig(type), connectedNexus => { - connectedNexus.OnConnectedEvent = async nexus => + connectedNexus.ServerTaskEvent = async nexus => { - Interlocked.Increment(ref connectedCount); - nexus.Context.Groups.Add("group"); - nexus.Context.Groups.Add("group2"); + await nexus.Context.Clients.GroupsExceptCaller(["group1", "group2"]).ClientTask(); + + // Delay to ensure the method has time to invoke on the client sessions. + await Task.Delay(50); + nexus.Context.Clients.Group("group1").ClientVoid(); + }; - if (connectedCount == 1) - { - _ = client2.ConnectAsync().Timeout(1); - } - else if (connectedCount == 2) - { - await nexus.Context.Clients.GroupsExceptCaller(new[] { "group", "group2" }).ClientTask(); - } + connectedNexus.OnConnectedEvent = nexus => + { + nexus.Context.Groups.Add(["group1", "group2"]); + return ValueTask.CompletedTask; }; }); -#pragma warning disable CS1998 - clientNexus1.ClientTaskEvent = async _ => + clientNexus1.ClientTaskEvent = clientNexus2.ClientTaskEvent = _ => { - Interlocked.Increment(ref invocationCount); - - if (++invocationOnFirstClient == 2) - tcs1.TrySetResult(); + Interlocked.Increment(ref groupInvokedCount); + return ValueTask.CompletedTask; }; - clientNexus2.ClientTaskEvent = async _ => + + clientNexus1.ClientVoidEvent = clientNexus2.ClientVoidEvent = _ => { - Interlocked.Increment(ref invocationCount); + if (Interlocked.Increment(ref voidInvokedCount) == 2) + tcs1.SetResult(); }; -#pragma warning restore CS1998 await server.StartAsync().Timeout(1); await client1.ConnectAsync().Timeout(1); + await client2.ConnectAsync().Timeout(1); + + await client1.Proxy.ServerTask(); await tcs1.Task.Timeout(1); - Assert.AreEqual(2, invocationCount); + Assert.AreEqual(2, groupInvokedCount); } [TestCase(Type.Uds)] diff --git a/src/NexNet/Invocation/ServerSessionContext.cs b/src/NexNet/Invocation/ServerSessionContext.cs index c7bde07b..c23e1225 100644 --- a/src/NexNet/Invocation/ServerSessionContext.cs +++ b/src/NexNet/Invocation/ServerSessionContext.cs @@ -119,12 +119,12 @@ public TClientProxy Clients(long[] ids) public TClientProxy Group(string groupName) { - return Groups(new []{ groupName }); + return Groups(new[] { groupName }); } public TClientProxy GroupExceptCaller(string groupName) { - return Groups(new[] { groupName }); + return GroupsExceptCaller(new[] { groupName }); } public TClientProxy Groups(string[] groupName) @@ -142,7 +142,15 @@ public TClientProxy Groups(string[] groupName) public TClientProxy GroupsExceptCaller(string[] groupName) { - return Groups(groupName); + var proxy = _cacheManager.ProxyCache.Rent( + _context.Session, + _context.SessionManager, + _context.Session.CacheManager, + ProxyInvocationMode.GroupsExceptCaller, + groupName); + _instancedProxies.Push(proxy); + + return proxy; } public IEnumerable GetIds() From a65f79763502e981838f61ef54c165faaf380a4b Mon Sep 17 00:00:00 2001 From: DJGosnell Date: Fri, 12 Jan 2024 13:51:06 -0500 Subject: [PATCH 5/7] Added more tests. --- .../NexusServerTests_NexusInvocations.cs | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/src/NexNet.IntegrationTests/NexusServerTests_NexusInvocations.cs b/src/NexNet.IntegrationTests/NexusServerTests_NexusInvocations.cs index 5be73b4b..59a77d65 100644 --- a/src/NexNet.IntegrationTests/NexusServerTests_NexusInvocations.cs +++ b/src/NexNet.IntegrationTests/NexusServerTests_NexusInvocations.cs @@ -370,6 +370,106 @@ public async Task NexusInvokesOnGroupsExceptCurrent(Type type) Assert.AreEqual(2, groupInvokedCount); } + [TestCase(Type.Uds)] + [TestCase(Type.Tcp)] + [TestCase(Type.TcpTls)] + [TestCase(Type.Quic)] + public async Task DirectNexusProxyInvokesOnGroupIncludingCurrent(Type type) + { + var groupInvokedCount = 0; + var voidInvokedCount = 0; + var tcs1 = new TaskCompletionSource(); + + var (client1, clientNexus1) = CreateClient(CreateClientConfig(type)); + var (client2, clientNexus2) = CreateClient(CreateClientConfig(type)); + + var server = CreateServer(CreateServerConfig(type), connectedNexus => + { + connectedNexus.OnConnectedEvent = nexus => + { + nexus.Context.Groups.Add("group"); + return ValueTask.CompletedTask; + }; + }); + + clientNexus1.ClientTaskEvent = clientNexus2.ClientTaskEvent = _ => + { + Interlocked.Increment(ref groupInvokedCount); + return ValueTask.CompletedTask; + }; + + clientNexus1.ClientVoidEvent = clientNexus2.ClientVoidEvent = _ => + { + if (Interlocked.Increment(ref voidInvokedCount) == 2) + tcs1.SetResult(); + }; + + await server.StartAsync().Timeout(1); + + await client1.ConnectAsync().Timeout(1); + await client2.ConnectAsync().Timeout(1); + + await server.GetContext().Clients.GroupExceptCaller("group").ClientTask(); + + // Delay to ensure the method has time to invoke on the client sessions. + await Task.Delay(50); + + server.GetContext().Clients.GroupExceptCaller("group").ClientVoid(); + + await tcs1.Task.Timeout(1); + Assert.AreEqual(2, groupInvokedCount); + } + + [TestCase(Type.Uds)] + [TestCase(Type.Tcp)] + [TestCase(Type.TcpTls)] + [TestCase(Type.Quic)] + public async Task DirectNexusProxyInvokesOnGroupsIncludingCurrent(Type type) + { + var groupInvokedCount = 0; + var voidInvokedCount = 0; + var tcs1 = new TaskCompletionSource(); + + var (client1, clientNexus1) = CreateClient(CreateClientConfig(type)); + var (client2, clientNexus2) = CreateClient(CreateClientConfig(type)); + + var server = CreateServer(CreateServerConfig(type), connectedNexus => + { + connectedNexus.OnConnectedEvent = nexus => + { + nexus.Context.Groups.Add(["group1", "group2"]); + return ValueTask.CompletedTask; + }; + }); + + clientNexus1.ClientTaskEvent = clientNexus2.ClientTaskEvent = _ => + { + Interlocked.Increment(ref groupInvokedCount); + return ValueTask.CompletedTask; + }; + + clientNexus1.ClientVoidEvent = clientNexus2.ClientVoidEvent = _ => + { + if (Interlocked.Increment(ref voidInvokedCount) == 2) + tcs1.SetResult(); + }; + + await server.StartAsync().Timeout(1); + + await client1.ConnectAsync().Timeout(1); + await client2.ConnectAsync().Timeout(1); + + await server.GetContext().Clients.GroupsExceptCaller(["group1", "group2"]).ClientTask(); + + // Delay to ensure the method has time to invoke on the client sessions. + await Task.Delay(50); + + server.GetContext().Clients.GroupExceptCaller("group1").ClientVoid(); + + await tcs1.Task.Timeout(1); + Assert.AreEqual(4, groupInvokedCount); + } + [TestCase(Type.Uds)] [TestCase(Type.Tcp)] [TestCase(Type.TcpTls)] From 89c907adcfaf3d8ed90c8f5fbe7d0845236b5e35 Mon Sep 17 00:00:00 2001 From: DJGosnell Date: Fri, 12 Jan 2024 14:02:33 -0500 Subject: [PATCH 6/7] Fixed build warnings. --- src/NexNet.Generator/NexusGenerator.Emitter.cs | 15 ++++++++------- .../Pipelines/ConnectionAbortedException.cs | 4 +--- .../Pipelines/ConnectionResetException.cs | 2 -- src/NexNet/Invocation/ProxyInvocationBase.cs | 4 ++-- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/NexNet.Generator/NexusGenerator.Emitter.cs b/src/NexNet.Generator/NexusGenerator.Emitter.cs index 30a2752d..61d945bf 100644 --- a/src/NexNet.Generator/NexusGenerator.Emitter.cs +++ b/src/NexNet.Generator/NexusGenerator.Emitter.cs @@ -297,7 +297,8 @@ public void EmitNexusInvocation(StringBuilder sb, InvocationInterfaceMeta proxyI /// Emits the invocation of the method on the nexus. /// /// - public void EmitNexusMethodInvocation(StringBuilder sb, bool writeParamNames) + /// Change the output to write the output params. Used for logging. + public void EmitNexusMethodInvocation(StringBuilder sb, bool forLog) { sb.Append(this.Name).Append("("); @@ -309,7 +310,7 @@ public void EmitNexusMethodInvocation(StringBuilder sb, bool writeParamNames) // otherwise we need to pass the serialized value. if (methodParameterMeta.IsDuplexPipe) { - if (writeParamNames) + if (forLog) { sb.Append(methodParameterMeta.Name) .Append(" = {arguments.Item") @@ -325,7 +326,7 @@ public void EmitNexusMethodInvocation(StringBuilder sb, bool writeParamNames) } else if (methodParameterMeta.IsDuplexUnmanagedChannel) { - if (writeParamNames) + if (forLog) { sb.Append(methodParameterMeta.Name) .Append(" = {arguments.Item") @@ -343,7 +344,7 @@ public void EmitNexusMethodInvocation(StringBuilder sb, bool writeParamNames) } else if (methodParameterMeta.IsDuplexChannel) { - if (writeParamNames) + if (forLog) { sb.Append(methodParameterMeta.Name) .Append(" = {arguments.Item") @@ -361,7 +362,7 @@ public void EmitNexusMethodInvocation(StringBuilder sb, bool writeParamNames) } else if (methodParameterMeta.SerializedValue != null) { - if (writeParamNames) + if (forLog) { sb.Append(methodParameterMeta.Name) .Append(" = {arguments.Item") @@ -379,7 +380,7 @@ public void EmitNexusMethodInvocation(StringBuilder sb, bool writeParamNames) if (CancellationTokenParameter != null) { - if (writeParamNames) + if (forLog) { sb.Append(CancellationTokenParameter.Name).Append(" = ct"); } @@ -396,7 +397,7 @@ public void EmitNexusMethodInvocation(StringBuilder sb, bool writeParamNames) sb.Append(");"); - if (!writeParamNames) + if (!forLog) sb.AppendLine(); } diff --git a/src/NexNet/Internals/Pipelines/ConnectionAbortedException.cs b/src/NexNet/Internals/Pipelines/ConnectionAbortedException.cs index 36542228..6f314d2b 100644 --- a/src/NexNet/Internals/Pipelines/ConnectionAbortedException.cs +++ b/src/NexNet/Internals/Pipelines/ConnectionAbortedException.cs @@ -24,6 +24,4 @@ public ConnectionAbortedException(string message) : base(message) { } /// Create a new instance of ConnectionAbortedException /// public ConnectionAbortedException(string message, Exception inner) : base(message, inner) { } - - private ConnectionAbortedException(SerializationInfo info, StreamingContext context) : base(info, context) { } -} \ No newline at end of file +} diff --git a/src/NexNet/Internals/Pipelines/ConnectionResetException.cs b/src/NexNet/Internals/Pipelines/ConnectionResetException.cs index 3a618c09..77218fd0 100644 --- a/src/NexNet/Internals/Pipelines/ConnectionResetException.cs +++ b/src/NexNet/Internals/Pipelines/ConnectionResetException.cs @@ -24,6 +24,4 @@ public ConnectionResetException(string message) : base(message) { } /// Create a new ConnectionResetException instance /// public ConnectionResetException(string message, Exception inner) : base(message, inner) { } - - private ConnectionResetException(SerializationInfo info, StreamingContext context) : base(info, context) { } } diff --git a/src/NexNet/Invocation/ProxyInvocationBase.cs b/src/NexNet/Invocation/ProxyInvocationBase.cs index e8a62154..8d7d3e27 100644 --- a/src/NexNet/Invocation/ProxyInvocationBase.cs +++ b/src/NexNet/Invocation/ProxyInvocationBase.cs @@ -268,7 +268,7 @@ await _sessionManager.GroupChannelIterator( } /// - async ValueTask IProxyInvoker.ProxyInvokeAndWaitForResultCore(ushort methodId, ITuple? arguments, CancellationToken? cancellationToken = null) + async ValueTask IProxyInvoker.ProxyInvokeAndWaitForResultCore(ushort methodId, ITuple? arguments, CancellationToken? cancellationToken) { var state = await InvokeWaitForResultCore(methodId, arguments, cancellationToken).ConfigureAwait(false); @@ -292,7 +292,7 @@ async ValueTask IProxyInvoker.ProxyInvokeAndWaitForResultCore(ushort methodId, I } /// - async ValueTask IProxyInvoker.ProxyInvokeAndWaitForResultCore(ushort methodId, ITuple? arguments, CancellationToken? cancellationToken = null) + async ValueTask IProxyInvoker.ProxyInvokeAndWaitForResultCore(ushort methodId, ITuple? arguments, CancellationToken? cancellationToken) { var state = await InvokeWaitForResultCore(methodId, arguments, cancellationToken).ConfigureAwait(false); From 2c7fd8785a25c5f8aa61673ff7b8b722d0457822 Mon Sep 17 00:00:00 2001 From: DJGosnell Date: Fri, 12 Jan 2024 14:04:05 -0500 Subject: [PATCH 7/7] Version bump. --- src/NexNet.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NexNet.props b/src/NexNet.props index 11344a9a..cdfd0487 100644 --- a/src/NexNet.props +++ b/src/NexNet.props @@ -1,6 +1,6 @@ - 0.7.0 + 0.8.0 enable latest net8.0