Skip to content

Commit 16ef7d1

Browse files
authored
Cache subscriptions dict locally (#225)
Removes reflection overhead in hot patch
1 parent 55314fa commit 16ef7d1

1 file changed

Lines changed: 8 additions & 9 deletions

File tree

‎Common/OpenShockRedisHubLifetimeManager.cs‎

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ namespace OpenShock.Common;
1414
/// <typeparam name="THub"></typeparam>
1515
public sealed class OpenShockRedisHubLifetimeManager<THub> : RedisHubLifetimeManager<THub> where THub : Hub
1616
{
17-
private readonly FieldInfo _usersField;
18-
private readonly FieldInfo _subscriptionsField;
17+
private readonly ConcurrentDictionary<string, HubConnectionStore> _subscriptions;
1918
private readonly string _redisPrefix = typeof(THub).FullName!;
2019

2120
/// <summary>
@@ -32,8 +31,12 @@ public OpenShockRedisHubLifetimeManager(ILogger<OpenShockRedisHubLifetimeManager
3231
IOptions<HubOptions<THub>>? hubOptions) : base(logger, options, hubProtocolResolver, globalHubOptions,
3332
hubOptions)
3433
{
35-
_usersField = typeof(RedisHubLifetimeManager<THub>).GetField("_users", BindingFlags.NonPublic | BindingFlags.Instance)!;
36-
_subscriptionsField = _usersField.FieldType.GetField("_subscriptions", BindingFlags.NonPublic | BindingFlags.Instance)!;
34+
var usersField = typeof(RedisHubLifetimeManager<THub>).GetField("_users", BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new NullReferenceException("Unable to get RedisHubLifetimeManager._users field");
35+
var subscriptionsField = usersField.FieldType.GetField("_subscriptions", BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new NullReferenceException("Unable to get RedisHubLifetimeManager._users._subscriptions field");
36+
var users = usersField.GetValue(this) ?? throw new NullReferenceException("Unable to get RedisHubLifetimeManager._users value");
37+
var subscriptions = subscriptionsField.GetValue(users) ?? throw new NullReferenceException("Unable to get RedisHubLifetimeManager._users._subscriptions value");
38+
39+
_subscriptions = (ConcurrentDictionary<string, HubConnectionStore>)subscriptions;
3740
}
3841

3942
/// <inheritdoc />
@@ -92,11 +95,7 @@ public override Task SendUserAsync(string userId, string methodName, object?[] a
9295
private Task SendLocalUserAsync(string userId, SerializedHubMessage message,
9396
CancellationToken cancellationToken)
9497
{
95-
var users = _usersField.GetValue(this)!;
96-
var subsObj =
97-
(ConcurrentDictionary<string, HubConnectionStore>)_subscriptionsField.GetValue(users)!;
98-
99-
if (!subsObj.TryGetValue($"{_redisPrefix}:user:{userId[6..]}", out var store)) return Task.CompletedTask;
98+
if (!_subscriptions.TryGetValue($"{_redisPrefix}:user:{userId[6..]}", out var store)) return Task.CompletedTask;
10099

101100
var tasks = new List<Task>(store.Count);
102101
foreach (var context in store) tasks.Add(context.WriteAsync(message, cancellationToken).AsTask());

0 commit comments

Comments
 (0)