R3Polska.Sse.Mercure
1.0.0
dotnet add package R3Polska.Sse.Mercure --version 1.0.0
NuGet\Install-Package R3Polska.Sse.Mercure -Version 1.0.0
<PackageReference Include="R3Polska.Sse.Mercure" Version="1.0.0" />
<PackageVersion Include="R3Polska.Sse.Mercure" Version="1.0.0" />
<PackageReference Include="R3Polska.Sse.Mercure" />
paket add R3Polska.Sse.Mercure --version 1.0.0
#r "nuget: R3Polska.Sse.Mercure, 1.0.0"
#:package R3Polska.Sse.Mercure@1.0.0
#addin nuget:?package=R3Polska.Sse.Mercure&version=1.0.0
#tool nuget:?package=R3Polska.Sse.Mercure&version=1.0.0
R3Polska.Sse.Mercure
A .NET 9 client library for publishing messages to Mercure hubs via Server-Sent Events (SSE).
Features
- 🚀 Simple, strongly-typed API for publishing messages to Mercure
- 🔧 Easy integration with ASP.NET Core dependency injection
- 🛡️ Built-in support for resilient HTTP communication with Polly
- ✅ 100% test coverage
Installation
dotnet add package R3Polska.Sse.Mercure
Quick Start
1. Configure Services
builder.Services.AddMercurePublisher(options =>
{
options.Host = "https://mercure.example.com";
options.Token = "your-jwt-token";
});
2. Create a Payload
Implement IMercureMessagePayload for your message payloads:
using R3Polska.Sse.Mercure.Message.Contract;
public record OrderCreatedPayload(
Guid OrderId,
string CustomerEmail,
decimal TotalAmount
) : IMercureMessagePayload;
3. Publish Messages
using R3Polska.Sse.Mercure.Contract;
using R3Polska.Sse.Mercure.Message;
public class OrderService
{
private readonly IMercurePublisher _mercurePublisher;
public OrderService(IMercurePublisher mercurePublisher)
{
_mercurePublisher = mercurePublisher;
}
public async Task NotifyOrderCreated(Order order, CancellationToken ct)
{
var message = new MercureMessage
{
Id = Guid.NewGuid().ToString(), // Optional: Mercure will generate one if omitted
Topic = $"orders/{order.CustomerId}",
Payload = new OrderCreatedPayload(order.Id, order.CustomerEmail, order.TotalAmount)
};
await _mercurePublisher.Publish(message, ct);
}
}
Configuration
Basic Configuration
builder.Services.AddMercurePublisher(options =>
{
options.Host = "https://mercure.example.com";
options.Token = "your-jwt-token";
});
Configuration from appsettings.json
{
"Mercure": {
"Host": "https://mercure.example.com",
"Token": "your-jwt-token"
}
}
builder.Services.AddMercurePublisher(options =>
{
builder.Configuration.GetSection("Mercure").Bind(options);
});
Configuration Options
| Option | Type | Required | Description |
|---|---|---|---|
Host |
string |
✅ | The base URL of your Mercure hub (must be a valid URL) |
Token |
string |
✅ | JWT token for authenticating with the Mercure hub |
Resilient HttpClient with Polly
For production use, it's strongly recommended to configure resilient HTTP communication using Polly and Microsoft.Extensions.Http.Resilience.
1. Install Required Packages
dotnet add package Microsoft.Extensions.Http.Resilience
2. Configure Resilient HttpClient
using Microsoft.Extensions.Http.Resilience;
builder.Services.AddMercurePublisher(options =>
{
options.Host = "https://mercure.example.com";
options.Token = "your-jwt-token";
});
// Configure resilience for the Mercure HttpClient
builder.Services.ConfigureHttpClientDefaults(http =>
{
http.AddStandardResilienceHandler();
});
3. Advanced Resilience Configuration
For fine-grained control over retry policies, circuit breakers, and timeouts:
using Microsoft.Extensions.Http.Resilience;
using Polly;
builder.Services.AddMercurePublisher(options =>
{
options.Host = "https://mercure.example.com";
options.Token = "your-jwt-token";
});
// Configure resilience specifically for IMercurePublisher's HttpClient
builder.Services.AddHttpClient<IMercurePublisher, MercurePublisher>()
.AddResilienceHandler("mercure-resilience", builder =>
{
// Retry policy: retry up to 3 times with exponential backoff
builder.AddRetry(new HttpRetryStrategyOptions
{
MaxRetryAttempts = 3,
Delay = TimeSpan.FromMilliseconds(500),
BackoffType = DelayBackoffType.Exponential,
UseJitter = true,
ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
.Handle<HttpRequestException>()
.HandleResult(r => r.StatusCode >= System.Net.HttpStatusCode.InternalServerError)
});
// Circuit breaker: break after 5 failures, stay open for 30 seconds
builder.AddCircuitBreaker(new HttpCircuitBreakerStrategyOptions
{
FailureRatio = 0.5,
SamplingDuration = TimeSpan.FromSeconds(10),
MinimumThroughput = 5,
BreakDuration = TimeSpan.FromSeconds(30),
ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
.Handle<HttpRequestException>()
.HandleResult(r => r.StatusCode >= System.Net.HttpStatusCode.InternalServerError)
});
// Timeout: 10 seconds per request
builder.AddTimeout(TimeSpan.FromSeconds(10));
});
4. Using Standard Resilience Handler (Recommended)
The simplest approach is using the standard resilience handler which includes sensible defaults:
using Microsoft.Extensions.Http.Resilience;
using R3Polska.Sse.Mercure;
using R3Polska.Sse.Mercure.Contract;
builder.Services.AddMercurePublisher(options =>
{
options.Host = "https://mercure.example.com";
options.Token = "your-jwt-token";
});
builder.Services.AddHttpClient<IMercurePublisher, MercurePublisher>()
.AddStandardResilienceHandler(options =>
{
options.Retry.MaxRetryAttempts = 3;
options.Retry.Delay = TimeSpan.FromMilliseconds(200);
options.CircuitBreaker.BreakDuration = TimeSpan.FromSeconds(15);
options.AttemptTimeout.Timeout = TimeSpan.FromSeconds(5);
options.TotalRequestTimeout.Timeout = TimeSpan.FromSeconds(30);
});
Standard Resilience Handler Defaults
The AddStandardResilienceHandler() includes these policies by default:
| Policy | Default Behavior |
|---|---|
| Rate Limiter | Limits concurrent requests |
| Total Timeout | 30 seconds for entire request including retries |
| Retry | 3 retries with exponential backoff + jitter |
| Circuit Breaker | Opens after 10% failure rate over 30 seconds |
| Attempt Timeout | 2 seconds per individual attempt |
Error Handling
The library throws MercurePublisherException when publishing fails:
try
{
await _mercurePublisher.Publish(message, cancellationToken);
}
catch (MercurePublisherException ex)
{
_logger.LogError(ex, "Failed to publish message to Mercure: {Message}", ex.Message);
// Check for inner exception (network errors, cancellation, etc.)
if (ex.InnerException is HttpRequestException httpEx)
{
// Handle network-related errors
}
}
Message Structure
MercureMessage Properties
| Property | Type | Required | Description |
|---|---|---|---|
Id |
string? |
❌ | Unique message identifier. If omitted, Mercure generates one. |
Topic |
string |
✅ | The topic URI that subscribers listen to |
Payload |
IMercureMessagePayload |
✅ | The message payload (serialized as JSON) |
Example Payloads
// Simple payload
public record NotificationPayload(string Message) : IMercureMessagePayload;
// Complex payload
public record UserActivityPayload(
Guid UserId,
string Action,
Dictionary<string, object> Metadata,
DateTime Timestamp
) : IMercureMessagePayload;
Development
Prerequisites
- .NET 9.0 SDK
- (Optional)
dotnet-reportgenerator-globaltoolfor coverage reports
Build
make build
# or
dotnet build R3Polska.Sse.Mercure.sln
Run Tests
make test
# or
dotnet test R3Polska.Sse.Mercure.Tests/R3Polska.Sse.Mercure.Tests.csproj
Generate Coverage Report
make coverage
The HTML report will be available at coveragereport/index.html.
License
BSD 3-Clause License - see LICENSE for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- Microsoft.Extensions.Configuration.Abstractions (>= 9.0.12)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.12)
- Microsoft.Extensions.Http (>= 9.0.12)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.12)
- Microsoft.Extensions.Options (>= 9.0.12)
- Microsoft.Extensions.Options.DataAnnotations (>= 9.0.12)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 220 | 2/2/2026 |