From 85ff3ee9d4d2d712530891aa4a4517665bb94b5a Mon Sep 17 00:00:00 2001 From: Brennan Conroy Date: Fri, 11 Aug 2023 17:09:24 -0700 Subject: [PATCH] Stateful Reconnect API changes --- .../csharp/Client.Core/src/HubConnection.cs | 2 +- .../src/HubConnectionBuilderHttpExtensions.cs | 12 ++++++++++++ .../csharp/Client/src/PublicAPI.Unshipped.txt | 1 + .../test/FunctionalTests/HubConnectionTests.cs | 16 +++++++--------- .../Client/test/FunctionalTests/Startup.cs | 2 +- .../test/UnitTests/HttpConnectionFactoryTests.cs | 2 +- .../src/HttpConnection.cs | 6 +++--- .../src/HttpConnectionFactory.cs | 2 +- .../src/HttpConnectionOptions.cs | 5 ++--- .../src/Internal/WebSocketsTransport.cs | 8 ++++---- .../src/PublicAPI.Unshipped.txt | 4 ++-- .../src/NegotiateProtocol.cs | 4 ++-- .../src/NegotiationResponse.cs | 2 +- .../src/PublicAPI.Unshipped.txt | 4 ++-- .../src/HttpConnectionDispatcherOptions.cs | 7 ++++--- .../src/Internal/HttpConnectionContext.cs | 8 ++++---- .../src/Internal/HttpConnectionDispatcher.cs | 6 +++--- .../Http.Connections/src/PublicAPI.Unshipped.txt | 4 ++-- .../test/HttpConnectionDispatcherTests.cs | 6 +++--- .../DefaultHubDispatcherBenchmark.cs | 1 - .../server/Core/src/HubConnectionContext.cs | 16 ++++++++-------- .../server/Core/src/HubConnectionHandler.cs | 2 -- .../Core/src/Internal/DefaultHubDispatcher.cs | 4 +--- 23 files changed, 65 insertions(+), 59 deletions(-) diff --git a/src/SignalR/clients/csharp/Client.Core/src/HubConnection.cs b/src/SignalR/clients/csharp/Client.Core/src/HubConnection.cs index 904a44b92ee0..fde6daf7337c 100644 --- a/src/SignalR/clients/csharp/Client.Core/src/HubConnection.cs +++ b/src/SignalR/clients/csharp/Client.Core/src/HubConnection.cs @@ -1904,7 +1904,7 @@ public ConnectionState(ConnectionContext connection, HubConnection hubConnection { _messageBuffer = new MessageBuffer(connection, hubConnection._protocol, _hubConnection._serviceProvider.GetService>()?.Value.StatefulReconnectBufferSize - ?? DefaultStatefulReconnectBufferSize); + ?? DefaultStatefulReconnectBufferSize); feature.NotifyOnReconnect = _messageBuffer.Resend; } diff --git a/src/SignalR/clients/csharp/Client/src/HubConnectionBuilderHttpExtensions.cs b/src/SignalR/clients/csharp/Client/src/HubConnectionBuilderHttpExtensions.cs index eda739d1776e..149df632c9ca 100644 --- a/src/SignalR/clients/csharp/Client/src/HubConnectionBuilderHttpExtensions.cs +++ b/src/SignalR/clients/csharp/Client/src/HubConnectionBuilderHttpExtensions.cs @@ -19,6 +19,18 @@ namespace Microsoft.AspNetCore.SignalR.Client; /// public static class HubConnectionBuilderHttpExtensions { + /// + /// Configures the to negotiate stateful reconnect with the server. + /// + /// The to configure. + /// The same instance of the for chaining. + public static IHubConnectionBuilder WithStatefulReconnect(this IHubConnectionBuilder hubConnectionBuilder) + { + hubConnectionBuilder.Services.Configure(options => options.UseStatefulReconnect = true); + + return hubConnectionBuilder; + } + /// /// Configures the to use HTTP-based transports to connect to the specified URL. /// diff --git a/src/SignalR/clients/csharp/Client/src/PublicAPI.Unshipped.txt b/src/SignalR/clients/csharp/Client/src/PublicAPI.Unshipped.txt index 7dc5c58110bf..01b2b1dae01e 100644 --- a/src/SignalR/clients/csharp/Client/src/PublicAPI.Unshipped.txt +++ b/src/SignalR/clients/csharp/Client/src/PublicAPI.Unshipped.txt @@ -1 +1,2 @@ #nullable enable +static Microsoft.AspNetCore.SignalR.Client.HubConnectionBuilderHttpExtensions.WithStatefulReconnect(this Microsoft.AspNetCore.SignalR.Client.IHubConnectionBuilder! hubConnectionBuilder) -> Microsoft.AspNetCore.SignalR.Client.IHubConnectionBuilder! diff --git a/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs b/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs index d8ae692ea8e3..89eed500de2b 100644 --- a/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs +++ b/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs @@ -2560,7 +2560,7 @@ public async Task CanReconnectAndSendMessageWhileDisconnected() tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); return websocket; }; - o.UseAcks = true; + o.UseStatefulReconnect = true; }); connectionBuilder.Services.AddSingleton(protocol); var connection = connectionBuilder.Build(); @@ -2617,7 +2617,7 @@ public async Task CanReconnectAndSendMessageOnceConnected() tcs.SetResult(); return websocket; }; - o.UseAcks = true; + o.UseStatefulReconnect = true; }) .WithAutomaticReconnect(); connectionBuilder.Services.AddSingleton(protocol); @@ -2691,8 +2691,8 @@ public async Task ChangingUserNameDuringReconnectLogsWarning() tcs.SetResult(); return websocket; }; - o.UseAcks = true; }) + .WithStatefulReconnect() .WithAutomaticReconnect(); connectionBuilder.Services.AddSingleton(protocol); var connection = connectionBuilder.Build(); @@ -2756,7 +2756,7 @@ public async Task ServerAbortsConnectionWithAckingEnabledNoReconnectAttempted() await ws.ConnectAsync(context.Uri, token); return ws; }; - o.UseAcks = true; + o.UseStatefulReconnect = true; }); connectionBuilder.Services.AddSingleton(protocol); var connection = connectionBuilder.Build(); @@ -2799,12 +2799,10 @@ public async Task CanSetMessageBufferSizeOnClient() const string originalMessage = "SignalR"; var connectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) - .WithUrl(server.Url + "/default", HttpTransportType.WebSockets, o => - { - o.UseAcks = true; - }); - connectionBuilder.Services.Configure(o => o.StatefulReconnectBufferSize = 500); + .WithStatefulReconnect() + .WithUrl(server.Url + "/default", HttpTransportType.WebSockets); connectionBuilder.Services.AddSingleton(protocol); + connectionBuilder.Services.Configure(o => o.StatefulReconnectBufferSize = 500); var connection = connectionBuilder.Build(); try diff --git a/src/SignalR/clients/csharp/Client/test/FunctionalTests/Startup.cs b/src/SignalR/clients/csharp/Client/test/FunctionalTests/Startup.cs index afc0e25c05dd..ec443c0d1724 100644 --- a/src/SignalR/clients/csharp/Client/test/FunctionalTests/Startup.cs +++ b/src/SignalR/clients/csharp/Client/test/FunctionalTests/Startup.cs @@ -93,7 +93,7 @@ public void Configure(IApplicationBuilder app) app.UseEndpoints(endpoints => { - endpoints.MapHub("/default", o => o.AllowAcks = true); + endpoints.MapHub("/default", o => o.AllowStatefulReconnects = true); endpoints.MapHub("/dynamic"); endpoints.MapHub("/hubT"); endpoints.MapHub("/authorizedhub"); diff --git a/src/SignalR/clients/csharp/Client/test/UnitTests/HttpConnectionFactoryTests.cs b/src/SignalR/clients/csharp/Client/test/UnitTests/HttpConnectionFactoryTests.cs index f019ec2a749b..c9457a8f36e9 100644 --- a/src/SignalR/clients/csharp/Client/test/UnitTests/HttpConnectionFactoryTests.cs +++ b/src/SignalR/clients/csharp/Client/test/UnitTests/HttpConnectionFactoryTests.cs @@ -100,7 +100,7 @@ public void ShallowCopyHttpConnectionOptionsCopiesAllPublicProperties() { $"{nameof(HttpConnectionOptions.WebSocketFactory)}", webSocketFactory }, { $"{nameof(HttpConnectionOptions.ApplicationMaxBufferSize)}", 1L * 1024 * 1024 }, { $"{nameof(HttpConnectionOptions.TransportMaxBufferSize)}", 1L * 1024 * 1024 }, - { $"{nameof(HttpConnectionOptions.UseAcks)}", true }, + { $"{nameof(HttpConnectionOptions.UseStatefulReconnect)}", true }, }; var options = new HttpConnectionOptions(); diff --git a/src/SignalR/clients/csharp/Http.Connections.Client/src/HttpConnection.cs b/src/SignalR/clients/csharp/Http.Connections.Client/src/HttpConnection.cs index 22c250f865f7..a538244bf915 100644 --- a/src/SignalR/clients/csharp/Http.Connections.Client/src/HttpConnection.cs +++ b/src/SignalR/clients/csharp/Http.Connections.Client/src/HttpConnection.cs @@ -399,13 +399,13 @@ private async Task SelectAndStartTransport(TransferFormat transferFormat, Cancel if (negotiationResponse == null) { // Temporary until other transports work - _httpConnectionOptions.UseAcks = transportType == HttpTransportType.WebSockets ? _httpConnectionOptions.UseAcks : false; + _httpConnectionOptions.UseStatefulReconnect = transportType == HttpTransportType.WebSockets ? _httpConnectionOptions.UseStatefulReconnect : false; negotiationResponse = await GetNegotiationResponseAsync(uri, cancellationToken).ConfigureAwait(false); connectUrl = CreateConnectUrl(uri, negotiationResponse.ConnectionToken); } Log.StartingTransport(_logger, transportType, uri); - await StartTransport(connectUrl, transportType, transferFormat, cancellationToken, negotiationResponse.UseAcking).ConfigureAwait(false); + await StartTransport(connectUrl, transportType, transferFormat, cancellationToken, negotiationResponse.UseStatefulReconnect).ConfigureAwait(false); break; } } @@ -457,7 +457,7 @@ private async Task NegotiateAsync(Uri url, HttpClient httpC uri = Utils.AppendQueryString(urlBuilder.Uri, $"negotiateVersion={_protocolVersionNumber}"); } - if (_httpConnectionOptions.UseAcks) + if (_httpConnectionOptions.UseStatefulReconnect) { uri = Utils.AppendQueryString(uri, "useAck=true"); } diff --git a/src/SignalR/clients/csharp/Http.Connections.Client/src/HttpConnectionFactory.cs b/src/SignalR/clients/csharp/Http.Connections.Client/src/HttpConnectionFactory.cs index b5f2b035e071..18868adb6850 100644 --- a/src/SignalR/clients/csharp/Http.Connections.Client/src/HttpConnectionFactory.cs +++ b/src/SignalR/clients/csharp/Http.Connections.Client/src/HttpConnectionFactory.cs @@ -89,7 +89,7 @@ internal static HttpConnectionOptions ShallowCopyHttpConnectionOptions(HttpConne DefaultTransferFormat = options.DefaultTransferFormat, ApplicationMaxBufferSize = options.ApplicationMaxBufferSize, TransportMaxBufferSize = options.TransportMaxBufferSize, - UseAcks = options.UseAcks, + UseStatefulReconnect = options.UseStatefulReconnect, }; if (!OperatingSystem.IsBrowser()) diff --git a/src/SignalR/clients/csharp/Http.Connections.Client/src/HttpConnectionOptions.cs b/src/SignalR/clients/csharp/Http.Connections.Client/src/HttpConnectionOptions.cs index c7a2ae78ed07..5b645e649cef 100644 --- a/src/SignalR/clients/csharp/Http.Connections.Client/src/HttpConnectionOptions.cs +++ b/src/SignalR/clients/csharp/Http.Connections.Client/src/HttpConnectionOptions.cs @@ -276,14 +276,13 @@ public Action? WebSocketConfiguration } /// - /// Setting to enable acking bytes sent between client and server, this allows reconnecting that preserves messages sent while disconnected. + /// Setting to enable Stateful Reconnect between client and server, this allows reconnecting that preserves messages sent while disconnected. /// Also preserves the when the reconnect is successful. /// /// /// Only works with WebSockets transport currently. - /// API likely to change in future previews. /// - public bool UseAcks { get; set; } + public bool UseStatefulReconnect { get; set; } private static void ThrowIfUnsupportedPlatform() { diff --git a/src/SignalR/clients/csharp/Http.Connections.Client/src/Internal/WebSocketsTransport.cs b/src/SignalR/clients/csharp/Http.Connections.Client/src/Internal/WebSocketsTransport.cs index 93b37d87f669..ab99b214c93b 100644 --- a/src/SignalR/clients/csharp/Http.Connections.Client/src/Internal/WebSocketsTransport.cs +++ b/src/SignalR/clients/csharp/Http.Connections.Client/src/Internal/WebSocketsTransport.cs @@ -36,7 +36,7 @@ internal sealed partial class WebSocketsTransport : ITransport, IReconnectFeatur private readonly HttpConnectionOptions _httpConnectionOptions; private readonly HttpClient? _httpClient; private CancellationTokenSource _stopCts = default!; - private readonly bool _useAck; + private readonly bool _useStatefulReconnect; private IDuplexPipe? _transport; // Used for reconnect (when enabled) to determine if the close was ungraceful or not, reconnect only happens on ungraceful disconnect @@ -53,9 +53,9 @@ internal sealed partial class WebSocketsTransport : ITransport, IReconnectFeatur public Action NotifyOnReconnect { get => _notifyOnReconnect is not null ? _notifyOnReconnect : () => { }; set => _notifyOnReconnect = value; } public WebSocketsTransport(HttpConnectionOptions httpConnectionOptions, ILoggerFactory loggerFactory, Func> accessTokenProvider, HttpClient? httpClient, - bool useAck = false) + bool useStatefulReconnect = false) { - _useAck = useAck; + _useStatefulReconnect = useStatefulReconnect; _logger = (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger(); _httpConnectionOptions = httpConnectionOptions ?? new HttpConnectionOptions(); @@ -368,7 +368,7 @@ private async Task ProcessSocketAsync(WebSocket socket, Uri url, bool ignoreFirs } } - if (_useAck && !_gracefulClose) + if (_useStatefulReconnect && !_gracefulClose) { UpdateConnectionPair(); await StartAsync(url, _webSocketMessageType == WebSocketMessageType.Binary ? TransferFormat.Binary : TransferFormat.Text, default).ConfigureAwait(false); diff --git a/src/SignalR/clients/csharp/Http.Connections.Client/src/PublicAPI.Unshipped.txt b/src/SignalR/clients/csharp/Http.Connections.Client/src/PublicAPI.Unshipped.txt index 80a34974298d..f81b5269348a 100644 --- a/src/SignalR/clients/csharp/Http.Connections.Client/src/PublicAPI.Unshipped.txt +++ b/src/SignalR/clients/csharp/Http.Connections.Client/src/PublicAPI.Unshipped.txt @@ -1,3 +1,3 @@ #nullable enable -Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionOptions.UseAcks.get -> bool -Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionOptions.UseAcks.set -> void +Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionOptions.UseStatefulReconnect.get -> bool +Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionOptions.UseStatefulReconnect.set -> void diff --git a/src/SignalR/common/Http.Connections.Common/src/NegotiateProtocol.cs b/src/SignalR/common/Http.Connections.Common/src/NegotiateProtocol.cs index 8ff9ba259ed1..e9e221a141ca 100644 --- a/src/SignalR/common/Http.Connections.Common/src/NegotiateProtocol.cs +++ b/src/SignalR/common/Http.Connections.Common/src/NegotiateProtocol.cs @@ -66,7 +66,7 @@ public static void WriteResponse(NegotiationResponse response, IBufferWriter content) AvailableTransports = availableTransports, Error = error, Version = version, - UseAcking = useAck, + UseStatefulReconnect = useAck, }; } catch (Exception ex) diff --git a/src/SignalR/common/Http.Connections.Common/src/NegotiationResponse.cs b/src/SignalR/common/Http.Connections.Common/src/NegotiationResponse.cs index 264ce71d1d38..17904c17f524 100644 --- a/src/SignalR/common/Http.Connections.Common/src/NegotiationResponse.cs +++ b/src/SignalR/common/Http.Connections.Common/src/NegotiationResponse.cs @@ -52,5 +52,5 @@ public class NegotiationResponse /// It should also set on the collection so other layers of the /// application (like SignalR) can react. /// - public bool UseAcking { get; set; } + public bool UseStatefulReconnect { get; set; } } diff --git a/src/SignalR/common/Http.Connections.Common/src/PublicAPI.Unshipped.txt b/src/SignalR/common/Http.Connections.Common/src/PublicAPI.Unshipped.txt index 437066a1e801..89713177659f 100644 --- a/src/SignalR/common/Http.Connections.Common/src/PublicAPI.Unshipped.txt +++ b/src/SignalR/common/Http.Connections.Common/src/PublicAPI.Unshipped.txt @@ -1,3 +1,3 @@ #nullable enable -Microsoft.AspNetCore.Http.Connections.NegotiationResponse.UseAcking.get -> bool -Microsoft.AspNetCore.Http.Connections.NegotiationResponse.UseAcking.set -> void +Microsoft.AspNetCore.Http.Connections.NegotiationResponse.UseStatefulReconnect.get -> bool +Microsoft.AspNetCore.Http.Connections.NegotiationResponse.UseStatefulReconnect.set -> void diff --git a/src/SignalR/common/Http.Connections/src/HttpConnectionDispatcherOptions.cs b/src/SignalR/common/Http.Connections/src/HttpConnectionDispatcherOptions.cs index 8c7d3ea0141e..f9da7eb5e304 100644 --- a/src/SignalR/common/Http.Connections/src/HttpConnectionDispatcherOptions.cs +++ b/src/SignalR/common/Http.Connections/src/HttpConnectionDispatcherOptions.cs @@ -4,6 +4,7 @@ using System.IO.Pipelines; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Connections; namespace Microsoft.AspNetCore.Http.Connections; @@ -125,12 +126,12 @@ public TimeSpan TransportSendTimeout public bool CloseOnAuthenticationExpiration { get; set; } /// - /// Set to allow connections to ack messages, helps enable reconnects that keep connection state. + /// Set to allow connections to reconnect with the same . /// /// - /// Keeps messages in memory until acked (up to a limit), and keeps connections around for a short time to allow stateful reconnects. + /// Client still has to negotiate this option. /// - public bool AllowAcks { get; set; } + public bool AllowStatefulReconnects { get; set; } internal long TransportSendTimeoutTicks { get; private set; } internal bool TransportSendTimeoutEnabled => _transportSendTimeout != Timeout.InfiniteTimeSpan; diff --git a/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionContext.cs b/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionContext.cs index 4508e36696d1..d96f2cd4c2cd 100644 --- a/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionContext.cs +++ b/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionContext.cs @@ -49,7 +49,7 @@ internal sealed partial class HttpConnectionContext : ConnectionContext, private CancellationTokenSource? _sendCts; private bool _activeSend; private long _startedSendTime; - private readonly bool _useAcks; + private readonly bool _useStatefulReconnect; private readonly object _sendingLock = new object(); internal CancellationToken SendingToken { get; private set; } @@ -105,10 +105,10 @@ public HttpConnectionContext(string connectionId, string connectionToken, ILogge _connectionCloseRequested = new CancellationTokenSource(); ConnectionClosedRequested = _connectionCloseRequested.Token; AuthenticationExpiration = DateTimeOffset.MaxValue; - _useAcks = useAcks; + _useStatefulReconnect = useAcks; } - public bool UseAcks => _useAcks; + public bool UseStatefulReconnect => _useStatefulReconnect; public CancellationTokenSource? Cancellation { get; set; } @@ -548,7 +548,7 @@ internal async Task CancelPreviousPoll(HttpContext context) cts?.Cancel(); // TODO: remove transport check once other transports support acks - if (UseAcks && TransportType == HttpTransportType.WebSockets) + if (UseStatefulReconnect && TransportType == HttpTransportType.WebSockets) { // Break transport send loop in case it's still waiting on reading from the application Application.Input.CancelPendingRead(); diff --git a/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.cs b/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.cs index fdfa7c59ff46..17b6fdaa3ae6 100644 --- a/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.cs +++ b/src/SignalR/common/Http.Connections/src/Internal/HttpConnectionDispatcher.cs @@ -189,7 +189,7 @@ private async Task ExecuteAsync(HttpContext context, ConnectionDelegate connecti return; } - if (connection.TransportType != HttpTransportType.WebSockets || connection.UseAcks) + if (connection.TransportType != HttpTransportType.WebSockets || connection.UseStatefulReconnect) { if (!await connection.CancelPreviousPoll(context)) { @@ -336,7 +336,7 @@ private async Task ProcessNegotiate(HttpContext context, HttpConnectionDispatche } var useAck = false; - if (options.AllowAcks == true && context.Request.Query.TryGetValue("UseAck", out var useAckValue)) + if (options.AllowStatefulReconnects == true && context.Request.Query.TryGetValue("UseAck", out var useAckValue)) { var useAckStringValue = useAckValue.ToString(); bool.TryParse(useAckStringValue, out useAck); @@ -389,7 +389,7 @@ private static void WriteNegotiatePayload(IBufferWriter writer, string? co response.ConnectionId = connectionId; response.ConnectionToken = connectionToken; response.AvailableTransports = new List(); - response.UseAcking = useAck; + response.UseStatefulReconnect = useAck; if ((options.Transports & HttpTransportType.WebSockets) != 0 && ServerHasWebSockets(context.Features)) { diff --git a/src/SignalR/common/Http.Connections/src/PublicAPI.Unshipped.txt b/src/SignalR/common/Http.Connections/src/PublicAPI.Unshipped.txt index 2c40e757b45c..1e5f0a8e0203 100644 --- a/src/SignalR/common/Http.Connections/src/PublicAPI.Unshipped.txt +++ b/src/SignalR/common/Http.Connections/src/PublicAPI.Unshipped.txt @@ -1,3 +1,3 @@ #nullable enable -Microsoft.AspNetCore.Http.Connections.HttpConnectionDispatcherOptions.AllowAcks.get -> bool -Microsoft.AspNetCore.Http.Connections.HttpConnectionDispatcherOptions.AllowAcks.set -> void +Microsoft.AspNetCore.Http.Connections.HttpConnectionDispatcherOptions.AllowStatefulReconnects.get -> bool +Microsoft.AspNetCore.Http.Connections.HttpConnectionDispatcherOptions.AllowStatefulReconnects.set -> void diff --git a/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs b/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs index 4f1cdbd5c223..4a5c5e253419 100644 --- a/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs +++ b/src/SignalR/common/Http.Connections/test/HttpConnectionDispatcherTests.cs @@ -2279,7 +2279,7 @@ public async Task NegotiateDoesNotReturnUseAckWhenNotEnabledOnServer() context.Request.Method = "POST"; context.Response.Body = ms; context.Request.QueryString = new QueryString("?negotiateVersion=1&UseAck=true"); - await dispatcher.ExecuteNegotiateAsync(context, new HttpConnectionDispatcherOptions { AllowAcks = false }); + await dispatcher.ExecuteNegotiateAsync(context, new HttpConnectionDispatcherOptions { AllowStatefulReconnects = false }); var negotiateResponse = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(ms.ToArray())); Assert.False(negotiateResponse.TryGetValue("useAck", out _)); @@ -2306,7 +2306,7 @@ public async Task NegotiateDoesNotReturnUseAckWhenEnabledOnServerButNotRequested context.Request.Method = "POST"; context.Response.Body = ms; context.Request.QueryString = new QueryString("?negotiateVersion=1"); - await dispatcher.ExecuteNegotiateAsync(context, new HttpConnectionDispatcherOptions { AllowAcks = true }); + await dispatcher.ExecuteNegotiateAsync(context, new HttpConnectionDispatcherOptions { AllowStatefulReconnects = true }); var negotiateResponse = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(ms.ToArray())); Assert.False(negotiateResponse.TryGetValue("useAck", out _)); @@ -2333,7 +2333,7 @@ public async Task NegotiateReturnsUseAckWhenEnabledOnServerAndRequestedByClient( context.Request.Method = "POST"; context.Response.Body = ms; context.Request.QueryString = new QueryString("?negotiateVersion=1&UseAck=true"); - await dispatcher.ExecuteNegotiateAsync(context, new HttpConnectionDispatcherOptions { AllowAcks = true }); + await dispatcher.ExecuteNegotiateAsync(context, new HttpConnectionDispatcherOptions { AllowStatefulReconnects = true }); var negotiateResponse = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(ms.ToArray())); Assert.True((bool)negotiateResponse["useAck"]); diff --git a/src/SignalR/perf/Microbenchmarks/DefaultHubDispatcherBenchmark.cs b/src/SignalR/perf/Microbenchmarks/DefaultHubDispatcherBenchmark.cs index d0efd3d4489c..bdbf8443d752 100644 --- a/src/SignalR/perf/Microbenchmarks/DefaultHubDispatcherBenchmark.cs +++ b/src/SignalR/perf/Microbenchmarks/DefaultHubDispatcherBenchmark.cs @@ -35,7 +35,6 @@ public void GlobalSetup() new HubContext(hubLifetimeManager), enableDetailedErrors: false, disableImplicitFromServiceParameters: true, - useAcks: false, new Logger>(NullLoggerFactory.Instance), hubFilters: null, hubLifetimeManager); diff --git a/src/SignalR/server/Core/src/HubConnectionContext.cs b/src/SignalR/server/Core/src/HubConnectionContext.cs index 5685c5d55060..8bc30779372b 100644 --- a/src/SignalR/server/Core/src/HubConnectionContext.cs +++ b/src/SignalR/server/Core/src/HubConnectionContext.cs @@ -51,10 +51,10 @@ public partial class HubConnectionContext private TimeSpan _receivedMessageElapsed; private long _receivedMessageTick; private ClaimsPrincipal? _user; - private bool _useAcks; + private bool _useStatefulReconnect; [MemberNotNullWhen(true, nameof(_messageBuffer))] - internal bool UsingAcks() => _useAcks; + internal bool UsingStatefulReconnect() => _useStatefulReconnect; /// /// Initializes a new instance of the class. @@ -264,7 +264,7 @@ private ValueTask WriteCore(HubMessage message, CancellationToken c { try { - if (UsingAcks()) + if (UsingStatefulReconnect()) { return _messageBuffer.WriteAsync(new SerializedHubMessage(message), cancellationToken); } @@ -292,7 +292,7 @@ private ValueTask WriteCore(SerializedHubMessage message, Cancellat { try { - if (UsingAcks()) + if (UsingStatefulReconnect()) { Debug.Assert(_messageBuffer is not null); return _messageBuffer.WriteAsync(message, cancellationToken); @@ -578,7 +578,7 @@ await WriteHandshakeResponseAsync(new HandshakeResponseMessage( if (_connectionContext.Features.Get() is IReconnectFeature feature) { - _useAcks = true; + _useStatefulReconnect = true; _messageBuffer = new MessageBuffer(_connectionContext, Protocol, _statefulReconnectBufferSize); feature.NotifyOnReconnect = _messageBuffer.Resend; } @@ -768,7 +768,7 @@ internal void Cleanup() internal void Ack(AckMessage ackMessage) { - if (UsingAcks()) + if (UsingStatefulReconnect()) { _messageBuffer.Ack(ackMessage); } @@ -776,7 +776,7 @@ internal void Ack(AckMessage ackMessage) internal bool ShouldProcessMessage(HubMessage message) { - if (UsingAcks()) + if (UsingStatefulReconnect()) { return _messageBuffer.ShouldProcessMessage(message); } @@ -785,7 +785,7 @@ internal bool ShouldProcessMessage(HubMessage message) internal void ResetSequence(SequenceMessage sequenceMessage) { - if (UsingAcks()) + if (UsingStatefulReconnect()) { _messageBuffer.ResetSequence(sequenceMessage); } diff --git a/src/SignalR/server/Core/src/HubConnectionHandler.cs b/src/SignalR/server/Core/src/HubConnectionHandler.cs index b2cdd8953d77..32df42a00b37 100644 --- a/src/SignalR/server/Core/src/HubConnectionHandler.cs +++ b/src/SignalR/server/Core/src/HubConnectionHandler.cs @@ -97,8 +97,6 @@ IServiceScopeFactory serviceScopeFactory new HubContext(lifetimeManager), _enableDetailedErrors, disableImplicitFromServiceParameters, - // TODO - useAcks: true, new Logger>(loggerFactory), hubFilters, lifetimeManager); diff --git a/src/SignalR/server/Core/src/Internal/DefaultHubDispatcher.cs b/src/SignalR/server/Core/src/Internal/DefaultHubDispatcher.cs index 8facf60e4d9b..874a66c57951 100644 --- a/src/SignalR/server/Core/src/Internal/DefaultHubDispatcher.cs +++ b/src/SignalR/server/Core/src/Internal/DefaultHubDispatcher.cs @@ -28,17 +28,15 @@ internal sealed partial class DefaultHubDispatcher : HubDispatcher w private readonly Func? _onConnectedMiddleware; private readonly Func? _onDisconnectedMiddleware; private readonly HubLifetimeManager _hubLifetimeManager; - private readonly bool _useAcks; public DefaultHubDispatcher(IServiceScopeFactory serviceScopeFactory, IHubContext hubContext, bool enableDetailedErrors, - bool disableImplicitFromServiceParameters, bool useAcks, ILogger> logger, List? hubFilters, HubLifetimeManager lifetimeManager) + bool disableImplicitFromServiceParameters, ILogger> logger, List? hubFilters, HubLifetimeManager lifetimeManager) { _serviceScopeFactory = serviceScopeFactory; _hubContext = hubContext; _enableDetailedErrors = enableDetailedErrors; _logger = logger; _hubLifetimeManager = lifetimeManager; - _useAcks = useAcks; DiscoverHubMethods(disableImplicitFromServiceParameters); var count = hubFilters?.Count ?? 0;