From 9733c3bc8fdc65006055e8f0cf108239e75a772d Mon Sep 17 00:00:00 2001 From: Mayuki Sawatari Date: Fri, 28 Jun 2024 16:27:31 +0900 Subject: [PATCH 1/3] Expose attributes lookup of Hub methods --- src/MagicOnion.Server/Hubs/StreamingHub.cs | 5 ++-- .../Hubs/StreamingHubContext.cs | 17 ++++++------ .../StreamingHubHandlerTest.cs | 26 +++++++++---------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/MagicOnion.Server/Hubs/StreamingHub.cs b/src/MagicOnion.Server/Hubs/StreamingHub.cs index 0406edf62..0b6da9f9c 100644 --- a/src/MagicOnion.Server/Hubs/StreamingHub.cs +++ b/src/MagicOnion.Server/Hubs/StreamingHub.cs @@ -242,11 +242,10 @@ async ValueTask ProcessRequestAsync(UniqueHashDictionary ha // Create a context for each call to the hub method. var context = StreamingHubContextPool.Shared.Get(); context.Initialize( - serviceContext: (IStreamingServiceContext)Context, + handler: handler, + streamingServiceContext: (IStreamingServiceContext)Context, hubInstance: this, request: body, - path: handler.ToString(), - methodId: methodId, messageId: messageId, timestamp: DateTime.UtcNow ); diff --git a/src/MagicOnion.Server/Hubs/StreamingHubContext.cs b/src/MagicOnion.Server/Hubs/StreamingHubContext.cs index 5307e00f9..11deb5963 100644 --- a/src/MagicOnion.Server/Hubs/StreamingHubContext.cs +++ b/src/MagicOnion.Server/Hubs/StreamingHubContext.cs @@ -35,6 +35,7 @@ public class StreamingHubContext { IStreamingServiceContext streamingServiceContext = default!; ConcurrentDictionary? items; + StreamingHubHandler handler = default!; /// Object storage per invoke. public ConcurrentDictionary Items @@ -49,10 +50,12 @@ public ConcurrentDictionary Items } } + public string Path => handler.ToString(); + public ILookup AttributeLookup => handler.AttributeLookup; + public object HubInstance { get; private set; } = default!; public ReadOnlyMemory Request { get; private set; } - public string Path { get; private set; } = default!; public DateTime Timestamp { get; private set; } public Guid ConnectionId => streamingServiceContext.ContextId; @@ -60,31 +63,29 @@ public ConcurrentDictionary Items public IServiceContext ServiceContext => streamingServiceContext; internal int MessageId { get; private set; } - internal int MethodId { get; private set; } + internal int MethodId => handler.MethodId; internal int ResponseSize { get; private set; } = -1; internal Type? ResponseType { get; private set; } - internal void Initialize(IStreamingServiceContext serviceContext, object hubInstance, ReadOnlyMemory request, string path, DateTime timestamp, int messageId, int methodId) + internal void Initialize(StreamingHubHandler handler, IStreamingServiceContext streamingServiceContext, object hubInstance, ReadOnlyMemory request, DateTime timestamp, int messageId) { - streamingServiceContext = serviceContext; + this.handler = handler; + this.streamingServiceContext = streamingServiceContext; HubInstance = hubInstance; Request = request; - Path = path; Timestamp = timestamp; MessageId = messageId; - MethodId = methodId; } internal void Uninitialize() { + handler = default!; streamingServiceContext = default!; HubInstance = default!; Request = default!; - Path = default!; Timestamp = default!; MessageId = default!; - MethodId = default!; ResponseSize = -1; items?.Clear(); } diff --git a/tests/MagicOnion.Server.Tests/StreamingHubHandlerTest.cs b/tests/MagicOnion.Server.Tests/StreamingHubHandlerTest.cs index 0c6dd2918..8f454a3ae 100644 --- a/tests/MagicOnion.Server.Tests/StreamingHubHandlerTest.cs +++ b/tests/MagicOnion.Server.Tests/StreamingHubHandlerTest.cs @@ -26,7 +26,7 @@ public async Task Parameterless_Returns_Task() // Act var handler = new StreamingHubHandler(hubType, hubMethod, new StreamingHubHandlerOptions(new MagicOnionOptions()), serviceProvider); var ctx = new StreamingHubContext(); - ctx.Initialize(fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(Nil.Default), string.Empty, DateTime.Now, 0, 0); + ctx.Initialize(handler, fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(Nil.Default), DateTime.Now, 0); await handler.MethodBody.Invoke(ctx); // Assert @@ -61,7 +61,7 @@ public async Task Parameterless_Returns_TaskOfInt32() // Act var handler = new StreamingHubHandler(hubType, hubMethod, new StreamingHubHandlerOptions(new MagicOnionOptions()), serviceProvider); var ctx = new StreamingHubContext(); - ctx.Initialize(fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(Nil.Default), string.Empty, DateTime.Now, 0, 0); + ctx.Initialize(handler, fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(Nil.Default), DateTime.Now, 0); await handler.MethodBody.Invoke(ctx); // Assert @@ -95,7 +95,7 @@ public async Task Parameterless_Returns_ValueTask() // Act var handler = new StreamingHubHandler(hubType, hubMethod, new StreamingHubHandlerOptions(new MagicOnionOptions()), serviceProvider); var ctx = new StreamingHubContext(); - ctx.Initialize(fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(Nil.Default), string.Empty, DateTime.Now, 0, 0); + ctx.Initialize(handler, fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(Nil.Default), DateTime.Now, 0); await handler.MethodBody.Invoke(ctx); // Assert @@ -130,7 +130,7 @@ public async Task Parameterless_Returns_ValueTaskOfInt32() // Act var handler = new StreamingHubHandler(hubType, hubMethod, new StreamingHubHandlerOptions(new MagicOnionOptions()), serviceProvider); var ctx = new StreamingHubContext(); - ctx.Initialize(fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(Nil.Default), string.Empty, DateTime.Now, 0, 0); + ctx.Initialize(handler, fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(Nil.Default), DateTime.Now, 0); await handler.MethodBody.Invoke(ctx); // Assert @@ -165,7 +165,7 @@ public async Task Parameter_Single_Returns_Task() // Act var handler = new StreamingHubHandler(hubType, hubMethod, new StreamingHubHandlerOptions(new MagicOnionOptions()), serviceProvider); var ctx = new StreamingHubContext(); - ctx.Initialize(fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(12345), string.Empty, DateTime.Now, 0, 0); + ctx.Initialize(handler, fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(12345), DateTime.Now, 0); await handler.MethodBody.Invoke(ctx); // Assert @@ -200,7 +200,7 @@ public async Task Parameter_Multiple_Returns_Task() // Act var handler = new StreamingHubHandler(hubType, hubMethod, new StreamingHubHandlerOptions(new MagicOnionOptions()), serviceProvider); var ctx = new StreamingHubContext(); - ctx.Initialize(fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(new DynamicArgumentTuple(12345, "テスト", true)), string.Empty, DateTime.Now, 0, 0); + ctx.Initialize(handler, fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(new DynamicArgumentTuple(12345, "テスト", true)), DateTime.Now, 0); await handler.MethodBody.Invoke(ctx); // Assert @@ -234,7 +234,7 @@ public async Task Parameter_Multiple_Returns_TaskOfInt32() // Act var handler = new StreamingHubHandler(hubType, hubMethod, new StreamingHubHandlerOptions(new MagicOnionOptions()), serviceProvider); var ctx = new StreamingHubContext(); - ctx.Initialize(fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(new DynamicArgumentTuple(12345, "テスト", true)), string.Empty, DateTime.Now, 0, 0); + ctx.Initialize(handler, fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(new DynamicArgumentTuple(12345, "テスト", true)), DateTime.Now, 0); await handler.MethodBody.Invoke(ctx); // Assert @@ -270,7 +270,7 @@ public async Task CallRepeated_Parameter_Multiple_Returns_TaskOfInt32() for (var i = 0; i < 3; i++) { var ctx = new StreamingHubContext(); - ctx.Initialize(fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(new DynamicArgumentTuple(i, $"テスト{i}", i % 2 == 0)), string.Empty, DateTime.Now, i * 1000, 0); + ctx.Initialize(handler, fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(new DynamicArgumentTuple(i, $"テスト{i}", i % 2 == 0)), DateTime.Now, i * 1000); await handler.MethodBody.Invoke(ctx); } @@ -310,7 +310,7 @@ public async Task Parameterless_Void() // Act var handler = new StreamingHubHandler(hubType, hubMethod, new StreamingHubHandlerOptions(new MagicOnionOptions()), serviceProvider); var ctx = new StreamingHubContext(); - ctx.Initialize(fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(Nil.Default), string.Empty, DateTime.Now, 0, 0); + ctx.Initialize(handler, fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(Nil.Default), DateTime.Now, 0); await handler.MethodBody.Invoke(ctx); // Assert @@ -345,7 +345,7 @@ public async Task Parameter_Single_Void() // Act var handler = new StreamingHubHandler(hubType, hubMethod, new StreamingHubHandlerOptions(new MagicOnionOptions()), serviceProvider); var ctx = new StreamingHubContext(); - ctx.Initialize(fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(12345), string.Empty, DateTime.Now, 0, 0); + ctx.Initialize(handler, fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(12345), DateTime.Now, 0); await handler.MethodBody.Invoke(ctx); // Assert @@ -380,7 +380,7 @@ public async Task Parameter_Multiple_Void() // Act var handler = new StreamingHubHandler(hubType, hubMethod, new StreamingHubHandlerOptions(new MagicOnionOptions()), serviceProvider); var ctx = new StreamingHubContext(); - ctx.Initialize(fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(new DynamicArgumentTuple(12345, "テスト", true)), string.Empty, DateTime.Now, 0, 0); + ctx.Initialize(handler, fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(new DynamicArgumentTuple(12345, "テスト", true)), DateTime.Now, 0); await handler.MethodBody.Invoke(ctx); // Assert @@ -415,7 +415,7 @@ public async Task Parameter_Multiple_Void_Without_MessageId() // Act var handler = new StreamingHubHandler(hubType, hubMethod, new StreamingHubHandlerOptions(new MagicOnionOptions()), serviceProvider); var ctx = new StreamingHubContext(); - ctx.Initialize(fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(new DynamicArgumentTuple(12345, "テスト", true)), string.Empty, DateTime.Now, -1 /* The client requires no response */, 0); + ctx.Initialize(handler, fakeStreamingHubContext, hubInstance, MessagePackSerializer.Serialize(new DynamicArgumentTuple(12345, "テスト", true)), DateTime.Now, -1 /* The client requires no response */); await handler.MethodBody.Invoke(ctx); // Assert @@ -443,7 +443,7 @@ public async Task UseCustomMessageSerializer() MessageSerializer = XorMessagePackMagicOnionSerializerProvider.Instance, }), serviceProvider); var ctx = new StreamingHubContext(); - ctx.Initialize(fakeStreamingHubContext, hubInstance, bufferWriter.WrittenMemory.ToArray(), string.Empty, DateTime.Now, 0, 0); + ctx.Initialize(handler, fakeStreamingHubContext, hubInstance, bufferWriter.WrittenMemory.ToArray(), DateTime.Now, 0); await handler.MethodBody.Invoke(ctx); // Assert From 5f5b2555df20051d0125b450e69dcf90a9d8991a Mon Sep 17 00:00:00 2001 From: Mayuki Sawatari Date: Mon, 1 Jul 2024 15:12:39 +0900 Subject: [PATCH 2/3] Fix unit test --- tests/MagicOnion.Server.Tests/StreamingHubHandlerTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/MagicOnion.Server.Tests/StreamingHubHandlerTest.cs b/tests/MagicOnion.Server.Tests/StreamingHubHandlerTest.cs index 8f454a3ae..73aa1e210 100644 --- a/tests/MagicOnion.Server.Tests/StreamingHubHandlerTest.cs +++ b/tests/MagicOnion.Server.Tests/StreamingHubHandlerTest.cs @@ -286,7 +286,7 @@ byte[] BuildMessage(int messageId, int retVal) var writer = new MessagePackWriter(buffer); writer.WriteArrayHeader(3); writer.Write(messageId); - writer.Write(0 /* MethodId - Fixed */); + writer.Write(FNV1A32.GetHashCode(nameof(StreamingHubHandlerTestHub.Method_Parameter_Multiple_Returns_TaskOfInt32)) /* MethodId */); MessagePackSerializer.Serialize(ref writer, retVal); writer.Flush(); return buffer.WrittenMemory.ToArray(); From 5f9614a7145be859d4fa1a432b47aadb147eaab3 Mon Sep 17 00:00:00 2001 From: Mayuki Sawatari Date: Mon, 1 Jul 2024 15:40:48 +0900 Subject: [PATCH 3/3] Add unit test --- .../StreamingHubHandlerTest.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/MagicOnion.Server.Tests/StreamingHubHandlerTest.cs b/tests/MagicOnion.Server.Tests/StreamingHubHandlerTest.cs index 73aa1e210..877a484f2 100644 --- a/tests/MagicOnion.Server.Tests/StreamingHubHandlerTest.cs +++ b/tests/MagicOnion.Server.Tests/StreamingHubHandlerTest.cs @@ -463,6 +463,24 @@ byte[] BuildMessage() fakeStreamingHubContext.Responses[0].Memory.ToArray().Should().Equal(BuildMessage()); } + [Fact] + public async Task MethodAttributeLookup() + { + // Arrange + var services = new ServiceCollection(); + var serviceProvider = services.BuildServiceProvider(); + var hubType = typeof(StreamingHubHandlerTestHub); + var hubMethod = hubType.GetMethod(nameof(StreamingHubHandlerTestHub.Method_Attribute))!; + + // Act + var handler = new StreamingHubHandler(hubType, hubMethod, new StreamingHubHandlerOptions(new MagicOnionOptions()), serviceProvider); + + // Assert + Assert.NotEmpty(handler.AttributeLookup); + Assert.NotEmpty(handler.AttributeLookup[typeof(CustomMethodAttribute)]); + Assert.NotEmpty(handler.AttributeLookup[typeof(CustomHubAttribute)]); + } + interface IStreamingHubHandlerTestHubReceiver { } @@ -482,8 +500,16 @@ interface IStreamingHubHandlerTestHub : IStreamingHub Results { get; } = new List(); @@ -548,5 +574,8 @@ public void Method_Parameter_Multiple_Void(int arg0, string arg1, bool arg2) { Results.Add(nameof(Method_Parameter_Multiple_Void) + $"({arg0},{arg1},{arg2}) called."); } + + [CustomMethod] + public Task Method_Attribute() => Task.CompletedTask; } }