EventHorizon.RocketMQ.Remoting.EventBus 0.3.0

dotnet add package EventHorizon.RocketMQ.Remoting.EventBus --version 0.3.0
                    
NuGet\Install-Package EventHorizon.RocketMQ.Remoting.EventBus -Version 0.3.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EventHorizon.RocketMQ.Remoting.EventBus" Version="0.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EventHorizon.RocketMQ.Remoting.EventBus" Version="0.3.0" />
                    
Directory.Packages.props
<PackageReference Include="EventHorizon.RocketMQ.Remoting.EventBus" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EventHorizon.RocketMQ.Remoting.EventBus --version 0.3.0
                    
#r "nuget: EventHorizon.RocketMQ.Remoting.EventBus, 0.3.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package EventHorizon.RocketMQ.Remoting.EventBus@0.3.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EventHorizon.RocketMQ.Remoting.EventBus&version=0.3.0
                    
Install as a Cake Addin
#tool nuget:?package=EventHorizon.RocketMQ.Remoting.EventBus&version=0.3.0
                    
Install as a Cake Tool

EventHorizon.RocketMQ.Remoting.EventBus

English | 简体中文

EventHorizon.RocketMQ.Remoting.EventBus adds strongly typed event publishing and Push consumption to EventHorizon.RocketMQ.Remoting.

Use this adapter when the application discovers Brokers through NameServer and connects with the classic RocketMQ Remoting protocol. Delivery is at least once, so handlers must make application side effects idempotent.

Install

dotnet add package EventHorizon.RocketMQ.Remoting.EventBus

The adapter includes the required Remoting client and shared EventBus dependencies. Applications normally need only this package.

The current EventBus surface supports strongly typed publishing and clustering-mode Push consumption. It does not expose standalone Pull, LitePull, broadcasting, FIFO, transactional, delayed, priority, batch, request-reply, SQL92, or runtime-subscription APIs.

Connect to RocketMQ

Set NamesrvAddr to one or more NameServer addresses. The client obtains route information from NameServer, then connects directly to the Broker addresses advertised in that route. Those Broker addresses must be reachable from the application environment.

builder.Services.AddRocketMQRemoting(options =>
{
    options.NamesrvAddr = "localhost:9876";
});

A RocketMQ 5 Proxy address is not a Remoting NamesrvAddr. See the underlying Remoting client guide for TLS, ACL, namespace, and multi-NameServer configuration.

PULL and POP inside Push

The EventBus always exposes one Push-consumer programming model. Queue assignment controls which receive path the underlying Remoting client uses:

QueueAssignmentMode Queue assignment and receive behavior
RemotingPushQueueAssignmentMode.Client Default. The client assigns queues and receives with PULL.
RemotingPushQueueAssignmentMode.Broker The Broker assigns queues; each returned assignment may use PULL or POP according to Broker configuration.

Switching between these modes does not change the EventBus API or handler contract. Broker assignment requires the corresponding Broker-side assignment request mode to be configured.

For POP, processing must finish within PopInvisibleDuration. Classic Remoting Push does not automatically renew the receipt while a handler is running, so configure the invisible duration for the longest expected processing time.

The adapter sets ConsumeMessageBatchSize = 1, which keeps one physical message per EventBus handler invocation. PullBatchSize and PopBatchSize may still be greater than one to preserve receive efficiency.

Define events and handlers

Each event declares a stable RocketMQ route in its public parameterless constructor:

public sealed class OrderSubmittedIntegrationEvent : IntegrationEvent
{
    public OrderSubmittedIntegrationEvent()
        : base("orders", "order-submitted")
    {
    }

    public Guid OrderId { get; init; }
    public decimal Total { get; init; }
}

Implement the typed asynchronous handler contract:

public sealed class OrderSubmittedIntegrationEventHandler
    : IIntegrationEventBusHandler<OrderSubmittedIntegrationEvent>
{
    public Task HandleAsync(
        OrderSubmittedIntegrationEvent integrationEvent,
        CancellationToken cancellationToken = default)
    {
        return Task.CompletedTask;
    }
}

Topic maps directly to the RocketMQ topic. A non-null Tag is one literal tag; null publishes an untagged message. Within one registration, the ordinal, case-sensitive (Topic, Tag) pair identifies exactly one event type. Topic and Tag are not included in the default JSON body.

Register the EventBus

This registration enables publishing and consumption, then scans the application assembly for handlers:

var builder = Host.CreateApplicationBuilder(args);

builder.Services
    .AddRocketMQRemoting(options => options.NamesrvAddr = "localhost:9876")
    .AddRemotingEventBus(
        configureConsumer: options =>
        {
            options.GroupName = "ordering-service";
            options.MaxConcurrency = 8;
            options.SkipDeserializationFailures = true; // default: log, skip, and acknowledge malformed payloads
        },
        configureProducer: static _ => { })
    .AddHandlersFromAssemblyOf<Program>();

using var host = builder.Build();
await host.RunAsync();

Use AddHandler<THandler>() for one handler, AddHandlersFromAssemblyOf<TMarker>() for a marker assembly, or AddHandlersFromAssembly(assembly) for an explicit assembly. Handler registration is startup-only. Handlers default to Scoped; Transient and Singleton are also available, and singleton handlers must be thread-safe.

configureProducer enables publishing and registers IEventBus. Omit it for a consumer-only service. A Push consumer is added when the first handler is registered, so a publisher-only service can enable the Producer without registering handlers. Generic Host starts and stops the configured RocketMQ roles. The delegates receive RemotingEventBusConsumerOptions and RemotingEventBusProducerOptions, protocol-owned wrappers rather than raw client options. The producer wrapper covers ordinary send settings only; EventBus does not expose raw subscriptions or transaction topics and checkers.

Named RocketMQ registrations are also supported. A named, Producer-enabled EventBus exposes keyed IEventBus under the same name:

builder.Services
    .AddRocketMQRemoting("orders", options => options.NamesrvAddr = "orders-nameserver:9876")
    .AddRemotingEventBus(
        configureConsumer: options => options.GroupName = "ordering-service",
        configureProducer: static _ => { })
    .AddHandler<OrderSubmittedIntegrationEventHandler>();

using var host = builder.Build();
var ordersEventBus = host.Services.GetRequiredKeyedService<IEventBus>("orders");

Delivery behavior

Each message is deserialized once. All matching handlers run sequentially within one asynchronous DI scope, and the message succeeds only after every handler completes.

Configure malformed-payload handling through the registration's protocol-specific RemotingEventBusConsumerOptions passed to configureConsumer.

true is the default. A malformed payload is logged at Error with an explicit skip action and without a Payload field, no application handler is invoked, and the delivery is acknowledged as Success. With false, no handler is invoked; the log records an explicit retry action and EventBus requests ordinary retry instead.

Condition Internal EventBus outcome Remoting settlement
Route is known, payload is valid, and all handlers finish Success ConsumeResult.Success
A handler, application dependency, or route lookup fails Retry ConsumeResult.Retry, with the default delay level 0
Deserialization fails with SkipDeserializationFailures = true (default) Success with a deserialization-failure diagnostic ConsumeResult.Success
Deserialization fails with SkipDeserializationFailures = false Retry with a deserialization-failure diagnostic ConsumeResult.Retry, with the default delay level 0
Host shutdown cancels delivery Cancellation is propagated without manufacturing a result Cancellation is propagated

The Remoting client 0.6.1 ConsumeResult enum has only Success and Retry. EventBus never sets a negative delay-level sentinel or requests direct DLQ placement: internal Retry maps to ConsumeResult.Retry and leaves RemotingPushConsumeContext.DelayLevelWhenNextConsume at its default 0. Normal retry progression and any eventual DLQ decision remain with the underlying Remoting client and service. The gRPC adapter maps the same internal Retry to Failure.

Serialization failures, transport send failures, and non-success Remoting send statuses use EventBusPublishException. Caller-requested cancellation remains an unwrapped OperationCanceledException.

Serialization and logging

Newtonsoft.Json is the default serializer. It writes compact UTF-8 JSON with TypeNameHandling.None and no event envelope or .NET type name. Use UseSerializer<TSerializer>() to replace it for one EventBus registration.

Structured EventBus logs and full-payload logging are enabled by default:

eventBusBuilder.ConfigureLogging(options =>
{
    options.Enabled = true;
    options.IncludePayload = false;
});

Payload logs may contain credentials, personal data, or other sensitive content. Configure category filters, retention, and access controls for EventHorizon.RocketMQ.Remoting.EventBus.

Further reading

License

This package is licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  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.  net9.0 was computed.  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 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
0.3.0 97 8/10/2026
0.2.3 87 8/9/2026
0.2.2 87 8/8/2026
0.2.1 95 8/5/2026
0.2.0 107 8/4/2026
0.1.0 106 8/1/2026