Skip to content
Development
Skill

/managedcode-orleans-signalr

Integrate ManagedCode.Orleans.SignalR for grain-driven SignalR delivery, connection and group routing, offline user queues, and restart-safe state. USE FOR: Orleans backplane setup, grain-to-hub publishing, reconnect, heartbeat, and client-invocation failures. DO NOT USE FOR:

From plugin
managedcode-dotnet-skills
483184 skills17 agents
Install
$ npx -y skills add managedcode/dotnet-skills --skill managedcode-orleans-signalr --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/managedcode-orleans-signalr

Context preview

The summary Claude sees to decide when to auto-load this skill.

Integrate ManagedCode.Orleans.SignalR for grain-driven SignalR delivery, connection and group routing, offline user queues, and restart-safe state. USE FOR: Orleans backplane setup, grain-to-hub publishing, reconnect, heartbeat, and client-invocation failures. DO NOT USE FOR:

SKILL.md

managedcode-orleans-signalr.SKILL.md
name: managedcode-orleans-signalr
description: "Integrate ManagedCode.Orleans.SignalR for grain-driven SignalR delivery, connection and group routing, offline user queues, and restart-safe state. USE FOR: Orleans backplane setup, grain-to-hub publishing, reconnect, heartbeat, and client-invocation failures. DO NOT USE FOR: ordinary SignalR without Orleans or unrelated persistence. INVOKES: inspect configuration, implement the integration, and validate connected-client delivery."
compatibility: "Requires a .NET application with compatible Orleans and ASP.NET Core SignalR packages; use aligned ManagedCode.Orleans.SignalR Client and Server versions."

ManagedCode.Orleans.SignalR

Trigger On

  • configuring an Orleans SignalR backplane or sending messages from grains
  • diagnosing connection, group, or user routing across hosts
  • upgrading offline delivery, heartbeat persistence, or client invocation handling

Install

For a host that runs both the silo and SignalR endpoint:

dotnet add package ManagedCode.Orleans.SignalR.Server --version 10.3.0
dotnet add package ManagedCode.Orleans.SignalR.Client --version 10.3.0

For separate hosts, put Server on the silo and Client on the ASP.NET Core endpoint. Core supplies shared contracts transitively. Keep versions and partition options aligned across participants; preserve central package management when present.

Configure the Backplane

A combined local development host can use the memory provider:

using ManagedCode.Orleans.SignalR.Server.Extensions;
using Microsoft.AspNetCore.SignalR;

var builder = WebApplication.CreateBuilder(args);
builder.Host.UseOrleans(silo =>
{
    silo.UseLocalhostClustering();
    silo.ConfigureOrleansSignalR();
    silo.AddOrleansSignalRInMemoryStorage();
});
builder.Services.AddSignalR().AddOrleans(options =>
{
    options.ConnectionPartitionCount = 4;
    options.GroupPartitionCount = 4;
    options.KeepMessageInterval = TimeSpan.FromMinutes(5);
    options.MaxQueuedMessagesPerUser = 100;
});

var app = builder.Build();
app.MapHub<UpdatesHub>("/updates");
app.Run();

public sealed class UpdatesHub : Hub { }

Import only `Server.Extensions` for this combined host; a separate client-only endpoint uses `Client.Extensions`. Importing both makes `AddOrleans` ambiguous. Use authenticated hub endpoints and the application's existing cluster discovery in deployed environments. The memory provider does not survive silo restarts. When offline delivery must survive restarts, register a durable Orleans grain-storage provider under `OrleansSignalROptions.OrleansSignalRStorage` instead of the memory helper. Connection metadata, queued messages, heartbeat registrations, and invocation state use this named store.

Send and Receive Updates

Inject `IHubContext<UpdatesHub>` into the grain or application service that owns the event:

using Microsoft.AspNetCore.SignalR;

public sealed class UpdatePublisher(IHubContext<UpdatesHub> hub)
{
    public Task NotifyUserAsync(string userId, string eventId, string text) =>
        hub.Clients.User(userId).SendAsync("Updated", eventId, text);

    public Task NotifyGroupAsync(string group, string eventId, string text) =>
        hub.Clients.Group(group).SendAsync("Updated", eventId, text);
}

Register a receiver before starting the connection. This example uses the application's `@microsoft/signalr` client:

import { HubConnectionBuilder } from '@microsoft/signalr';

const connection = new HubConnectionBuilder()
  .withUrl('/updates')
  .withAutomaticReconnect()
  .build();

connection.on('Updated', (eventId, text) => {
  renderUpdate(eventId, text); // Application-owned rendering and deduplication.
});
await connection.start();

Derive `userId` and permitted group membership from authenticated application identity. Never treat a client-supplied user or group name as authorization. Keep domain state in the owning grain; the backplane transports notifications about that state.

Delivery and Upgrade Boundaries

  • `10.3.0` persists queued offline user messages with delivery IDs and expiry, removing them after acknowledgement. Successful dispatch or queue storage is not proof that the browser applied the update; use application event IDs and idempotent handlers when replay matters.
  • `KeepMessageInterval` bounds offline retention. `MaxQueuedMessagesPerUser` defaults to 100 and discards oldest entries when exceeded. Test expiry and overflow explicitly; offline queues are not an unlimited event log.
  • `KeepEachConnectionAlive` renews a bounded heartbeat lease. Disabling it relies on ordinary observer/activation lifecycle; it does not make disconnected observers immortal. Test clean disconnect and abrupt host loss independently.
  • Observer failure thresholds, grace-period buffering, and circuit-breaker options affect retries and cleanup. Set them from measured reconnect behavior and watch drop/failure metrics.
  • Internal persisted `HubMessageState` changed from a dictionary to a `QueuedHubMessage` list, and `ISignalRInvocationGrain.WaitForCompletion` now returns a cancellation-aware `IAsyncEnumerable<CqrsStreamChunk<InvocationProgress, CompletionMessage>>`. Applications using these lower-level contracts must validate serialization and mixed-version compatibility before rolling upgrades.
  • A storage write failure must remain observable. Test retry and reactivation with the actual configured serializer and storage provider; an in-memory-only test does not prove durable recovery.
flowchart LR
  G[Grain or service] --> H[IHubContext]
  H --> R[Orleans connection, group, or user routing]
  R --> L[Live observer dispatch]
  R --> Q[Offline user queue in named grain storage]
  Q --> P[Reconnect and replay]
  P --> A[Acknowledge delivery ID]
  A --> D[Remove queued message]
  L --> C[SignalR client]
  P --> C

Workflow

1. Choose combined or separate silo/endpoint hosts and align packages, clustering, partition o

Read more
Ships withmanagedcode-dotnet-skills

Stop explaining .NET to your AI. Start building. We've all been there: asking Claude to use Entity Framework, only to get EF6 patterns in a .NET 8 project. Explaining to Copilot that Blazor Server and Blazor WebAssembly aren't the same thing.

Get the whole plugin

Other skills on managedcode-dotnet-skills.