Skip to content

Commit 47eaa1a

Browse files
V7 initial candidate (#144)
* V7 initial candidate * Minor cleanups * Some more minor cleanups --------- Co-authored-by: Gutemberg Ribeiro <[email protected]>
1 parent 9f3ec76 commit 47eaa1a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1323
-1216
lines changed

.github/workflows/ci.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ jobs:
1111
runs-on: ubuntu-latest
1212

1313
steps:
14-
- uses: actions/checkout@v1
14+
- uses: actions/checkout@v3
1515
- name: Setup .NET Core
16-
uses: actions/setup-dotnet@v1
16+
uses: actions/setup-dotnet@v3
1717
with:
18-
dotnet-version: 6.0.x
18+
dotnet-version: 7.x
1919
- name: Build
2020
run: dotnet build --configuration Release
2121
- name: Test

.github/workflows/publish.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ jobs:
1414
runs-on: ubuntu-latest
1515

1616
steps:
17-
- uses: actions/checkout@v1
17+
- uses: actions/checkout@v3
1818
- name: Setup .NET Core
19-
uses: actions/setup-dotnet@v1
19+
uses: actions/setup-dotnet@v3
2020
with:
21-
dotnet-version: 6.0.x
21+
dotnet-version: 7.x
2222
- name: Build
2323
run: dotnet build --configuration Release
2424
- name: Test

Directory.Build.props

+5-17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<Project>
2-
<!-- Set the repository root into a variable -->
2+
<!-- Set the repository root into a variable -->
33
<PropertyGroup>
44
<SourceRoot>$(MSBuildThisFileDirectory)</SourceRoot>
55
</PropertyGroup>
@@ -19,24 +19,12 @@
1919

2020
<!-- Common compile parameters -->
2121
<PropertyGroup>
22+
<TargetFramework>net7.0</TargetFramework>
23+
<ImplicitUsings>enable</ImplicitUsings>
24+
<LangVersion>latest</LangVersion>
25+
<Nullable>enable</Nullable>
2226
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
2327
<NoWarn>$(NoWarn);1701;1702;1705;1591</NoWarn>
24-
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
25-
<LangVersion>latest</LangVersion>
26-
</PropertyGroup>
27-
28-
<PropertyGroup>
29-
<TargetFramework>net6.0</TargetFramework>
30-
</PropertyGroup>
31-
32-
<!-- Shared Package Versions -->
33-
<PropertyGroup>
34-
<!-- vendors -->
35-
<OrleansCoreVersion>3.6.3</OrleansCoreVersion>
36-
<OrleansProvidersVersion>3.6.3</OrleansProvidersVersion>
37-
<OrleansCodeGeneratorVersion>3.6.3</OrleansCodeGeneratorVersion>
38-
<OrleansRuntimeAbstractionsVersion>3.6.3</OrleansRuntimeAbstractionsVersion>
39-
<OrleansRuntimeVersion>3.6.3</OrleansRuntimeVersion>
4028
</PropertyGroup>
4129

4230
<ItemGroup>

README.md

+162-8
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,33 @@
77
[![Package Version](https://img.shields.io/nuget/v/SignalR.Orleans.svg)](https://www.nuget.org/packages/SignalR.Orleans)
88
[![NuGet Downloads](https://img.shields.io/nuget/dt/SignalR.Orleans.svg)](https://www.nuget.org/packages/SignalR.Orleans)
99
[![License](https://img.shields.io/github/license/OrleansContrib/SignalR.Orleans.svg)](https://github.com/OrleansContrib/SignalR.Orleans/blob/master/LICENSE)
10-
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/dotnet/orleans?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
10+
[![Discord](https://img.shields.io/discord/333727978460676096)](https://discord.gg/TCSAgM9k)
1111

12-
[Orleans](https://github.com/dotnet/orleans) is a framework that provides a straight-forward approach to building distributed high-scale computing applications, without the need to learn and apply complex concurrency or other scaling patterns.
12+
[Orleans](https://learn.microsoft.com/en-us/dotnet/orleans/overview) is a cross-platform framework for building robust, scalable distributed applications. Distributed applications are defined as apps that span more than a single process, often beyond hardware boundaries using peer-to-peer communication. Orleans scales from a single on-premises server to hundreds to thousands of distributed, highly available applications in the cloud. [See Orleans source code on Github](https://github.com/dotnet/orleans)
1313

14-
[ASP.NET Core SignalR](https://github.com/aspnet/SignalR) is a new library for ASP.NET Core developers that makes it incredibly simple to add real-time web functionality to your applications. What is "real-time web" functionality? It's the ability to have your server-side code push content to the connected clients as it happens, in real-time.
14+
[ASP.NET Core SignalR](https://learn.microsoft.com/en-us/aspnet/core/signalr/introduction?view=aspnetcore-7.0) is an open-source library that simplifies adding real-time web functionality to apps. Real-time web functionality enables server-side code to push content to clients instantly.
1515

16-
**SignalR.Orleans** is a package that allow us to enhance the _real-time_ capabilities of SignalR by leveraging Orleans distributed cloud platform capabilities.
16+
**SignalR.Orleans** is a package that gives you two abilities:
1717

18+
1. Use your Orleans cluster as a backplane for SignalR. [Learn about scaling out SignalR on multiple servers.](https://learn.microsoft.com/en-us/aspnet/core/signalr/scale?view=aspnetcore-7.0)
19+
20+
> There are various choices of backplane that you can use for SignalR, as you will see in the link above. If you're already using Orleans, then you might want to use Orleans as the backplane to reduce the number of dependencies used by your application and to reduce the number of network hops (and latency) that would be required when calling an external service.
21+
22+
2. Send messages from Orleans grains to SignalR clients.
23+
24+
> If the SignalR component of your application is cohosted with Orleans (same server, same process and `Microsoft.AspNetCore.SignalR.IHubContext<MyHub>` can be injected into an Orleans gain), you already have this ability without installing this package.
25+
26+
> However, if the SignalR component of your application is "remote" from the grains, this package will give the grains a way of sending messages to SignalR clients by injecting `SignalR.Orleans.Core.HubContext<MyHub>`.
27+
28+
TODO: These two abilities should be provided independently of each other. Unfortunately at this stage, ability #2 is only provided if ability #1 is used as well.
1829

1930
# Installation
2031

21-
Installation is performed via [NuGet](https://www.nuget.org/packages/SignalR.Orleans/)
32+
Installation is performed via [NuGet.](https://www.nuget.org/packages/SignalR.Orleans/)
33+
34+
Packages with version `7.x.x` are compatible with Orleans `v7.x.x` and above. If you're still using an earlier version of Orleans, you will need to use earlier versions of the package.
2235

23-
From Package Manager:
36+
Package Manager:
2437

2538
> PS> Install-Package SignalR.Orleans
2639
@@ -32,9 +45,150 @@ Paket:
3245

3346
> \# paket add SignalR.Orleans
3447
35-
# Configuration
48+
---
49+
# Version 7.0.0 documentation
50+
> Scroll down to see documentation for earlier versions.
51+
52+
Here is a complete starter example featuring cohosted aspnetcore app with SignalR and Orleans.
53+
54+
```csharp
55+
using Microsoft.AspNetCore.SignalR;
56+
using Orleans.Hosting;
57+
using SignalR.Orleans;
58+
59+
// Create a host that can cohost aspnetcore AND orleans together in a single process.
60+
var builder = WebApplication.CreateBuilder(args);
61+
builder.Host.UseOrleans(siloBuilder =>
62+
{
63+
siloBuilder.UseLocalhostClustering();
64+
siloBuilder.UseSignalR(); // Adds ability #1 and #2 to Orleans.
65+
siloBuilder.RegisterHub<MyHub>(); // Required for each hub type if the backplane ability #1 is being used.
66+
});
67+
68+
builder.Services
69+
.AddSignalR() // Adds SignalR hubs to the web application
70+
.AddOrleans(); // Tells the SignalR hubs in the web application to use Orleans as a backplane (ability #1)
71+
72+
var app = builder.Build();
73+
app.MapHub<MyHub>("/myhub");
74+
await app.RunAsync();
75+
76+
// A SignalR Hub. https://learn.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-7.0
77+
class MyHub : Hub
78+
{
79+
}
80+
```
81+
82+
### Silo configuration - grain storage
83+
84+
The SignalR.Orleans backplane (ability #1) uses grains under the hood that use storage to keep track of where each SignalR client is connected and what groups it belongs to. The storage used by default is `MemoryStorage`.
85+
86+
Use the given storage name constant to configure the correct storage provider.
87+
88+
```csharp
89+
// **************************************************************************
90+
// Use memory storage ONLY when your app is not clustered, otherwise you'll
91+
// need to use proper external storage providers
92+
// **************************************************************************
93+
94+
// Customize the storage used by the SignalR Orleans backplane grains.
95+
siloBuilder.AddSomeOtherGrainStorage(SignalROrleansConstants.SIGNALR_ORLEANS_STORAGE_PROVIDER);
96+
97+
// THEN
98+
siloBuilder.UseSignalR();
99+
```
100+
101+
### Silo configuration - stream type and stream storage
102+
103+
SignalR.Orleans uses streams under the hood to provide the backplane (ability #1). The default stream type is `MemoryStream`. All streams in a given Orleans instance must use the same storage provider, named `PubSubStore`, currently defaulted to `MemoryStorage`.
104+
105+
```csharp
106+
// FIRST customize the storage used by ALL stream providers in the entire Orleans host:
107+
// Remember, memory storage won't work if you're using a cluster.
108+
siloBuilder.AddSomeOtherGrainStorage("PubSubStore");
109+
110+
// THEN customize the type of stream used for the backplane, using the correct stream provider name
111+
siloBuilder.AddPersistentStreams(SignalROrleansConstants.SIGNALR_ORLEANS_STREAM_PROVIDER, adapterFactory, configureStream);
112+
113+
// THEN
114+
siloBuilder.UseSignalR();
115+
```
116+
117+
## Sending messages from Orleans grains
118+
119+
If the SignalR app is cohosted as demonstrated above, you don't need this package to send messages from an Orleans grain. Simply inject `IHubContext<MyHub>` to the grain's constructor and call its methods to send messages. [Read more about it here.](https://learn.microsoft.com/en-us/aspnet/core/signalr/hubcontext?view=aspnetcore-7.0)
120+
121+
However, if the SignalR app is not cohosted, and if it's using Orleans as a backplane, then it's possible to use this package to send messages to the SignalR clients using the backplane streams in Orleans as a conduit (ability #2).
122+
123+
```csharp
124+
class SampleGrain : Grain, ISampleGrain
125+
{
126+
private readonly SignalR.Orleans.Core.HubContext<MyHub> _hubContext;
127+
128+
public SampleGrain(SignalR.Orleans.Core.HubContext<MyHub> hubContext)
129+
{
130+
_hubContext = hubContext;
131+
}
132+
133+
public async Task SendMessageToClients()
134+
{
135+
// Create an invocation message
136+
var msg = new InvocationMessage("method", new object?[]{ 1, 2, 3 }).ToImmutable();
137+
138+
// Send a message to a single client
139+
await _hubContext.Client("someConnectionId").Send(msg);
140+
141+
// Send a message to a group
142+
await _hubContext.Group("someGroupName").Send(msg);
143+
144+
// Send a message to all connections made by a particular authenticated user
145+
await _hubContext.Group("someUserId").Send(msg);
146+
147+
// TODO: We have not implemented ability to send a message to ALL clients yet.
148+
}
149+
}
150+
```
151+
152+
## Configuring the `IClusterClient`
153+
If your SignalR app is cohosted with Orleans, it will automatically grab an `IClusterClient` from the service provider and connect to the Orleans backplane.
154+
155+
However, if it's not cohosted, you'll have to give it an `IClusterClient` to use:
156+
157+
```csharp
158+
using Microsoft.AspNetCore.SignalR;
159+
using Orleans.Hosting;
160+
using SignalR.Orleans;
161+
162+
// Create a web application that will connect to a remote Orleans cluster
163+
var builder = WebApplication.CreateBuilder(args);
164+
builder.Services
165+
// Adds an IClusterClient to the service provider.
166+
.AddOrleansClient(clientBuilder =>
167+
{
168+
// Tell the client how to connect to Orleans (you'll need to customize this for yourself)
169+
clientBuilder.UseLocalhostClustering();
170+
// Tells the client how to connect to the SignalR.Orleans backplane.
171+
clientBuilder.UseSignalR(configure: null);
172+
})
173+
.AddSignalR() // Adds SignalR hubs to the web application
174+
.AddOrleans(); // Tells SignalR to use Orleans as a backplane (ability #1)
175+
176+
var app = builder.Build();
177+
app.MapHub<MyHub>("/myhub");
178+
await app.RunAsync();
179+
180+
// A SignalR Hub. https://learn.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-7.0
181+
class MyHub : Hub
182+
{
183+
}
184+
```
185+
186+
This is the end of documentation for versions >= 7.0.0. Below is older documenation for previous versions.
187+
188+
---
189+
# Earlier version documentation
36190

37-
## Silo
191+
## Configure the Silo
38192
We need to configure the Orleans Silo with the below:
39193
* Use `.UseSignalR()` on `ISiloHostBuilder`.
40194
* Make sure to call `RegisterHub<THub>()` where `THub` is the type of the Hub you want to be added to the backplane.

SignalR.Orleans.sln

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Microsoft Visual Studio Solution File, Format Version 12.00
2-
# Visual Studio Version 16
3-
VisualStudioVersion = 16.0.30204.135
2+
# Visual Studio Version 17
3+
VisualStudioVersion = 17.5.33209.295
44
MinimumVisualStudioVersion = 15.0.26124.0
55
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{20D142F6-AE1A-4AF1-A314-13E6AAF040ED}"
66
EndProject
@@ -12,7 +12,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SignalR.Orleans.Tests", "te
1212
EndProject
1313
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6813D377-6B57-40E3-9FDD-8D20F7CADEDF}"
1414
ProjectSection(SolutionItems) = preProject
15+
.github\workflows\ci.yml = .github\workflows\ci.yml
1516
Directory.Build.props = Directory.Build.props
17+
.github\workflows\publish.yml = .github\workflows\publish.yml
1618
README.md = README.md
1719
README.Nuget.md = README.Nuget.md
1820
EndProjectSection

src/SignalR.Orleans/AllMessage.cs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
using Microsoft.AspNetCore.SignalR.Protocol;
2+
3+
namespace SignalR.Orleans;
4+
5+
[Immutable, GenerateSerializer]
6+
public sealed record AllMessage([Immutable] InvocationMessage Message, [Immutable] IReadOnlyList<string>? ExcludedIds = null);

src/SignalR.Orleans/ClientMessage.cs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
using Microsoft.AspNetCore.SignalR.Protocol;
2+
3+
namespace SignalR.Orleans;
4+
5+
[Immutable, GenerateSerializer]
6+
public sealed record ClientMessage(string HubName, string ConnectionId, [Immutable] InvocationMessage Message);

0 commit comments

Comments
 (0)