Skip to content

Commit 51d12df

Browse files
committed
update libs and fix tests + IHostApplicationLifetime
1 parent b0f2d1f commit 51d12df

8 files changed

Lines changed: 92 additions & 90 deletions

File tree

Directory.Build.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
<RepositoryUrl>https://github.com/managedcode/Orleans.SignalR</RepositoryUrl>
1818
<PackageProjectUrl>https://github.com/managedcode/Orleans.SignalR</PackageProjectUrl>
1919
<Product>Managed Code - Orleans SignalR</Product>
20-
<Version>8.1.0</Version>
21-
<PackageVersion>8.1.0</PackageVersion>
20+
<Version>8.1.1</Version>
21+
<PackageVersion>8.1.1</PackageVersion>
2222

2323
</PropertyGroup>
2424
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">

ManagedCode.Orleans.SignalR.Core/SignalR/OrleansHubLifetimeManager.cs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using ManagedCode.Orleans.SignalR.Core.SignalR.Observers;
1414
using Microsoft.AspNetCore.SignalR;
1515
using Microsoft.AspNetCore.SignalR.Protocol;
16+
using Microsoft.Extensions.Hosting;
1617
using Microsoft.Extensions.Logging;
1718
using Microsoft.Extensions.Options;
1819
using Orleans;
@@ -29,14 +30,16 @@ public class OrleansHubLifetimeManager<THub> : HubLifetimeManager<THub> where TH
2930
private readonly IOptions<OrleansSignalROptions> _orleansSignalOptions;
3031

3132
public OrleansHubLifetimeManager(ILogger<OrleansHubLifetimeManager<THub>> logger, IClusterClient clusterClient,
32-
IHubProtocolResolver hubProtocolResolver, IOptions<OrleansSignalROptions> orleansSignalOptions,
33+
IHostApplicationLifetime hostLifetime, IOptions<OrleansSignalROptions> orleansSignalOptions,
3334
IOptions<HubOptions> globalHubOptions, IOptions<HubOptions<THub>> hubOptions)
3435
{
3536
_logger = logger;
3637
_orleansSignalOptions = orleansSignalOptions;
3738
_globalHubOptions = globalHubOptions;
3839
_hubOptions = hubOptions;
3940
_clusterClient = clusterClient;
41+
42+
hostLifetime.ApplicationStopping.Register(OnApplicationStopping);
4043
}
4144

4245
public override async Task OnConnectedAsync(HubConnectionContext connection)
@@ -49,7 +52,6 @@ public override async Task OnConnectedAsync(HubConnectionContext connection)
4952
var connectionHolderGrain = NameHelperGenerator.GetConnectionHolderGrain<THub>(_clusterClient);
5053
subscription.AddGrain(connectionHolderGrain);
5154
await Task.Run(() => connectionHolderGrain.AddConnection(connection.ConnectionId, subscription.Reference));
52-
5355
}
5456

5557
if (!string.IsNullOrEmpty(connection.UserIdentifier))
@@ -269,8 +271,7 @@ public override bool TryGetReturnType(string invocationId, [NotNullWhen(true)] o
269271
{
270272
var returnType = NameHelperGenerator.GetInvocationGrain<THub>(_clusterClient, invocationId).TryGetReturnType();
271273

272-
var timeSpan =
273-
TimeIntervalHelper.GetClientTimeoutInterval(_orleansSignalOptions, _globalHubOptions, _hubOptions);
274+
var timeSpan = TimeIntervalHelper.GetClientTimeoutInterval(_orleansSignalOptions, _globalHubOptions, _hubOptions);
274275
Task.WaitAny(returnType, Task.Delay(timeSpan * 0.8));
275276

276277
if (returnType.IsCompleted)
@@ -346,4 +347,22 @@ private static string GenerateInvocationId()
346347
var connection = _connections[connectionId];
347348
return connection?.Features.Get<Subscription>();
348349
}
350+
351+
private void OnApplicationStopping()
352+
{
353+
var tasks = new List<Task>(_connections.Count);
354+
355+
foreach (var connection in _connections)
356+
{
357+
var subscription = connection.Features.Get<Subscription>();
358+
359+
if (subscription is null)
360+
return;
361+
362+
foreach (var grain in subscription.Grains)
363+
tasks.Add(grain.RemoveConnection(connection.ConnectionId, subscription.Reference));
364+
}
365+
366+
_ = Task.Run(() => Task.WhenAll(tasks));
367+
}
349368
}

ManagedCode.Orleans.SignalR.Tests/HubTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -582,9 +582,9 @@ public async Task UsersDeliveryTimeoutMessagesTest()
582582
var token2 = await (await _secondApp.CreateHttpClient().GetAsync("/auth?user=TestUser2-t")).Content.ReadAsStringAsync();
583583

584584
var hubConnection1 = _firstApp.CreateSignalRClient(nameof(InterfaceTestHub),
585-
configureConnection: options => { options.AccessTokenProvider = () => Task.FromResult(token1); });
585+
configureConnection: options => { options.AccessTokenProvider = () => Task.FromResult(token1)!; });
586586
var hubConnection2 = _secondApp.CreateSignalRClient(nameof(InterfaceTestHub),
587-
configureConnection: options => { options.AccessTokenProvider = () => Task.FromResult(token2); });
587+
configureConnection: options => { options.AccessTokenProvider = () => Task.FromResult(token2)!; });
588588

589589

590590
hubConnection1.On("SendMessage", (string m) => { messages1 = m; });

ManagedCode.Orleans.SignalR.Tests/ManagedCode.Orleans.SignalR.Tests.csproj

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212

1313
<ItemGroup>
1414
<PackageReference Include="FluentAssertions" Version="6.12.0" />
15-
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.4" />
16-
<PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="8.0.4" />
17-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
15+
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.6" />
16+
<PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="8.0.6" />
17+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
1818
<PackageReference Include="Microsoft.Orleans.Analyzers" Version="8.1.0">
1919
<PrivateAssets>all</PrivateAssets>
2020
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
@@ -23,12 +23,12 @@
2323
<PackageReference Include="Microsoft.Orleans.Server" Version="8.1.0" />
2424
<PackageReference Include="Microsoft.Orleans.TestingHost" Version="8.1.0" />
2525
<PackageReference Include="System.Linq.Async" Version="6.0.1"/>
26-
<PackageReference Include="xunit" Version="2.8.0" />
27-
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.0">
26+
<PackageReference Include="xunit" Version="2.8.1" />
27+
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.1">
2828
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2929
<PrivateAssets>all</PrivateAssets>
3030
</PackageReference>
31-
<PackageReference Include="xunit.runner.console" Version="2.8.0">
31+
<PackageReference Include="xunit.runner.console" Version="2.8.1">
3232
<PrivateAssets>all</PrivateAssets>
3333
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
3434
</PackageReference>
@@ -40,9 +40,9 @@
4040
<PrivateAssets>all</PrivateAssets>
4141
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
4242
</PackageReference>
43-
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.4" />
44-
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.4" />
45-
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="8.0.4" />
43+
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.6" />
44+
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.6" />
45+
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="8.0.6" />
4646
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
4747
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" />
4848
<PackageReference Include="Microsoft.Orleans.Sdk" Version="8.1.0" />

ManagedCode.Orleans.SignalR.Tests/StressTests.cs

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -178,24 +178,6 @@ public async Task InvokeAsyncAndOnTest()
178178
signalRUserGrainCount.Count.Should().BeGreaterOrEqualTo(1);
179179
_outputHelper.WriteLine($"ConnectionHolder:{signalRConnectionHolderGrainCount.Count};GroupGrain:{signalRGroupGrainCount.Count}; InvocationGrain:{signalRInvocationGrainCount.Count}; UserGrain:{signalRUserGrainCount.Count};");
180180

181-
182-
for (int i = 1; i <= 5; i++)
183-
{
184-
_outputHelper.WriteLine($"wait {i} minute");
185-
await Task.Delay(TimeSpan.FromMinutes(1));
186-
187-
signalRConnectionHolderGrainCount = await _siloCluster.Cluster.Client.GetGrain<IManagementGrain>(0).GetActiveGrains(GrainType.Create($"ManagedCode.{nameof(SignalRConnectionHolderGrain)}"));
188-
signalRGroupGrainCount = await _siloCluster.Cluster.Client.GetGrain<IManagementGrain>(0).GetActiveGrains(GrainType.Create($"ManagedCode.{nameof(SignalRGroupGrain)}"));
189-
signalRInvocationGrainCount = await _siloCluster.Cluster.Client.GetGrain<IManagementGrain>(0).GetActiveGrains(GrainType.Create($"ManagedCode.{nameof(SignalRInvocationGrain)}"));
190-
signalRUserGrainCount = await _siloCluster.Cluster.Client.GetGrain<IManagementGrain>(0).GetActiveGrains(GrainType.Create($"ManagedCode.{nameof(SignalRUserGrain)}"));
191-
192-
_outputHelper.WriteLine($"ConnectionHolder:{signalRConnectionHolderGrainCount.Count};GroupGrain:{signalRGroupGrainCount.Count}; InvocationGrain:{signalRInvocationGrainCount.Count}; UserGrain:{signalRUserGrainCount.Count};");
193-
194-
signalRConnectionHolderGrainCount.Count.Should().BeGreaterOrEqualTo(1);
195-
signalRGroupGrainCount.Count.Should().BeGreaterOrEqualTo(1);
196-
signalRInvocationGrainCount.Count.Should().Be(0);
197-
signalRUserGrainCount.Count.Should().BeGreaterOrEqualTo(1);
198-
}
199181

200182
_outputHelper.WriteLine($"Invoke one more time. Connection is {hubConnection.State}");
201183
var rnd = await hubConnection.InvokeAsync<int>("DoTest");
@@ -208,23 +190,20 @@ public async Task InvokeAsyncAndOnTest()
208190
hubConnection.State.Should().Be(HubConnectionState.Disconnected);
209191
await hubConnection.DisposeAsync();
210192
_outputHelper.WriteLine("Connection is stopped.");
193+
_outputHelper.WriteLine($"wait a minute");
194+
await Task.Delay(TimeSpan.FromMinutes(1));
195+
196+
signalRConnectionHolderGrainCount = await _siloCluster.Cluster.Client.GetGrain<IManagementGrain>(0).GetActiveGrains(GrainType.Create($"ManagedCode.{nameof(SignalRConnectionHolderGrain)}"));
197+
signalRGroupGrainCount = await _siloCluster.Cluster.Client.GetGrain<IManagementGrain>(0).GetActiveGrains(GrainType.Create($"ManagedCode.{nameof(SignalRGroupGrain)}"));
198+
signalRInvocationGrainCount = await _siloCluster.Cluster.Client.GetGrain<IManagementGrain>(0).GetActiveGrains(GrainType.Create($"ManagedCode.{nameof(SignalRInvocationGrain)}"));
199+
signalRUserGrainCount = await _siloCluster.Cluster.Client.GetGrain<IManagementGrain>(0).GetActiveGrains(GrainType.Create($"ManagedCode.{nameof(SignalRUserGrain)}"));
211200

212-
for (int i = 1; i <= 5; i++)
213-
{
214-
_outputHelper.WriteLine($"wait {i} minute");
215-
await Task.Delay(TimeSpan.FromMinutes(1));
216-
217-
signalRConnectionHolderGrainCount = await _siloCluster.Cluster.Client.GetGrain<IManagementGrain>(0).GetActiveGrains(GrainType.Create($"ManagedCode.{nameof(SignalRConnectionHolderGrain)}"));
218-
signalRGroupGrainCount = await _siloCluster.Cluster.Client.GetGrain<IManagementGrain>(0).GetActiveGrains(GrainType.Create($"ManagedCode.{nameof(SignalRGroupGrain)}"));
219-
signalRInvocationGrainCount = await _siloCluster.Cluster.Client.GetGrain<IManagementGrain>(0).GetActiveGrains(GrainType.Create($"ManagedCode.{nameof(SignalRInvocationGrain)}"));
220-
signalRUserGrainCount = await _siloCluster.Cluster.Client.GetGrain<IManagementGrain>(0).GetActiveGrains(GrainType.Create($"ManagedCode.{nameof(SignalRUserGrain)}"));
221-
222-
_outputHelper.WriteLine($"ConnectionHolder:{signalRConnectionHolderGrainCount.Count};GroupGrain:{signalRGroupGrainCount.Count}; InvocationGrain:{signalRInvocationGrainCount.Count}; UserGrain:{signalRUserGrainCount.Count};");
201+
_outputHelper.WriteLine($"ConnectionHolder:{signalRConnectionHolderGrainCount.Count};GroupGrain:{signalRGroupGrainCount.Count}; InvocationGrain:{signalRInvocationGrainCount.Count}; UserGrain:{signalRUserGrainCount.Count};");
223202

224-
}
203+
225204
_outputHelper.WriteLine($"check...");
226205

227-
await _siloCluster.Cluster.Client.GetGrain<IManagementGrain>(0).ForceActivationCollection(TimeSpan.FromMinutes(4));
206+
await _siloCluster.Cluster.Client.GetGrain<IManagementGrain>(0).ForceActivationCollection(TimeSpan.FromSeconds(10));
228207

229208
signalRConnectionHolderGrainCount = await _siloCluster.Cluster.Client.GetGrain<IManagementGrain>(0).GetActiveGrains(GrainType.Create($"ManagedCode.{nameof(SignalRConnectionHolderGrain)}"));
230209
signalRGroupGrainCount = await _siloCluster.Cluster.Client.GetGrain<IManagementGrain>(0).GetActiveGrains(GrainType.Create($"ManagedCode.{nameof(SignalRGroupGrain)}"));

ManagedCode.Orleans.SignalR.Tests/TestApp/Controllers/AuthController.cs

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,46 +10,34 @@ namespace ManagedCode.Orleans.SignalR.Tests.TestApp.Controllers;
1010
[Route("/[controller]")]
1111
[ApiController]
1212
[AllowAnonymous]
13-
public class AuthController : ControllerBase
13+
public class AuthController(JwtSecurityTokenHandler tokenHandler) : ControllerBase
1414
{
1515
[HttpGet]
16-
public async Task<ActionResult<string>> OkAction([FromQuery] string user = null)
16+
public async Task<ActionResult<string>> OkAction([FromQuery] string? user = null)
1717
{
18-
// create a secret key for signing the token
19-
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your_secret_key_here"));
20-
21-
// create the signing credentials using the secret key
22-
var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
23-
2418
if (string.IsNullOrEmpty(user))
25-
user = Guid.NewGuid().ToString();
19+
user = Guid.NewGuid().ToString("N");
2620

27-
// create a list of claims for the token
28-
var claims = new[]
21+
var claims = new ClaimsIdentity(new[]
2922
{
3023
new Claim(ClaimTypes.Name, user),
3124
new Claim(ClaimTypes.Email, user),
3225
new Claim(ClaimTypes.NameIdentifier, user)
33-
};
34-
35-
// create the token descriptor with the claims, expiration time, and signing credentials
26+
});
27+
28+
29+
SignIn(new ClaimsPrincipal(claims));
30+
3631
var tokenDescriptor = new SecurityTokenDescriptor
3732
{
38-
Subject = new ClaimsIdentity(claims),
39-
Expires = DateTime.UtcNow.AddHours(1),
40-
SigningCredentials = signingCredentials
33+
Subject = claims,
34+
Expires = DateTime.UtcNow.AddDays(7),
35+
Issuer = "YourIssuer",
36+
Audience = "YourAudience",
37+
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(HttpHostProgram.GetEncryptionKey()), SecurityAlgorithms.HmacSha256Signature)
4138
};
42-
43-
// create the JWT token handler
44-
var tokenHandler = new JwtSecurityTokenHandler();
45-
46-
// create the JWT token
47-
var token = tokenHandler.CreateJwtSecurityToken(tokenDescriptor);
48-
49-
// write the token as a string
50-
var jwtToken = tokenHandler.WriteToken(token);
51-
52-
// return the token to the client
53-
return Ok(jwtToken);
39+
var token = tokenHandler.CreateToken(tokenDescriptor);
40+
41+
return tokenHandler.WriteToken(token);
5442
}
5543
}

ManagedCode.Orleans.SignalR.Tests/TestApp/HttpHostProgram.cs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System.Diagnostics;
2+
using System.IdentityModel.Tokens.Jwt;
13
using System.Text;
24
using ManagedCode.Orleans.SignalR.Client.Extensions;
35
using ManagedCode.Orleans.SignalR.Tests.TestApp.Hubs;
@@ -12,35 +14,43 @@ namespace ManagedCode.Orleans.SignalR.Tests.TestApp;
1214

1315
public class HttpHostProgram
1416
{
17+
public static byte[] GetEncryptionKey()
18+
{
19+
return Encoding.ASCII.GetBytes("your_secret_key_here_your_secret_key_here");
20+
}
21+
1522
public static void Main(string[] args)
1623
{
1724
var builder = WebApplication.CreateBuilder(args);
1825
builder.Services.AddControllers();
1926

2027

2128
if (builder.Environment.IsProduction())
22-
builder.Services.AddSignalR().AddOrleans();
29+
builder.Services.AddSignalR()
30+
.AddOrleans();
2331
else
2432
builder.Services.AddSignalR(); //.AddStackExchangeRedis();
25-
33+
34+
35+
builder.Services.AddSingleton<JwtSecurityTokenHandler>();
36+
builder.Services.AddAuthentication(options =>
37+
{
38+
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
39+
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
40+
});
41+
2642
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
2743
{
2844
options.RequireHttpsMetadata = false;
2945
options.SaveToken = true;
3046
options.TokenValidationParameters = new TokenValidationParameters
3147
{
3248
ValidateIssuerSigningKey = true,
33-
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your_secret_key_here")),
34-
ValidateIssuer = false,
35-
ValidateAudience = false
36-
};
37-
options.Events = new JwtBearerEvents
38-
{
39-
OnMessageReceived = context =>
40-
{
41-
context.Token = context.Request.Query["access_token"];
42-
return Task.CompletedTask;
43-
}
49+
ValidateIssuer = true,
50+
ValidateAudience = true,
51+
ValidIssuer = "YourIssuer",
52+
ValidAudience = "YourAudience",
53+
IssuerSigningKey = new SymmetricSecurityKey(GetEncryptionKey())
4454
};
4555
});
4656

ManagedCode.Orleans.SignalR.Tests/TestApp/Hubs/InterfaceTestHub.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ namespace ManagedCode.Orleans.SignalR.Tests.TestApp.Hubs;
44

55
public class InterfaceTestHub : Hub<IClientInterfaceHub>, IServerInterfaceHub
66
{
7+
public override Task OnConnectedAsync()
8+
{
9+
var user = Context.User;
10+
return base.OnConnectedAsync();
11+
}
12+
713
public Task PushRandom()
814
{
915
return Clients.All.SendRandom(new Random().Next());

0 commit comments

Comments
 (0)