diff --git a/.gitattributes b/.gitattributes index 018b045b3..2b3522614 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,6 @@ -src/MagicOnion.HttpGateway/Swagger/SwaggerUI/* linguist-vendored \ No newline at end of file +src/MagicOnion.HttpGateway/Swagger/SwaggerUI/* linguist-vendored +*.csproj text +*.props text +*.targets text +*.cs text +*.xml text diff --git a/Directory.Packages.props b/Directory.Packages.props index 8070d98b2..1a7a0d6cc 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -20,6 +20,7 @@ + diff --git a/src/MagicOnion.Client.Unity/Assets/Scripts/MagicOnion/MagicOnion.Client/Internal.Shared/Buffers/MemoryPoolBufferWriter.cs b/src/MagicOnion.Client.Unity/Assets/Scripts/MagicOnion/MagicOnion.Client/Internal.Shared/Buffers/MemoryPoolBufferWriter.cs deleted file mode 100644 index 2666b3aba..000000000 --- a/src/MagicOnion.Client.Unity/Assets/Scripts/MagicOnion/MagicOnion.Client/Internal.Shared/Buffers/MemoryPoolBufferWriter.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.Buffers; - -namespace MagicOnion.Internal.Buffers -{ - public class MemoryPoolBufferWriter : IBufferWriter - { - readonly MemoryPool memoryPool; - IMemoryOwner? buffer; - int written; - - [ThreadStatic] - static MemoryPoolBufferWriter? shared; - public static MemoryPoolBufferWriter RentThreadStaticWriter() => shared ??= new MemoryPoolBufferWriter(MemoryPool.Shared); - - public MemoryPoolBufferWriter(MemoryPool memoryPool) - { - this.memoryPool = memoryPool; - this.buffer = null; - this.written = 0; - } - - public void Advance(int count) - { - written += count; - } - - public Memory GetMemory(int sizeHint = 0) - { - if (buffer != null && (buffer.Memory.Length - written) > sizeHint) - { - return buffer.Memory.Slice(written); - } - else - { - if (buffer == null) - { - // New - buffer = memoryPool.Rent(sizeHint > 0 ? sizeHint : 32767); - } - else - { - // Grow - var oldBuffer = buffer; - var newBuffer = memoryPool.Rent(buffer.Memory.Length * 2); - - oldBuffer.Memory.Slice(0, written).CopyTo(newBuffer.Memory); - oldBuffer.Dispose(); - - buffer = newBuffer; - } - return buffer.Memory.Slice(written); - } - } - - public Span GetSpan(int sizeHint = 0) - { - return GetMemory(sizeHint).Span; - } - - public (IMemoryOwner Owner, int Written) ToMemoryOwnerAndReturn() - { - var result = (buffer ?? memoryPool.Rent(0), written); - written = 0; - buffer = null; - return result; - } - } -} diff --git a/src/MagicOnion.Client.Unity/Assets/Scripts/MagicOnion/MagicOnion.Client/Internal.Shared/Buffers/MemoryPoolBufferWriter.cs.meta b/src/MagicOnion.Client.Unity/Assets/Scripts/MagicOnion/MagicOnion.Client/Internal.Shared/Buffers/MemoryPoolBufferWriter.cs.meta deleted file mode 100644 index fa5ec2709..000000000 --- a/src/MagicOnion.Client.Unity/Assets/Scripts/MagicOnion/MagicOnion.Client/Internal.Shared/Buffers/MemoryPoolBufferWriter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c58e159a2bd5bed469aa95ac4ef89613 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/src/MagicOnion.Client.Unity/Assets/Scripts/MagicOnion/MagicOnion.Client/StreamingHubClientBase.cs b/src/MagicOnion.Client.Unity/Assets/Scripts/MagicOnion/MagicOnion.Client/StreamingHubClientBase.cs index cf18930c8..c88defaa9 100644 --- a/src/MagicOnion.Client.Unity/Assets/Scripts/MagicOnion/MagicOnion.Client/StreamingHubClientBase.cs +++ b/src/MagicOnion.Client.Unity/Assets/Scripts/MagicOnion/MagicOnion.Client/StreamingHubClientBase.cs @@ -24,12 +24,12 @@ public class StreamingHubClientOptions public TimeSpan? ClientHeartbeatTimeout { get; } public Action? OnServerHeartbeatReceived { get; } public Action? OnClientHeartbeatResponseReceived { get; } -#if NET8_0_OR_GREATER +#if NON_UNITY public TimeProvider? TimeProvider { get; } #endif public StreamingHubClientOptions(string? host, CallOptions callOptions, IMagicOnionSerializerProvider serializerProvider, IMagicOnionClientLogger logger) -#if NET8_0_OR_GREATER +#if NON_UNITY : this(host, callOptions, serializerProvider, logger, default, default, default, default, default) #else : this(host, callOptions, serializerProvider, logger, default, default, default, default) @@ -37,7 +37,7 @@ public StreamingHubClientOptions(string? host, CallOptions callOptions, IMagicOn { } -#if NET8_0_OR_GREATER +#if NON_UNITY public StreamingHubClientOptions(string? host, CallOptions callOptions, IMagicOnionSerializerProvider serializerProvider, IMagicOnionClientLogger logger, TimeSpan? clientHeartbeatInterval, TimeSpan? clientHeartbeatTimeout, Action? onServerHeartbeatReceived, Action? onClientHeartbeatResponseReceived,TimeProvider? timeProvider) #else public StreamingHubClientOptions(string? host, CallOptions callOptions, IMagicOnionSerializerProvider serializerProvider, IMagicOnionClientLogger logger, TimeSpan? clientHeartbeatInterval, TimeSpan? clientHeartbeatTimeout, Action? onServerHeartbeatReceived, Action? onClientHeartbeatResponseReceived) @@ -51,7 +51,7 @@ public StreamingHubClientOptions(string? host, CallOptions callOptions, IMagicOn ClientHeartbeatTimeout = clientHeartbeatTimeout; OnServerHeartbeatReceived = onServerHeartbeatReceived; OnClientHeartbeatResponseReceived = onClientHeartbeatResponseReceived; -#if NET8_0_OR_GREATER +#if NON_UNITY TimeProvider = timeProvider; #endif } @@ -62,14 +62,14 @@ public static StreamingHubClientOptions CreateWithDefault(string? host = default public StreamingHubClientOptions WithHost(string? host) => new(host, CallOptions, SerializerProvider, Logger , ClientHeartbeatInterval, ClientHeartbeatTimeout, OnServerHeartbeatReceived, OnClientHeartbeatResponseReceived -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider #endif ); public StreamingHubClientOptions WithCallOptions(CallOptions callOptions) => new(Host, callOptions, SerializerProvider, Logger , ClientHeartbeatInterval, ClientHeartbeatTimeout, OnServerHeartbeatReceived, OnClientHeartbeatResponseReceived -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider #endif ); @@ -77,14 +77,14 @@ public StreamingHubClientOptions WithSerializerProvider(IMagicOnionSerializerPro => new( Host, CallOptions, serializerProvider, Logger , ClientHeartbeatInterval, ClientHeartbeatTimeout, OnServerHeartbeatReceived, OnClientHeartbeatResponseReceived -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider #endif ); public StreamingHubClientOptions WithLogger(IMagicOnionClientLogger logger) => new(Host, CallOptions, SerializerProvider, logger , ClientHeartbeatInterval, ClientHeartbeatTimeout, OnServerHeartbeatReceived, OnClientHeartbeatResponseReceived -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider #endif ); @@ -97,7 +97,7 @@ public StreamingHubClientOptions WithLogger(IMagicOnionClientLogger logger) public StreamingHubClientOptions WithClientHeartbeatInterval(TimeSpan? interval) => new(Host, CallOptions, SerializerProvider, Logger , interval, ClientHeartbeatTimeout, OnServerHeartbeatReceived, OnClientHeartbeatResponseReceived -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider #endif ); @@ -110,7 +110,7 @@ public StreamingHubClientOptions WithClientHeartbeatInterval(TimeSpan? interval) public StreamingHubClientOptions WithClientHeartbeatTimeout(TimeSpan? timeout) => new(Host, CallOptions, SerializerProvider, Logger , ClientHeartbeatInterval, timeout, OnServerHeartbeatReceived, OnClientHeartbeatResponseReceived -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider #endif ); @@ -123,7 +123,7 @@ public StreamingHubClientOptions WithClientHeartbeatTimeout(TimeSpan? timeout) public StreamingHubClientOptions WithServerHeartbeatReceived(Action? onServerHeartbeatReceived) => new(Host, CallOptions, SerializerProvider, Logger , ClientHeartbeatInterval, ClientHeartbeatTimeout, onServerHeartbeatReceived, OnClientHeartbeatResponseReceived -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider #endif ); @@ -136,12 +136,12 @@ public StreamingHubClientOptions WithServerHeartbeatReceived(Action? onClientHeartbeatResponseReceived) => new(Host, CallOptions, SerializerProvider, Logger , ClientHeartbeatInterval, ClientHeartbeatTimeout, OnServerHeartbeatReceived, onClientHeartbeatResponseReceived -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider #endif ); -#if NET8_0_OR_GREATER +#if NON_UNITY /// /// Sets a /// @@ -199,7 +199,7 @@ protected StreamingHubClientBase(string serviceName, TReceiver receiver, CallInv } // call immediately after create. - public async Task __ConnectAndSubscribeAsync(CancellationToken cancellationToken) + internal async Task __ConnectAndSubscribeAsync(CancellationToken cancellationToken) { var syncContext = SynchronizationContext.Current; // capture SynchronizationContext. var callResult = callInvoker.AsyncDuplexStreamingCall(duplexStreamingConnectMethod, options.Host, options.CallOptions); @@ -279,7 +279,7 @@ async Task StartSubscribe(SynchronizationContext? syncContext, Task firstM options.OnClientHeartbeatResponseReceived, syncContext, cancellationTokenSource.Token -#if NET8_0_OR_GREATER +#if NON_UNITY , options.TimeProvider ?? TimeProvider.System #endif ); diff --git a/src/MagicOnion.Client.Unity/Assets/Scripts/MagicOnion/MagicOnion.Client/StreamingHubClientHeartbeatManager.cs b/src/MagicOnion.Client.Unity/Assets/Scripts/MagicOnion/MagicOnion.Client/StreamingHubClientHeartbeatManager.cs index 809e0531f..1da3965c8 100644 --- a/src/MagicOnion.Client.Unity/Assets/Scripts/MagicOnion/MagicOnion.Client/StreamingHubClientHeartbeatManager.cs +++ b/src/MagicOnion.Client.Unity/Assets/Scripts/MagicOnion/MagicOnion.Client/StreamingHubClientHeartbeatManager.cs @@ -57,7 +57,7 @@ internal class StreamingHubClientHeartbeatManager : IDisposable readonly Action? onClientHeartbeatResponseReceived; readonly SynchronizationContext? synchronizationContext; readonly ChannelWriter writer; -#if NET8_0_OR_GREATER +#if NON_UNITY readonly TimeProvider timeProvider; #endif @@ -77,7 +77,7 @@ public StreamingHubClientHeartbeatManager( Action? onClientHeartbeatResponseReceived, SynchronizationContext? synchronizationContext, CancellationToken shutdownToken -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider timeProvider #endif ) @@ -94,7 +94,7 @@ CancellationToken shutdownToken this.onClientHeartbeatResponseReceived = onClientHeartbeatResponseReceived; this.synchronizationContext = synchronizationContext; this.shutdownTokenSource = CancellationTokenSource.CreateLinkedTokenSource(shutdownToken, timeoutTokenSource.Token); -#if NET8_0_OR_GREATER +#if NON_UNITY this.timeProvider = timeProvider; #endif } @@ -177,7 +177,7 @@ SendOrPostCallback ProcessClientHeartbeatResponseCore(Action + + + + diff --git a/src/MagicOnion.Client/PublicAPI.Shipped.txt b/src/MagicOnion.Client/PublicAPI.Shipped.txt index c756a4cea..735c9fe11 100644 --- a/src/MagicOnion.Client/PublicAPI.Shipped.txt +++ b/src/MagicOnion.Client/PublicAPI.Shipped.txt @@ -4,7 +4,7 @@ abstract MagicOnion.Client.Internal.RawMethodInvoker.Invoke abstract MagicOnion.Client.Internal.RawMethodInvoker.InvokeServerStreaming(MagicOnion.Client.MagicOnionClientBase! client, string! path, TRequest request) -> System.Threading.Tasks.Task>! abstract MagicOnion.Client.Internal.RawMethodInvoker.InvokeUnary(MagicOnion.Client.MagicOnionClientBase! client, string! path, TRequest request) -> MagicOnion.UnaryResult abstract MagicOnion.Client.Internal.RawMethodInvoker.InvokeUnaryNonGeneric(MagicOnion.Client.MagicOnionClientBase! client, string! path, TRequest request) -> MagicOnion.UnaryResult -abstract MagicOnion.Client.MagicOnionClientBase.Clone(MagicOnion.Client.MagicOnionClientOptions options) -> MagicOnion.Client.MagicOnionClientBase! +abstract MagicOnion.Client.MagicOnionClientBase.Clone(MagicOnion.Client.MagicOnionClientOptions! options) -> MagicOnion.Client.MagicOnionClientBase! abstract MagicOnion.Client.RequestContext.RequestType.get -> System.Type! abstract MagicOnion.Client.ResponseContext.Dispose() -> void abstract MagicOnion.Client.ResponseContext.GetStatus() -> Grpc.Core.Status @@ -14,8 +14,13 @@ abstract MagicOnion.Client.ResponseContext.ResponseType.get -> System.Type! abstract MagicOnion.Client.ResponseContext.WaitResponseAsync() -> System.Threading.Tasks.Task! abstract MagicOnion.Client.ResponseContext.ResponseAsync.get -> System.Threading.Tasks.Task! abstract MagicOnion.Client.ResponseContext.WithNewResult(T newValue) -> MagicOnion.Client.ResponseContext! -abstract MagicOnion.Client.StreamingHubClientBase.OnBroadcastEvent(int methodId, System.ArraySegment data) -> void -abstract MagicOnion.Client.StreamingHubClientBase.OnResponseEvent(int methodId, object! taskCompletionSource, System.ArraySegment data) -> void +abstract MagicOnion.Client.StreamingHubClientBase.OnBroadcastEvent(int methodId, System.ReadOnlyMemory data) -> void +abstract MagicOnion.Client.StreamingHubClientBase.OnClientResultEvent(int methodId, System.Guid messageId, System.ReadOnlyMemory data) -> void +abstract MagicOnion.Client.StreamingHubClientBase.OnResponseEvent(int methodId, object! taskSource, System.ReadOnlyMemory data) -> void +MagicOnion.Client.ClientHeartbeatEvent +MagicOnion.Client.ClientHeartbeatEvent.ClientHeartbeatEvent() -> void +MagicOnion.Client.ClientHeartbeatEvent.ClientHeartbeatEvent(long roundTripTimeMs) -> void +MagicOnion.Client.ClientHeartbeatEvent.RoundTripTime.get -> System.TimeSpan MagicOnion.Client.DynamicClient.DynamicMagicOnionClientFactoryProvider MagicOnion.Client.DynamicClient.DynamicMagicOnionClientFactoryProvider.TryGetFactory(out MagicOnion.Client.MagicOnionClientFactoryDelegate? factory) -> bool MagicOnion.Client.DynamicClient.DynamicNotSupportedMagicOnionClientFactoryProvider @@ -52,16 +57,12 @@ MagicOnion.Client.Internal.RawMethodInvoker MagicOnion.Client.Internal.RawMethodInvoker.RawMethodInvoker() -> void MagicOnion.Client.IStreamingHubClientFactoryProvider MagicOnion.Client.IStreamingHubClientFactoryProvider.TryGetFactory(out MagicOnion.Client.StreamingHubClientFactoryDelegate? factory) -> bool -MagicOnion.Client.IStreamingHubDiagnosticHandler -MagicOnion.Client.IStreamingHubDiagnosticHandler.InvokeMethodDelegate -MagicOnion.Client.IStreamingHubDiagnosticHandler.OnBroadcastEvent(THub hubInstance, string! methodName, T value) -> void -MagicOnion.Client.IStreamingHubDiagnosticHandler.OnMethodInvoke(THub hubInstance, int methodId, string! methodName, TRequest request, bool isFireAndForget, MagicOnion.Client.IStreamingHubDiagnosticHandler.InvokeMethodDelegate! invokeMethod) -> System.Threading.Tasks.Task! MagicOnion.Client.MagicOnionClient MagicOnion.Client.MagicOnionClientBase -MagicOnion.Client.MagicOnionClientBase.MagicOnionClientBase(MagicOnion.Client.MagicOnionClientOptions options) -> void -MagicOnion.Client.MagicOnionClientBase.Options.get -> MagicOnion.Client.MagicOnionClientOptions +MagicOnion.Client.MagicOnionClientBase.MagicOnionClientBase(MagicOnion.Client.MagicOnionClientOptions! options) -> void +MagicOnion.Client.MagicOnionClientBase.Options.get -> MagicOnion.Client.MagicOnionClientOptions! MagicOnion.Client.MagicOnionClientBase -MagicOnion.Client.MagicOnionClientBase.MagicOnionClientBase(MagicOnion.Client.MagicOnionClientOptions options) -> void +MagicOnion.Client.MagicOnionClientBase.MagicOnionClientBase(MagicOnion.Client.MagicOnionClientOptions! options) -> void MagicOnion.Client.MagicOnionClientFactoryDelegate MagicOnion.Client.MagicOnionClientFactoryProvider MagicOnion.Client.MagicOnionClientOptions @@ -69,11 +70,10 @@ MagicOnion.Client.MagicOnionClientOptions.CallInvoker.get -> Grpc.Core.CallInvok MagicOnion.Client.MagicOnionClientOptions.CallOptions.get -> Grpc.Core.CallOptions MagicOnion.Client.MagicOnionClientOptions.Filters.get -> System.Collections.Generic.IReadOnlyList! MagicOnion.Client.MagicOnionClientOptions.Host.get -> string? -MagicOnion.Client.MagicOnionClientOptions.MagicOnionClientOptions() -> void -MagicOnion.Client.MagicOnionClientOptions.MagicOnionClientOptions(Grpc.Core.CallInvoker! callInvoker, string? host, Grpc.Core.CallOptions callOptions, System.Collections.Generic.IReadOnlyList! filters) -> void -MagicOnion.Client.MagicOnionClientOptions.WithCallOptions(Grpc.Core.CallOptions callOptions) -> MagicOnion.Client.MagicOnionClientOptions -MagicOnion.Client.MagicOnionClientOptions.WithFilters(System.Collections.Generic.IReadOnlyList! filters) -> MagicOnion.Client.MagicOnionClientOptions -MagicOnion.Client.MagicOnionClientOptions.WithHost(string? host) -> MagicOnion.Client.MagicOnionClientOptions +MagicOnion.Client.MagicOnionClientOptions.MagicOnionClientOptions(Grpc.Core.CallInvoker! callInvoker, string? host, Grpc.Core.CallOptions callOptions, System.Collections.Generic.IReadOnlyList? filters) -> void +MagicOnion.Client.MagicOnionClientOptions.WithCallOptions(Grpc.Core.CallOptions callOptions) -> MagicOnion.Client.MagicOnionClientOptions! +MagicOnion.Client.MagicOnionClientOptions.WithFilters(System.Collections.Generic.IReadOnlyList! filters) -> MagicOnion.Client.MagicOnionClientOptions! +MagicOnion.Client.MagicOnionClientOptions.WithHost(string? host) -> MagicOnion.Client.MagicOnionClientOptions! MagicOnion.Client.ManagedStreamingHubInfo MagicOnion.Client.ManagedStreamingHubInfo.Client.get -> MagicOnion.IStreamingHubMarker! MagicOnion.Client.ManagedStreamingHubInfo.ManagedStreamingHubInfo() -> void @@ -98,26 +98,62 @@ MagicOnion.Client.ResponseContext.GetResponseAs() -> System.Threading.Tasks.T MagicOnion.Client.ResponseContext.ResponseContext() -> void MagicOnion.Client.ResponseContext MagicOnion.Client.ResponseContext.ResponseContext() -> void +MagicOnion.Client.ServerHeartbeatEvent +MagicOnion.Client.ServerHeartbeatEvent.Metadata.get -> System.ReadOnlyMemory +MagicOnion.Client.ServerHeartbeatEvent.ServerHeartbeatEvent() -> void +MagicOnion.Client.ServerHeartbeatEvent.ServerHeartbeatEvent(long serverTimeUnixMs, System.ReadOnlyMemory metadata) -> void +MagicOnion.Client.ServerHeartbeatEvent.ServerTime.get -> System.DateTimeOffset MagicOnion.Client.StreamingHubClient MagicOnion.Client.StreamingHubClientBase -MagicOnion.Client.StreamingHubClientBase.cts -> System.Threading.CancellationTokenSource! -MagicOnion.Client.StreamingHubClientBase.Deserialize(System.ArraySegment bytes) -> T +MagicOnion.Client.StreamingHubClientBase.Deserialize(System.ReadOnlyMemory data) -> T MagicOnion.Client.StreamingHubClientBase.DisposeAsync() -> System.Threading.Tasks.Task! -MagicOnion.Client.StreamingHubClientBase.receiver -> TReceiver MagicOnion.Client.StreamingHubClientBase.Serialize(System.Buffers.IBufferWriter! writer, in T value) -> void -MagicOnion.Client.StreamingHubClientBase.SetResultForResponse(object! taskCompletionSource, System.ArraySegment data) -> void -MagicOnion.Client.StreamingHubClientBase.StreamingHubClientBase(string! serviceName, Grpc.Core.CallInvoker! callInvoker, string? host, Grpc.Core.CallOptions option, MagicOnion.Serialization.IMagicOnionSerializerProvider! serializerProvider, MagicOnion.Client.IMagicOnionClientLogger! logger) -> void +MagicOnion.Client.StreamingHubClientBase.SetResultForResponse(object! taskSource, System.ReadOnlyMemory data) -> void +MagicOnion.Client.StreamingHubClientBase.StreamingHubClientBase(string! serviceName, TReceiver receiver, Grpc.Core.CallInvoker! callInvoker, MagicOnion.Client.StreamingHubClientOptions! options) -> void MagicOnion.Client.StreamingHubClientBase.WaitForDisconnect() -> System.Threading.Tasks.Task! -MagicOnion.Client.StreamingHubClientBase.WriteMessageFireAndForgetAsync(int methodId, TRequest message) -> System.Threading.Tasks.Task! -MagicOnion.Client.StreamingHubClientBase.WriteMessageWithResponseAsync(int methodId, TRequest message) -> System.Threading.Tasks.Task! +MagicOnion.Client.StreamingHubClientBase.AwaitAndWriteClientResultResponseMessage(int methodId, System.Guid clientResultMessageId, System.Threading.Tasks.Task! task) -> void +MagicOnion.Client.StreamingHubClientBase.AwaitAndWriteClientResultResponseMessage(int methodId, System.Guid clientResultMessageId, System.Threading.Tasks.ValueTask task) -> void +MagicOnion.Client.StreamingHubClientBase.AwaitAndWriteClientResultResponseMessage(int methodId, System.Guid clientResultMessageId, System.Threading.Tasks.Task! task) -> void +MagicOnion.Client.StreamingHubClientBase.AwaitAndWriteClientResultResponseMessage(int methodId, System.Guid clientResultMessageId, System.Threading.Tasks.ValueTask task) -> void +MagicOnion.Client.StreamingHubClientBase.WriteClientResultResponseMessageAsync(int methodId, System.Guid clientResultMessageId, T result) -> System.Threading.Tasks.Task! +MagicOnion.Client.StreamingHubClientBase.WriteClientResultResponseMessageForError(int methodId, System.Guid clientResultMessageId, System.Exception! ex) -> void +MagicOnion.Client.StreamingHubClientBase.WriteClientResultResponseMessageForErrorAsync(int methodId, System.Guid clientResultMessageId, System.Exception! ex) -> System.Threading.Tasks.Task! +MagicOnion.Client.StreamingHubClientBase.WriteMessageFireAndForgetTaskAsync(int methodId, TRequest message) -> System.Threading.Tasks.Task! +MagicOnion.Client.StreamingHubClientBase.WriteMessageFireAndForgetValueTaskAsync(int methodId, TRequest message) -> System.Threading.Tasks.ValueTask +MagicOnion.Client.StreamingHubClientBase.WriteMessageFireAndForgetValueTaskOfTAsync(int methodId, TRequest message) -> System.Threading.Tasks.ValueTask +MagicOnion.Client.StreamingHubClientBase.WriteMessageWithResponseTaskAsync(int methodId, TRequest message) -> System.Threading.Tasks.Task! +MagicOnion.Client.StreamingHubClientBase.WriteMessageWithResponseValueTaskAsync(int methodId, TRequest message) -> System.Threading.Tasks.ValueTask +MagicOnion.Client.StreamingHubClientBase.WriteMessageWithResponseValueTaskOfTAsync(int methodId, TRequest message) -> System.Threading.Tasks.ValueTask MagicOnion.Client.StreamingHubClientFactoryDelegate MagicOnion.Client.StreamingHubClientFactoryProvider +MagicOnion.Client.StreamingHubClientOptions +MagicOnion.Client.StreamingHubClientOptions.CallOptions.get -> Grpc.Core.CallOptions +MagicOnion.Client.StreamingHubClientOptions.ClientHeartbeatInterval.get -> System.TimeSpan? +MagicOnion.Client.StreamingHubClientOptions.ClientHeartbeatTimeout.get -> System.TimeSpan? +MagicOnion.Client.StreamingHubClientOptions.Host.get -> string? +MagicOnion.Client.StreamingHubClientOptions.Logger.get -> MagicOnion.Client.IMagicOnionClientLogger! +MagicOnion.Client.StreamingHubClientOptions.OnClientHeartbeatResponseReceived.get -> System.Action? +MagicOnion.Client.StreamingHubClientOptions.OnServerHeartbeatReceived.get -> System.Action? +MagicOnion.Client.StreamingHubClientOptions.SerializerProvider.get -> MagicOnion.Serialization.IMagicOnionSerializerProvider! +MagicOnion.Client.StreamingHubClientOptions.StreamingHubClientOptions(string? host, Grpc.Core.CallOptions callOptions, MagicOnion.Serialization.IMagicOnionSerializerProvider! serializerProvider, MagicOnion.Client.IMagicOnionClientLogger! logger) -> void +MagicOnion.Client.StreamingHubClientOptions.StreamingHubClientOptions(string? host, Grpc.Core.CallOptions callOptions, MagicOnion.Serialization.IMagicOnionSerializerProvider! serializerProvider, MagicOnion.Client.IMagicOnionClientLogger! logger, System.TimeSpan? clientHeartbeatInterval, System.TimeSpan? clientHeartbeatTimeout, System.Action? onServerHeartbeatReceived, System.Action? onClientHeartbeatResponseReceived, System.TimeProvider? timeProvider) -> void +MagicOnion.Client.StreamingHubClientOptions.TimeProvider.get -> System.TimeProvider? +MagicOnion.Client.StreamingHubClientOptions.WithCallOptions(Grpc.Core.CallOptions callOptions) -> MagicOnion.Client.StreamingHubClientOptions! +MagicOnion.Client.StreamingHubClientOptions.WithClientHeartbeatInterval(System.TimeSpan? interval) -> MagicOnion.Client.StreamingHubClientOptions! +MagicOnion.Client.StreamingHubClientOptions.WithClientHeartbeatResponseReceived(System.Action? onClientHeartbeatResponseReceived) -> MagicOnion.Client.StreamingHubClientOptions! +MagicOnion.Client.StreamingHubClientOptions.WithClientHeartbeatTimeout(System.TimeSpan? timeout) -> MagicOnion.Client.StreamingHubClientOptions! +MagicOnion.Client.StreamingHubClientOptions.WithHost(string? host) -> MagicOnion.Client.StreamingHubClientOptions! +MagicOnion.Client.StreamingHubClientOptions.WithLogger(MagicOnion.Client.IMagicOnionClientLogger! logger) -> MagicOnion.Client.StreamingHubClientOptions! +MagicOnion.Client.StreamingHubClientOptions.WithSerializerProvider(MagicOnion.Serialization.IMagicOnionSerializerProvider! serializerProvider) -> MagicOnion.Client.StreamingHubClientOptions! +MagicOnion.Client.StreamingHubClientOptions.WithServerHeartbeatReceived(System.Action? onServerHeartbeatReceived) -> MagicOnion.Client.StreamingHubClientOptions! +MagicOnion.Client.StreamingHubClientOptions.WithTimeProvider(System.TimeProvider! timeProvider) -> MagicOnion.Client.StreamingHubClientOptions! override MagicOnion.Client.Internal.RawMethodInvoker.InvokeClientStreaming(MagicOnion.Client.MagicOnionClientBase! client, string! path) -> System.Threading.Tasks.Task>! override MagicOnion.Client.Internal.RawMethodInvoker.InvokeDuplexStreaming(MagicOnion.Client.MagicOnionClientBase! client, string! path) -> System.Threading.Tasks.Task>! override MagicOnion.Client.Internal.RawMethodInvoker.InvokeServerStreaming(MagicOnion.Client.MagicOnionClientBase! client, string! path, TRequest request) -> System.Threading.Tasks.Task>! override MagicOnion.Client.Internal.RawMethodInvoker.InvokeUnary(MagicOnion.Client.MagicOnionClientBase! client, string! path, TRequest request) -> MagicOnion.UnaryResult override MagicOnion.Client.Internal.RawMethodInvoker.InvokeUnaryNonGeneric(MagicOnion.Client.MagicOnionClientBase! client, string! path, TRequest request) -> MagicOnion.UnaryResult override MagicOnion.Client.RequestContext.RequestType.get -> System.Type! +readonly MagicOnion.Client.StreamingHubClientBase.receiver -> TReceiver static MagicOnion.Client.DynamicClient.DynamicMagicOnionClientFactoryProvider.Instance.get -> MagicOnion.Client.IMagicOnionClientFactoryProvider! static MagicOnion.Client.DynamicClient.DynamicNotSupportedMagicOnionClientFactoryProvider.Instance.get -> MagicOnion.Client.IMagicOnionClientFactoryProvider! static MagicOnion.Client.DynamicClient.DynamicNotSupportedStreamingHubClientFactoryProvider.Instance.get -> MagicOnion.Client.IStreamingHubClientFactoryProvider! @@ -137,14 +173,17 @@ static MagicOnion.Client.MagicOnionClient.Create(Grpc.Core.ChannelBase! chann static MagicOnion.Client.MagicOnionClient.Create(Grpc.Core.ChannelBase! channel, MagicOnion.Serialization.IMagicOnionSerializerProvider! serializerProvider) -> T static MagicOnion.Client.MagicOnionClient.Create(Grpc.Core.ChannelBase! channel, MagicOnion.Serialization.IMagicOnionSerializerProvider! serializerProvider, MagicOnion.Client.IClientFilter![]! clientFilters) -> T static MagicOnion.Client.MagicOnionClient.Create(Grpc.Core.ChannelBase! channel, MagicOnion.Serialization.IMagicOnionSerializerProvider! serializerProvider, MagicOnion.Client.IClientFilter![]! clientFilters, MagicOnion.Client.IMagicOnionClientFactoryProvider! clientFactoryProvider) -> T -static MagicOnion.Client.MagicOnionClient.Create(MagicOnion.Client.MagicOnionClientOptions clientOptions, MagicOnion.Serialization.IMagicOnionSerializerProvider! serializerProvider) -> T -static MagicOnion.Client.MagicOnionClient.Create(MagicOnion.Client.MagicOnionClientOptions clientOptions, MagicOnion.Serialization.IMagicOnionSerializerProvider! serializerProvider, MagicOnion.Client.IMagicOnionClientFactoryProvider! clientFactoryProvider) -> T +static MagicOnion.Client.MagicOnionClient.Create(MagicOnion.Client.MagicOnionClientOptions! clientOptions, MagicOnion.Serialization.IMagicOnionSerializerProvider! serializerProvider) -> T +static MagicOnion.Client.MagicOnionClient.Create(MagicOnion.Client.MagicOnionClientOptions! clientOptions, MagicOnion.Serialization.IMagicOnionSerializerProvider! serializerProvider, MagicOnion.Client.IMagicOnionClientFactoryProvider! clientFactoryProvider) -> T static MagicOnion.Client.MagicOnionClientFactoryProvider.Default.get -> MagicOnion.Client.IMagicOnionClientFactoryProvider! static MagicOnion.Client.MagicOnionClientFactoryProvider.Default.set -> void static MagicOnion.Client.ResponseContext.Create(T value, Grpc.Core.Status status, Grpc.Core.Metadata! responseHeaders, Grpc.Core.Metadata! trailers) -> MagicOnion.Client.ResponseContext! static MagicOnion.Client.ResponseContext.Create(Grpc.Core.AsyncUnaryCall! inner, System.Func! fromRawResponseToResponse) -> MagicOnion.Client.ResponseContext! static MagicOnion.Client.StreamingHubClient.ConnectAsync(Grpc.Core.CallInvoker! callInvoker, TReceiver receiver, string? host = null, Grpc.Core.CallOptions option = default(Grpc.Core.CallOptions), MagicOnion.Serialization.IMagicOnionSerializerProvider? serializerProvider = null, MagicOnion.Client.IStreamingHubClientFactoryProvider? factoryProvider = null, MagicOnion.Client.IMagicOnionClientLogger? logger = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! static MagicOnion.Client.StreamingHubClient.ConnectAsync(Grpc.Core.ChannelBase! channel, TReceiver receiver, string? host = null, Grpc.Core.CallOptions option = default(Grpc.Core.CallOptions), MagicOnion.Serialization.IMagicOnionSerializerProvider? serializerProvider = null, MagicOnion.Client.IStreamingHubClientFactoryProvider? factoryProvider = null, MagicOnion.Client.IMagicOnionClientLogger? logger = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static MagicOnion.Client.StreamingHubClient.ConnectAsync(Grpc.Core.CallInvoker! callInvoker, TReceiver receiver, MagicOnion.Client.StreamingHubClientOptions! options, MagicOnion.Client.IStreamingHubClientFactoryProvider? factoryProvider = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static MagicOnion.Client.StreamingHubClient.ConnectAsync(Grpc.Core.ChannelBase! channel, TReceiver receiver, MagicOnion.Client.StreamingHubClientOptions! options, MagicOnion.Client.IStreamingHubClientFactoryProvider? factoryProvider = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +static MagicOnion.Client.StreamingHubClientOptions.CreateWithDefault(string? host = null, Grpc.Core.CallOptions callOptions = default(Grpc.Core.CallOptions), MagicOnion.Serialization.IMagicOnionSerializerProvider? serializerProvider = null, MagicOnion.Client.IMagicOnionClientLogger? logger = null) -> MagicOnion.Client.StreamingHubClientOptions! static MagicOnion.Client.StreamingHubClientFactoryProvider.Default.get -> MagicOnion.Client.IStreamingHubClientFactoryProvider! static MagicOnion.Client.StreamingHubClientFactoryProvider.Default.set -> void virtual MagicOnion.Client.MagicOnionClientBase.WithCancellationToken(System.Threading.CancellationToken cancellationToken) -> T diff --git a/src/MagicOnion.Client/PublicAPI.Unshipped.txt b/src/MagicOnion.Client/PublicAPI.Unshipped.txt index dd581604b..eb21bcd6b 100644 --- a/src/MagicOnion.Client/PublicAPI.Unshipped.txt +++ b/src/MagicOnion.Client/PublicAPI.Unshipped.txt @@ -1,4 +1,9 @@ #nullable enable +MagicOnion.Client.IStreamingHubDiagnosticHandler +MagicOnion.Client.IStreamingHubDiagnosticHandler.InvokeMethodDelegate +MagicOnion.Client.IStreamingHubDiagnosticHandler.OnBroadcastEventRaw(THub hubInstance, int methodId, System.ReadOnlyMemory data) -> void +MagicOnion.Client.IStreamingHubDiagnosticHandler.OnBroadcastEvent(THub hubInstance, string! methodName, T value) -> void +MagicOnion.Client.IStreamingHubDiagnosticHandler.OnMethodInvoke(THub hubInstance, int methodId, string! methodName, TRequest request, bool isFireAndForget, MagicOnion.Client.IStreamingHubDiagnosticHandler.InvokeMethodDelegate! invokeMethod) -> System.Threading.Tasks.ValueTask +MagicOnion.Client.IStreamingHubDiagnosticHandler.OnResponseEvent(THub hubInstance, string! methodName, System.ReadOnlyMemory data) -> void static MagicOnion.Client.StreamingHubClient.Connect(Grpc.Core.CallInvoker! callInvoker, TReceiver receiver, string? host = null, Grpc.Core.CallOptions option = default(Grpc.Core.CallOptions), MagicOnion.Serialization.IMagicOnionSerializerProvider? serializerProvider = null, MagicOnion.Client.IStreamingHubClientFactoryProvider? factoryProvider = null, MagicOnion.Client.IMagicOnionClientLogger? logger = null) -> TStreamingHub static MagicOnion.Client.StreamingHubClient.Connect(Grpc.Core.ChannelBase! channel, TReceiver receiver, string? host = null, Grpc.Core.CallOptions option = default(Grpc.Core.CallOptions), MagicOnion.Serialization.IMagicOnionSerializerProvider? serializerProvider = null, MagicOnion.Client.IStreamingHubClientFactoryProvider? factoryProvider = null, MagicOnion.Client.IMagicOnionClientLogger? logger = null) -> TStreamingHub -MagicOnion.Client.StreamingHubClientBase.__ConnectAndSubscribeAsync(TReceiver receiver, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! diff --git a/src/MagicOnion.Client/StreamingHubClientBase.cs b/src/MagicOnion.Client/StreamingHubClientBase.cs index cf18930c8..c88defaa9 100644 --- a/src/MagicOnion.Client/StreamingHubClientBase.cs +++ b/src/MagicOnion.Client/StreamingHubClientBase.cs @@ -24,12 +24,12 @@ public class StreamingHubClientOptions public TimeSpan? ClientHeartbeatTimeout { get; } public Action? OnServerHeartbeatReceived { get; } public Action? OnClientHeartbeatResponseReceived { get; } -#if NET8_0_OR_GREATER +#if NON_UNITY public TimeProvider? TimeProvider { get; } #endif public StreamingHubClientOptions(string? host, CallOptions callOptions, IMagicOnionSerializerProvider serializerProvider, IMagicOnionClientLogger logger) -#if NET8_0_OR_GREATER +#if NON_UNITY : this(host, callOptions, serializerProvider, logger, default, default, default, default, default) #else : this(host, callOptions, serializerProvider, logger, default, default, default, default) @@ -37,7 +37,7 @@ public StreamingHubClientOptions(string? host, CallOptions callOptions, IMagicOn { } -#if NET8_0_OR_GREATER +#if NON_UNITY public StreamingHubClientOptions(string? host, CallOptions callOptions, IMagicOnionSerializerProvider serializerProvider, IMagicOnionClientLogger logger, TimeSpan? clientHeartbeatInterval, TimeSpan? clientHeartbeatTimeout, Action? onServerHeartbeatReceived, Action? onClientHeartbeatResponseReceived,TimeProvider? timeProvider) #else public StreamingHubClientOptions(string? host, CallOptions callOptions, IMagicOnionSerializerProvider serializerProvider, IMagicOnionClientLogger logger, TimeSpan? clientHeartbeatInterval, TimeSpan? clientHeartbeatTimeout, Action? onServerHeartbeatReceived, Action? onClientHeartbeatResponseReceived) @@ -51,7 +51,7 @@ public StreamingHubClientOptions(string? host, CallOptions callOptions, IMagicOn ClientHeartbeatTimeout = clientHeartbeatTimeout; OnServerHeartbeatReceived = onServerHeartbeatReceived; OnClientHeartbeatResponseReceived = onClientHeartbeatResponseReceived; -#if NET8_0_OR_GREATER +#if NON_UNITY TimeProvider = timeProvider; #endif } @@ -62,14 +62,14 @@ public static StreamingHubClientOptions CreateWithDefault(string? host = default public StreamingHubClientOptions WithHost(string? host) => new(host, CallOptions, SerializerProvider, Logger , ClientHeartbeatInterval, ClientHeartbeatTimeout, OnServerHeartbeatReceived, OnClientHeartbeatResponseReceived -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider #endif ); public StreamingHubClientOptions WithCallOptions(CallOptions callOptions) => new(Host, callOptions, SerializerProvider, Logger , ClientHeartbeatInterval, ClientHeartbeatTimeout, OnServerHeartbeatReceived, OnClientHeartbeatResponseReceived -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider #endif ); @@ -77,14 +77,14 @@ public StreamingHubClientOptions WithSerializerProvider(IMagicOnionSerializerPro => new( Host, CallOptions, serializerProvider, Logger , ClientHeartbeatInterval, ClientHeartbeatTimeout, OnServerHeartbeatReceived, OnClientHeartbeatResponseReceived -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider #endif ); public StreamingHubClientOptions WithLogger(IMagicOnionClientLogger logger) => new(Host, CallOptions, SerializerProvider, logger , ClientHeartbeatInterval, ClientHeartbeatTimeout, OnServerHeartbeatReceived, OnClientHeartbeatResponseReceived -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider #endif ); @@ -97,7 +97,7 @@ public StreamingHubClientOptions WithLogger(IMagicOnionClientLogger logger) public StreamingHubClientOptions WithClientHeartbeatInterval(TimeSpan? interval) => new(Host, CallOptions, SerializerProvider, Logger , interval, ClientHeartbeatTimeout, OnServerHeartbeatReceived, OnClientHeartbeatResponseReceived -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider #endif ); @@ -110,7 +110,7 @@ public StreamingHubClientOptions WithClientHeartbeatInterval(TimeSpan? interval) public StreamingHubClientOptions WithClientHeartbeatTimeout(TimeSpan? timeout) => new(Host, CallOptions, SerializerProvider, Logger , ClientHeartbeatInterval, timeout, OnServerHeartbeatReceived, OnClientHeartbeatResponseReceived -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider #endif ); @@ -123,7 +123,7 @@ public StreamingHubClientOptions WithClientHeartbeatTimeout(TimeSpan? timeout) public StreamingHubClientOptions WithServerHeartbeatReceived(Action? onServerHeartbeatReceived) => new(Host, CallOptions, SerializerProvider, Logger , ClientHeartbeatInterval, ClientHeartbeatTimeout, onServerHeartbeatReceived, OnClientHeartbeatResponseReceived -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider #endif ); @@ -136,12 +136,12 @@ public StreamingHubClientOptions WithServerHeartbeatReceived(Action? onClientHeartbeatResponseReceived) => new(Host, CallOptions, SerializerProvider, Logger , ClientHeartbeatInterval, ClientHeartbeatTimeout, OnServerHeartbeatReceived, onClientHeartbeatResponseReceived -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider #endif ); -#if NET8_0_OR_GREATER +#if NON_UNITY /// /// Sets a /// @@ -199,7 +199,7 @@ protected StreamingHubClientBase(string serviceName, TReceiver receiver, CallInv } // call immediately after create. - public async Task __ConnectAndSubscribeAsync(CancellationToken cancellationToken) + internal async Task __ConnectAndSubscribeAsync(CancellationToken cancellationToken) { var syncContext = SynchronizationContext.Current; // capture SynchronizationContext. var callResult = callInvoker.AsyncDuplexStreamingCall(duplexStreamingConnectMethod, options.Host, options.CallOptions); @@ -279,7 +279,7 @@ async Task StartSubscribe(SynchronizationContext? syncContext, Task firstM options.OnClientHeartbeatResponseReceived, syncContext, cancellationTokenSource.Token -#if NET8_0_OR_GREATER +#if NON_UNITY , options.TimeProvider ?? TimeProvider.System #endif ); diff --git a/src/MagicOnion.Client/StreamingHubClientHeartbeatManager.cs b/src/MagicOnion.Client/StreamingHubClientHeartbeatManager.cs index 809e0531f..1da3965c8 100644 --- a/src/MagicOnion.Client/StreamingHubClientHeartbeatManager.cs +++ b/src/MagicOnion.Client/StreamingHubClientHeartbeatManager.cs @@ -57,7 +57,7 @@ internal class StreamingHubClientHeartbeatManager : IDisposable readonly Action? onClientHeartbeatResponseReceived; readonly SynchronizationContext? synchronizationContext; readonly ChannelWriter writer; -#if NET8_0_OR_GREATER +#if NON_UNITY readonly TimeProvider timeProvider; #endif @@ -77,7 +77,7 @@ public StreamingHubClientHeartbeatManager( Action? onClientHeartbeatResponseReceived, SynchronizationContext? synchronizationContext, CancellationToken shutdownToken -#if NET8_0_OR_GREATER +#if NON_UNITY , TimeProvider timeProvider #endif ) @@ -94,7 +94,7 @@ CancellationToken shutdownToken this.onClientHeartbeatResponseReceived = onClientHeartbeatResponseReceived; this.synchronizationContext = synchronizationContext; this.shutdownTokenSource = CancellationTokenSource.CreateLinkedTokenSource(shutdownToken, timeoutTokenSource.Token); -#if NET8_0_OR_GREATER +#if NON_UNITY this.timeProvider = timeProvider; #endif } @@ -177,7 +177,7 @@ SendOrPostCallback ProcessClientHeartbeatResponseCore(Action - { - readonly MemoryPool memoryPool; - IMemoryOwner? buffer; - int written; - - [ThreadStatic] - static MemoryPoolBufferWriter? shared; - public static MemoryPoolBufferWriter RentThreadStaticWriter() => shared ??= new MemoryPoolBufferWriter(MemoryPool.Shared); - - public MemoryPoolBufferWriter(MemoryPool memoryPool) - { - this.memoryPool = memoryPool; - this.buffer = null; - this.written = 0; - } - - public void Advance(int count) - { - written += count; - } - - public Memory GetMemory(int sizeHint = 0) - { - if (buffer != null && (buffer.Memory.Length - written) > sizeHint) - { - return buffer.Memory.Slice(written); - } - else - { - if (buffer == null) - { - // New - buffer = memoryPool.Rent(sizeHint > 0 ? sizeHint : 32767); - } - else - { - // Grow - var oldBuffer = buffer; - var newBuffer = memoryPool.Rent(buffer.Memory.Length * 2); - - oldBuffer.Memory.Slice(0, written).CopyTo(newBuffer.Memory); - oldBuffer.Dispose(); - - buffer = newBuffer; - } - return buffer.Memory.Slice(written); - } - } - - public Span GetSpan(int sizeHint = 0) - { - return GetMemory(sizeHint).Span; - } - - public (IMemoryOwner Owner, int Written) ToMemoryOwnerAndReturn() - { - var result = (buffer ?? memoryPool.Rent(0), written); - written = 0; - buffer = null; - return result; - } - } -} diff --git a/tests/MagicOnion.Integration.Tests/HandCraftedStreamingHubClientTest.cs b/tests/MagicOnion.Integration.Tests/HandCraftedStreamingHubClientTest.cs index 1f883ead2..f87b18483 100644 --- a/tests/MagicOnion.Integration.Tests/HandCraftedStreamingHubClientTest.cs +++ b/tests/MagicOnion.Integration.Tests/HandCraftedStreamingHubClientTest.cs @@ -24,10 +24,10 @@ public async Task MethodParameterless() // Arrange var channel = GrpcChannel.ForAddress("http://localhost", new GrpcChannelOptions() { HttpClient = factory.CreateDefaultClient() }); var receiver = new Receiver(); - var client = new __HandCraftedClient__IHandCraftedStreamingHubClientTestHub(receiver, channel.CreateCallInvoker(), string.Empty, new CallOptions(), MagicOnionSerializerProvider.Default, NullMagicOnionClientLogger.Instance); + var clientConnectTask = StreamingHubClient.ConnectAsync(channel.CreateCallInvoker(), receiver, StreamingHubClientOptions.CreateWithDefault(), factoryProvider: HandCraftedClientFactoryProvider.Instance); // Act - await client.ConnectAsync(); + var client = await clientConnectTask; var retVal = await client.MethodParameterless(); // Assert @@ -40,10 +40,10 @@ public async Task Callback() // Arrange var channel = GrpcChannel.ForAddress("http://localhost", new GrpcChannelOptions() { HttpClient = factory.CreateDefaultClient() }); var receiver = new Receiver(); - var client = new __HandCraftedClient__IHandCraftedStreamingHubClientTestHub(receiver, channel.CreateCallInvoker(), string.Empty, new CallOptions(), MagicOnionSerializerProvider.Default, NullMagicOnionClientLogger.Instance); + var clientConnectTask = StreamingHubClient.ConnectAsync(channel.CreateCallInvoker(), receiver, StreamingHubClientOptions.CreateWithDefault(), factoryProvider: HandCraftedClientFactoryProvider.Instance); // Act - await client.ConnectAsync(); + var client = await clientConnectTask; var retVal = await client.Callback(1234, "FooBarBaz"); await Task.Delay(500); // Wait for the broadcast queue to be consumed. @@ -61,18 +61,25 @@ public void OnMessage(int arg0, string arg1) } } - class __HandCraftedClient__IHandCraftedStreamingHubClientTestHub : StreamingHubClientBase, IHandCraftedStreamingHubClientTestHub + class HandCraftedClientFactoryProvider : IStreamingHubClientFactoryProvider { - public __HandCraftedClient__IHandCraftedStreamingHubClientTestHub(IHandCraftedStreamingHubClientTestHubReceiver receiver, CallInvoker callInvoker, string host, CallOptions option, IMagicOnionSerializerProvider messageSerializer, IMagicOnionClientLogger logger) - : base(nameof(IHandCraftedStreamingHubClientTestHub), receiver, callInvoker, new StreamingHubClientOptions(host, option, messageSerializer, logger)) + public static IStreamingHubClientFactoryProvider Instance { get; } = new HandCraftedClientFactoryProvider(); + + public bool TryGetFactory(out StreamingHubClientFactoryDelegate factory) where TStreamingHub : IStreamingHub { + factory = (receiver, invoker, options) => (TStreamingHub)(object)new __HandCraftedClient__IHandCraftedStreamingHubClientTestHub((IHandCraftedStreamingHubClientTestHubReceiver)(object)receiver!, invoker, options); + return true; } + } - public Task ConnectAsync() + class __HandCraftedClient__IHandCraftedStreamingHubClientTestHub : StreamingHubClientBase, IHandCraftedStreamingHubClientTestHub + { + public __HandCraftedClient__IHandCraftedStreamingHubClientTestHub(IHandCraftedStreamingHubClientTestHubReceiver receiver, CallInvoker callInvoker, StreamingHubClientOptions options) + : base(nameof(IHandCraftedStreamingHubClientTestHub), receiver, callInvoker, options) { - return __ConnectAndSubscribeAsync(CancellationToken.None); } + protected override void OnResponseEvent(int methodId, object taskCompletionSource, ReadOnlyMemory data) { if (FNV1A32.GetHashCode(nameof(MethodParameterless)) == methodId)