Skip to content

Commit e8181ae

Browse files
Pass options to HubConnectionContext (#11382)
1 parent c987ce5 commit e8181ae

11 files changed

+141
-52
lines changed

src/SignalR/common/testassets/Tests.Utils/HubConnectionContextUtils.cs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ static class HubConnectionContextUtils
2020
{
2121
public static HubConnectionContext Create(ConnectionContext connection, IHubProtocol protocol = null, string userIdentifier = null)
2222
{
23-
return new HubConnectionContext(connection, TimeSpan.FromSeconds(15), NullLoggerFactory.Instance)
23+
var contextOptions = new HubConnectionContextOptions()
24+
{
25+
KeepAliveInterval = TimeSpan.FromSeconds(15),
26+
};
27+
28+
return new HubConnectionContext(connection, contextOptions, NullLoggerFactory.Instance)
2429
{
2530
Protocol = protocol ?? new JsonHubProtocol(),
2631
UserIdentifier = userIdentifier,
@@ -29,15 +34,20 @@ public static HubConnectionContext Create(ConnectionContext connection, IHubProt
2934

3035
public static MockHubConnectionContext CreateMock(ConnectionContext connection)
3136
{
32-
return new MockHubConnectionContext(connection, TimeSpan.FromSeconds(15), NullLoggerFactory.Instance, TimeSpan.FromSeconds(15), streamBufferCapacity: 10);
37+
var contextOptions = new HubConnectionContextOptions()
38+
{
39+
KeepAliveInterval = TimeSpan.FromSeconds(15),
40+
ClientTimeoutInterval = TimeSpan.FromSeconds(15),
41+
StreamBufferCapacity = 10,
42+
};
43+
return new MockHubConnectionContext(connection, contextOptions, NullLoggerFactory.Instance);
3344
}
3445

3546
public class MockHubConnectionContext : HubConnectionContext
3647
{
37-
public MockHubConnectionContext(ConnectionContext connectionContext, TimeSpan keepAliveInterval, ILoggerFactory loggerFactory, TimeSpan clientTimeoutInterval, int streamBufferCapacity)
38-
: base(connectionContext, keepAliveInterval, loggerFactory, clientTimeoutInterval, streamBufferCapacity)
48+
public MockHubConnectionContext(ConnectionContext connectionContext, HubConnectionContextOptions contextOptions, ILoggerFactory loggerFactory)
49+
: base(connectionContext, contextOptions, loggerFactory)
3950
{
40-
4151
}
4252

4353
public override ValueTask WriteAsync(HubMessage message, CancellationToken cancellationToken = default)

src/SignalR/perf/Microbenchmarks/BroadcastBenchmark.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ public void GlobalSetup()
4646
{
4747
var pair = DuplexPipe.CreateConnectionPair(options, options);
4848
var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Application, pair.Transport);
49-
var hubConnection = new HubConnectionContext(connection, Timeout.InfiniteTimeSpan, NullLoggerFactory.Instance);
49+
var contextOptions = new HubConnectionContextOptions()
50+
{
51+
KeepAliveInterval = Timeout.InfiniteTimeSpan,
52+
};
53+
var hubConnection = new HubConnectionContext(connection, contextOptions, NullLoggerFactory.Instance);
5054
hubConnection.Protocol = protocol;
5155
_hubLifetimeManager.OnConnectedAsync(hubConnection).GetAwaiter().GetResult();
5256
_hubLifetimeManager.AddToGroupAsync(connection.ConnectionId, TestGroupName).GetAwaiter().GetResult();

src/SignalR/perf/Microbenchmarks/DefaultHubDispatcherBenchmark.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
using System;
55
using System.Buffers;
66
using System.Collections.Generic;
7-
using System.IO;
87
using System.IO.Pipelines;
9-
using System.Reactive.Linq;
108
using System.Threading;
119
using System.Threading.Channels;
1210
using System.Threading.Tasks;
@@ -46,7 +44,11 @@ public void GlobalSetup()
4644
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
4745
var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), pair.Application, pair.Transport);
4846

49-
_connectionContext = new NoErrorHubConnectionContext(connection, TimeSpan.Zero, NullLoggerFactory.Instance);
47+
var contextOptions = new HubConnectionContextOptions()
48+
{
49+
KeepAliveInterval = TimeSpan.Zero,
50+
};
51+
_connectionContext = new NoErrorHubConnectionContext(connection, contextOptions, NullLoggerFactory.Instance);
5052

5153
_connectionContext.Protocol = new FakeHubProtocol();
5254
}
@@ -83,7 +85,8 @@ public class NoErrorHubConnectionContext : HubConnectionContext
8385
{
8486
public TaskCompletionSource<object> ReceivedCompleted = new TaskCompletionSource<object>();
8587

86-
public NoErrorHubConnectionContext(ConnectionContext connectionContext, TimeSpan keepAliveInterval, ILoggerFactory loggerFactory) : base(connectionContext, keepAliveInterval, loggerFactory)
88+
public NoErrorHubConnectionContext(ConnectionContext connectionContext, HubConnectionContextOptions contextOptions, ILoggerFactory loggerFactory)
89+
: base(connectionContext, contextOptions, loggerFactory)
8790
{
8891
}
8992

src/SignalR/perf/Microbenchmarks/DefaultHubLifetimeManagerBenchmark.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ public void GlobalSetup()
5151
ConnectionId = connectionId,
5252
Transport = new TestDuplexPipe(ForceAsync)
5353
};
54-
var hubConnectionContext = new HubConnectionContext(connectionContext, TimeSpan.Zero, NullLoggerFactory.Instance);
54+
var contextOptions = new HubConnectionContextOptions()
55+
{
56+
KeepAliveInterval = TimeSpan.Zero,
57+
};
58+
var hubConnectionContext = new HubConnectionContext(connectionContext, contextOptions, NullLoggerFactory.Instance);
5559
hubConnectionContext.UserIdentifier = userIdentifier;
5660
hubConnectionContext.Protocol = jsonHubProtocol;
5761

src/SignalR/perf/Microbenchmarks/HubConnectionContextBenchmark.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
using System.Threading.Tasks;
1010
using BenchmarkDotNet.Attributes;
1111
using Microsoft.AspNetCore.Connections;
12-
using Microsoft.AspNetCore.SignalR.Internal;
1312
using Microsoft.AspNetCore.Internal;
1413
using Microsoft.AspNetCore.SignalR.Protocol;
1514
using Microsoft.AspNetCore.SignalR.Microbenchmarks.Shared;
@@ -44,7 +43,11 @@ public void GlobalSetup()
4443
_pipe = new TestDuplexPipe();
4544

4645
var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), _pipe, _pipe);
47-
_hubConnectionContext = new HubConnectionContext(connection, Timeout.InfiniteTimeSpan, NullLoggerFactory.Instance);
46+
var contextOptions = new HubConnectionContextOptions()
47+
{
48+
KeepAliveInterval = Timeout.InfiniteTimeSpan,
49+
};
50+
_hubConnectionContext = new HubConnectionContext(connection, contextOptions, NullLoggerFactory.Instance);
4851

4952
_successHubProtocolResolver = new TestHubProtocolResolver(new NewtonsoftJsonHubProtocol());
5053
_failureHubProtocolResolver = new TestHubProtocolResolver(null);

src/SignalR/server/Core/ref/Microsoft.AspNetCore.SignalR.Core.netcoreapp3.0.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,7 @@ public static partial class HubClientsExtensions
127127
}
128128
public partial class HubConnectionContext
129129
{
130-
public HubConnectionContext(Microsoft.AspNetCore.Connections.ConnectionContext connectionContext, System.TimeSpan keepAliveInterval, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { }
131-
public HubConnectionContext(Microsoft.AspNetCore.Connections.ConnectionContext connectionContext, System.TimeSpan keepAliveInterval, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, System.TimeSpan clientTimeoutInterval) { }
132-
public HubConnectionContext(Microsoft.AspNetCore.Connections.ConnectionContext connectionContext, System.TimeSpan keepAliveInterval, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, System.TimeSpan clientTimeoutInterval, int streamBufferCapacity) { }
130+
public HubConnectionContext(Microsoft.AspNetCore.Connections.ConnectionContext connectionContext, Microsoft.AspNetCore.SignalR.HubConnectionContextOptions contextOptions, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { }
133131
public virtual System.Threading.CancellationToken ConnectionAborted { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
134132
public virtual string ConnectionId { get { throw null; } }
135133
public virtual Microsoft.AspNetCore.Http.Features.IFeatureCollection Features { get { throw null; } }
@@ -141,6 +139,13 @@ public virtual void Abort() { }
141139
public virtual System.Threading.Tasks.ValueTask WriteAsync(Microsoft.AspNetCore.SignalR.Protocol.HubMessage message, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
142140
public virtual System.Threading.Tasks.ValueTask WriteAsync(Microsoft.AspNetCore.SignalR.SerializedHubMessage message, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
143141
}
142+
public partial class HubConnectionContextOptions
143+
{
144+
public HubConnectionContextOptions() { }
145+
public System.TimeSpan ClientTimeoutInterval { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
146+
public System.TimeSpan KeepAliveInterval { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
147+
public int StreamBufferCapacity { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
148+
}
144149
public partial class HubConnectionHandler<THub> : Microsoft.AspNetCore.Connections.ConnectionHandler where THub : Microsoft.AspNetCore.SignalR.Hub
145150
{
146151
public HubConnectionHandler(Microsoft.AspNetCore.SignalR.HubLifetimeManager<THub> lifetimeManager, Microsoft.AspNetCore.SignalR.IHubProtocolResolver protocolResolver, Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.SignalR.HubOptions> globalHubOptions, Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.SignalR.HubOptions<THub>> hubOptions, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.AspNetCore.SignalR.IUserIdProvider userIdProvider, Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) { }

src/SignalR/server/Core/src/HubConnectionContext.cs

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -48,37 +48,17 @@ public class HubConnectionContext
4848
/// Initializes a new instance of the <see cref="HubConnectionContext"/> class.
4949
/// </summary>
5050
/// <param name="connectionContext">The underlying <see cref="ConnectionContext"/>.</param>
51-
/// <param name="keepAliveInterval">The keep alive interval. If no messages are sent by the server in this interval, a Ping message will be sent.</param>
5251
/// <param name="loggerFactory">The logger factory.</param>
53-
public HubConnectionContext(ConnectionContext connectionContext, TimeSpan keepAliveInterval, ILoggerFactory loggerFactory)
54-
: this(connectionContext, keepAliveInterval, loggerFactory, HubOptionsSetup.DefaultClientTimeoutInterval, HubOptionsSetup.DefaultStreamBufferCapacity) { }
55-
56-
/// <summary>
57-
/// Initializes a new instance of the <see cref="HubConnectionContext"/> class.
58-
/// </summary>
59-
/// <param name="connectionContext">The underlying <see cref="ConnectionContext"/>.</param>
60-
/// <param name="keepAliveInterval">The keep alive interval. If no messages are sent by the server in this interval, a Ping message will be sent.</param>
61-
/// <param name="loggerFactory">The logger factory.</param>
62-
/// <param name="clientTimeoutInterval">Clients we haven't heard from in this interval are assumed to have disconnected.</param>
63-
public HubConnectionContext(ConnectionContext connectionContext, TimeSpan keepAliveInterval, ILoggerFactory loggerFactory, TimeSpan clientTimeoutInterval)
64-
: this(connectionContext, keepAliveInterval, loggerFactory, clientTimeoutInterval, HubOptionsSetup.DefaultStreamBufferCapacity) { }
65-
66-
/// <summary>
67-
/// Initializes a new instance of the <see cref="HubConnectionContext"/> class.
68-
/// </summary>
69-
/// <param name="connectionContext">The underlying <see cref="ConnectionContext"/>.</param>
70-
/// <param name="keepAliveInterval">The keep alive interval. If no messages are sent by the server in this interval, a Ping message will be sent.</param>
71-
/// <param name="loggerFactory">The logger factory.</param>
72-
/// <param name="clientTimeoutInterval">Clients we haven't heard from in this interval are assumed to have disconnected.</param>
73-
/// <param name="streamBufferCapacity">The buffer size for client upload streams</param>
74-
public HubConnectionContext(ConnectionContext connectionContext, TimeSpan keepAliveInterval, ILoggerFactory loggerFactory, TimeSpan clientTimeoutInterval, int streamBufferCapacity)
52+
/// <param name="contextOptions">The options to configure the HubConnectionContext.</param>
53+
public HubConnectionContext(ConnectionContext connectionContext, HubConnectionContextOptions contextOptions, ILoggerFactory loggerFactory)
7554
{
55+
_keepAliveInterval = contextOptions.KeepAliveInterval.Ticks;
56+
_clientTimeoutInterval = contextOptions.ClientTimeoutInterval.Ticks;
57+
_streamBufferCapacity = contextOptions.StreamBufferCapacity;
58+
7659
_connectionContext = connectionContext;
7760
_logger = loggerFactory.CreateLogger<HubConnectionContext>();
7861
ConnectionAborted = _connectionAbortedTokenSource.Token;
79-
_keepAliveInterval = keepAliveInterval.Ticks;
80-
_clientTimeoutInterval = clientTimeoutInterval.Ticks;
81-
_streamBufferCapacity = streamBufferCapacity;
8262
}
8363

8464
internal StreamTracker StreamTracker
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
6+
namespace Microsoft.AspNetCore.SignalR
7+
{
8+
/// <summary>
9+
/// Options used to configure <see cref="HubConnectionContext"/>.
10+
/// </summary>
11+
public class HubConnectionContextOptions
12+
{
13+
/// <summary>
14+
/// Gets or sets the interval used to send keep alive pings to connected clients.
15+
/// </summary>
16+
public TimeSpan KeepAliveInterval { get; set; }
17+
18+
/// <summary>
19+
/// Gets or sets the time window clients have to send a message before the server closes the connection.
20+
/// </summary>
21+
public TimeSpan ClientTimeoutInterval { get; set; }
22+
23+
/// <summary>
24+
/// Gets or sets the max buffer size for client upload streams.
25+
/// </summary>
26+
public int StreamBufferCapacity { get; set; }
27+
}
28+
}

src/SignalR/server/Core/src/HubConnectionHandler.cs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
using Microsoft.AspNetCore.SignalR.Protocol;
1212
using Microsoft.Extensions.DependencyInjection;
1313
using Microsoft.Extensions.Logging;
14-
using Microsoft.Extensions.Logging.Abstractions;
1514
using Microsoft.Extensions.Options;
1615

1716
namespace Microsoft.AspNetCore.SignalR
@@ -75,21 +74,26 @@ IServiceScopeFactory serviceScopeFactory
7574
public override async Task OnConnectedAsync(ConnectionContext connection)
7675
{
7776
// We check to see if HubOptions<THub> are set because those take precedence over global hub options.
78-
// Then set the keepAlive and handshakeTimeout values to the defaults in HubOptionsSetup incase they were explicitly set to null.
79-
var keepAlive = _hubOptions.KeepAliveInterval ?? _globalHubOptions.KeepAliveInterval ?? HubOptionsSetup.DefaultKeepAliveInterval;
80-
var clientTimeout = _hubOptions.ClientTimeoutInterval ?? _globalHubOptions.ClientTimeoutInterval ?? HubOptionsSetup.DefaultClientTimeoutInterval;
81-
var handshakeTimeout = _hubOptions.HandshakeTimeout ?? _globalHubOptions.HandshakeTimeout ?? HubOptionsSetup.DefaultHandshakeTimeout;
82-
var streamBufferCapacity = _hubOptions.StreamBufferCapacity ?? _globalHubOptions.StreamBufferCapacity ?? HubOptionsSetup.DefaultStreamBufferCapacity;
83-
var supportedProtocols = _hubOptions.SupportedProtocols ?? _globalHubOptions.SupportedProtocols;
77+
// Then set the keepAlive and handshakeTimeout values to the defaults in HubOptionsSetup when they were explicitly set to null.
8478

85-
if (supportedProtocols != null && supportedProtocols.Count == 0)
79+
var supportedProtocols = _hubOptions.SupportedProtocols ?? _globalHubOptions.SupportedProtocols;
80+
if (supportedProtocols == null || supportedProtocols.Count == 0)
8681
{
8782
throw new InvalidOperationException("There are no supported protocols");
8883
}
8984

85+
var handshakeTimeout = _hubOptions.HandshakeTimeout ?? _globalHubOptions.HandshakeTimeout ?? HubOptionsSetup.DefaultHandshakeTimeout;
86+
87+
var contextOptions = new HubConnectionContextOptions()
88+
{
89+
KeepAliveInterval = _hubOptions.KeepAliveInterval ?? _globalHubOptions.KeepAliveInterval ?? HubOptionsSetup.DefaultKeepAliveInterval,
90+
ClientTimeoutInterval = _hubOptions.ClientTimeoutInterval ?? _globalHubOptions.ClientTimeoutInterval ?? HubOptionsSetup.DefaultClientTimeoutInterval,
91+
StreamBufferCapacity = _hubOptions.StreamBufferCapacity ?? _globalHubOptions.StreamBufferCapacity ?? HubOptionsSetup.DefaultStreamBufferCapacity,
92+
};
93+
9094
Log.ConnectedStarting(_logger);
9195

92-
var connectionContext = new HubConnectionContext(connection, keepAlive, _loggerFactory, clientTimeout, streamBufferCapacity);
96+
var connectionContext = new HubConnectionContext(connection, contextOptions, _loggerFactory);
9397

9498
var resolvedSupportedProtocols = (supportedProtocols as IReadOnlyList<string>) ?? supportedProtocols.ToList();
9599
if (!await connectionContext.HandshakeAsync(handshakeTimeout, resolvedSupportedProtocols, _protocolResolver, _userIdProvider, _enableDetailedErrors))

src/SignalR/server/Core/src/HubOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class HubOptions
1717
// for all available protocols.
1818

1919
/// <summary>
20-
/// Gets or sets the interval used by the server to timeout incoming handshake requests by clients. The default timeout is 15 seconds
20+
/// Gets or sets the interval used by the server to timeout incoming handshake requests by clients. The default timeout is 15 seconds.
2121
/// </summary>
2222
public TimeSpan? HandshakeTimeout { get; set; } = null;
2323

0 commit comments

Comments
 (0)