You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
v7: Host the bus through dependency injection (AddObvs, IOptions, ILogger, hosted service) #84
Today: a bus is built with a long fluent chain carrying five or six generic parameters (ServiceBus.Configure().WithRabbitMQEndpoints<TServiceMessage>().Named(..).ConnectToBroker(..).SerializedAsJson().AsClientAndServer().Create()). The order matters, and mistakes produce generic-constraint compiler errors that are hard to act on. There is no integration with Microsoft.Extensions.*.
Proposal:services.AddObvs(...) with:
per-service options bound from IConfiguration, using IOptions validation on start;
ILogger throughout;
an IHostedService that starts and stops the bus;
IServiceBus and IServiceBusClient resolvable from DI.
Lifetime: the bus stays one shared instance, now enforced by DI.
IServiceBus and IServiceBusClient forward to one singleton registration, never two buses.
The container owns it: the hosted service starts it before the app takes traffic, stops it while letting in-flight handlers finish, and the container disposes it. App code no longer disposes the bus.
Handlers are resolved in a DI scope per message; the bus never holds onto scoped services.
Repeated AddObvs calls add to one bus configuration, or fail with an actionable error.
Instance ID: a DI singleton is one per container, not per process, so test hosts and WebApplicationFactory can create several buses in one process. Each bus gets an instance ID (a GUID by default, overridable in options), used in broker-side names instead of the process ID. That avoids v6's collisions: duplicate RabbitMQ exclusive queue names, a shared Kafka consumer group that splits messages between buses, and duplicate ActiveMQ client IDs on .NET Framework.
Keyed buses (AddObvs("name", ...) with [FromKeyedServices]) for the rare app that needs more than one, and a lightweight ObvsBus.StartAsync builder for apps without a host.
Done when: a worker service can configure, start and stop a bus purely through AddObvs and appsettings.json, with no fluent chain, and two hosts in one test process each run their own bus against the same broker without collisions.
The "done when" is essentially met: a worker can configure, start and stop a bus purely through AddObvs and appsettings.json, and two hosts in one test process run their own buses against the same broker.
Done in #107 (AddObvs, the hosted service and ILogger), #112, #118, #119, #121 and #123 (each transport's options from configuration), and #146 (ObvsBus.StartAsync for apps without a host, and logging transport errors). Merged into v7.
Activity
Add v7 'AI native' design doc (#97)
Host the bus through dependency injection (AddObvs) (#107)
Merge master into v7 (design doc, NetMQ fix) (#111)
UseRabbitMq with options from configuration and a per-bus instance ID (…
Merge master into v7 (deadlock backport tests) (#124)
christopherread commentedon Oct 26, 2026
Status on the
v7branch.Merged
v7: Host the bus through dependency injection (AddObvs) #107:
AddObvs, with a keyedAddObvs("name", ...)for apps that need more than one bus;IServiceBusandIServiceBusClientresolved from DI as one singleton;AddObvscalls adding to the same bus.v7: UseRabbitMq, options from configuration, per-bus instance ID #112:
ValidateWith, which reports every startup problem together in oneObvsConfigurationException;UseRabbitMq, with options bound from configuration or set in code.Configuration for the other transports:
UseNats(v7: UseNats with options from configuration, and headers over NATS #118),UseKafka(v7: UseKafka with options from configuration, and headers over Kafka #119),UseActiveMq(v7: UseActiveMq with options from configuration, and headers over ActiveMQ #121) and the newUseAzureServiceBus(v7: Obvs.AzureSB, an Azure Service Bus transport #123).The instance ID fixes v6's collisions:
Each transport has a broker test that runs two hosts in one process.
v7: Handlers, RequestAsync and MaxConcurrency #114: handlers resolved in a DI scope per message.
v7: Settle messages after their handler, starting with Azure Service Bus #126: stopping lets running handlers finish and settle before the transport stops.
The "done when" is essentially met: a worker can configure, start and stop a bus purely through
AddObvsandappsettings.json, and two hosts in one test process run their own buses against the same broker.Left
ObvsBus.StartAsync, the lightweight builder for apps without a host (v7: ObvsBus.StartAsync for apps without a host, and log transport errors (#84) #146).ILoggerinside the transports (v7: ObvsBus.StartAsync for apps without a host, and log transport errors (#84) #146). Azure Service Bus, SQS and NATS JetStream log when they start retrying after losing the broker, as Kafka already did. A hosted bus logs every error on itsExceptionsstream, which covers the other transports.Examples/still use the v6 fluent chain. The migration work (v7: Migration path and wire compatibility with v6 #95) should move them toAddObvs.Merge pull request #146 from christopherread/v7-hostless-bus
christopherread commentedon Oct 27, 2026
Done in #107 (
AddObvs, the hosted service andILogger), #112, #118, #119, #121 and #123 (each transport's options from configuration), and #146 (ObvsBus.StartAsyncfor apps without a host, and logging transport errors). Merged intov7.