Unitee.EventDriven.AzureServiceBus
7.0.0
See the version list below for details.
dotnet add package Unitee.EventDriven.AzureServiceBus --version 7.0.0
NuGet\Install-Package Unitee.EventDriven.AzureServiceBus -Version 7.0.0
<PackageReference Include="Unitee.EventDriven.AzureServiceBus" Version="7.0.0" />
paket add Unitee.EventDriven.AzureServiceBus --version 7.0.0
#r "nuget: Unitee.EventDriven.AzureServiceBus, 7.0.0"
// Install Unitee.EventDriven.AzureServiceBus as a Cake Addin
#addin nuget:?package=Unitee.EventDriven.AzureServiceBus&version=7.0.0
// Install Unitee.EventDriven.AzureServiceBus as a Cake Tool
#tool nuget:?package=Unitee.EventDriven.AzureServiceBus&version=7.0.0
Unitee.EventDriven
https://github.com/uniteeio/Unitee.EventDriven
Summary
Unitee.EventDriven is library to deal with Event Driven Programming (EDP) in a distributed environment.
dotnet add package Unitee.EventDriven.RedisStream
For now, we mainly focus on Redis as an event store because:
- Easy to deploy or find free (cheap) clusters
- Easy to visualize with a gui tool
- A tool you may already familiar with (for caching for example)
- Builtin system for pub/sub and storing streams
- Good .NET integration
Features
- Publishing distributed messages
- Subscribe to distributed messages
- Request/Reply pattern
- Scheduling messages
- Treat pending messages at start
How to use
- Use the package
StackExchang.Redis
to make theIConnectionMultiplexer
in the DI container.
var multiplexer = ConnectionMultiplexer.Connect(builder.Configuration["Redis:ConnectionString"]);
builder.Services.AddSingleton<IConnectionMultiplexer>(multiplexer);
- Create an event as a POCO object.
[Subject("USER_REGISTERED")]
public record UserRegistered(int UserId, string Email);
If the subject is ommited, the name of the object is used instead (here, UserRegistered
)
Guide
Publish an event
Setup
builder.Services.AddScoped<IRedisStreamPublisher, RedisStreamPublisher>();
Publish
Use the IRedisStreamPublisher
to actually publish the event:
[ApiController]
public class UserController : ControllerBase
{
private readonly IRedisStreamPublisher _publisher;
private readonly IUserService _userService;
public UserController(IRedisStreamPublisher publisher, IUserService userService)
{
_publisher = publisher;
_userService = userService;
}
public async Task<IActionResult> Register(string email)
{
var userId = _userService.CreateUserInBdd();
await _publisher.PublishAsync(new UserRegistered(userId, email));
return Ok();
}
// Request a reply
public async Task<IActionResult> ForgotPassword(string email)
{
try
{
var response = await _publisher.RequestResponseAsync(new PasswordForgotten(email));
return Ok();
}
catch (TimeoutException)
{
return NotFound();
}
}
// Schedule
public async Task<IActionResult> Register(string email)
{
await _publisher.PublishAsync(new UserRegistered30MinutesAgo(email), new()
{
ScheduledEnqueueTime = DateTime.UtcNow.AddMinutes(30);
});
return Ok();
}
}
Consume an event
Setup
You need to register a RedisStreamBackgorundReceiver
:
services.AddRedisStreamBackgroundReceiver("ConsumerService");
Implementation detail: The name is used to create consumer groups. A message is delivered to all the consumer groups. (one to many communication).
Consume
You also need to create a class that implements: IRedisStreamConsumer<TEvent>
public class UserRegisteredConsumer : IRedisStreamConsumer<UserRegistered>
{
public async Task ConsumeAsync(UserRegistered message)
{
await _email.Send(message.Email);
}
}
Then, register your consumer:
services.AddScoped<IConsumer, UserRegisteredConsumer>();
If you want to your consumer to be able to reply, then, implement IRedisStreamConsumerWithContext<TRequest, TResponse>
instead.
public class UserRegisteredConsumer : IRedisStreamConsumeWithContext<UserRegistered, MyResponse>
{
public async Task ConsumeAsync(UserRegistered message, IRedisStreamMessageContext context)
{
await _email.Send(message.Email);
await context.ReplyAsync(new MyResponse());
}
}
Dead letter queue
If a consumer throw, then the message and the exception are published to a special queue named: dead letter queue.
The default name is DEAD_LETTER
but you can configured it by providing a second parameter to AddRedisStreamBackgroundReceiver
. You can easily imagine a script able to pull the messages from the dead letter queue and send them again.
Horizontal scaling
Inside a consumer group, you can have multiple consumers. Each consumer group receives a single copy of the message.
You can name the consumer with the third parameter of AddRedisStreamBackgroundReceiver
. You should use an unique name PER INSTANCE.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net7.0
- Azure.Messaging.ServiceBus (>= 7.12.0)
- Unitee.EventDriven.Abstraction (>= 7.0.0)
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 |
---|---|---|
11.0.0 | 151 | 8/31/2023 |
10.2.0 | 149 | 7/10/2023 |
10.0.0 | 140 | 7/7/2023 |
9.2.0 | 167 | 6/29/2023 |
9.1.0-alpha.1 | 74 | 4/24/2023 |
9.0.0-alpha.4 | 85 | 3/9/2023 |
9.0.0-alpha.2 | 81 | 3/9/2023 |
9.0.0-alpha.1 | 87 | 2/21/2023 |
8.0.0-alpha.2 | 81 | 2/16/2023 |
8.0.0-alpha.1 | 82 | 2/15/2023 |
7.0.0 | 269 | 2/15/2023 |
7.0.0-alpha.1 | 87 | 2/7/2023 |
6.1.1 | 325 | 12/12/2022 |
6.1.0 | 280 | 12/8/2022 |
6.0.3 | 348 | 11/28/2022 |
6.0.2 | 327 | 11/28/2022 |
5.6.0 | 368 | 11/8/2022 |
5.5.0 | 334 | 11/8/2022 |
5.4.0 | 325 | 11/8/2022 |
5.3.0 | 336 | 11/8/2022 |
5.2.0 | 351 | 11/8/2022 |
5.1.0 | 324 | 11/8/2022 |
5.0.1 | 360 | 10/27/2022 |
5.0.0 | 356 | 10/27/2022 |
4.0.1 | 411 | 10/26/2022 |