Skip to content

v7: Host the bus through dependency injection (AddObvs) - #107

Merged
christopherread merged 1 commit into
v7from
v7-di-hosting
Oct 25, 2026
Merged

christopherread merged 1 commit into
v7from
v7-di-hosting

Conversation

@christopherread

Copy link
Copy Markdown
Owner

First v7 increment, part of #84 (design, section 1). Targets the long-running v7 branch.

API

builder.Services.AddObvs(obvs => obvs
    .AddService<IOrderMessage>("orders", service => service
        .UseEndpointProvider(sp => /* any existing transport's IServiceEndpointProvider */)
        .AsServer()));          // or AsClient(); client and server is the default

builder.Services.AddObvs("analytics", obvs => ...);   // separate keyed bus, if ever needed

Behaviour

  • One bus: a single singleton resolves as both IServiceBus and IServiceBusClient.
  • Created at startup: a hosted service creates the bus when the host starts, so configuration errors stop startup. The container disposes it; stopping the host doesn't.
  • Repeated calls: AddObvs called more than once adds to the same bus.
  • Roles: AsClient() and AsServer() control which endpoints are created.
  • Keyed buses: AddObvs(key, ...) registers a bus resolved with [FromKeyedServices(key)]. Each container gets its own bus, so two hosts in one process don't share one.
  • Validation: an invalid configuration throws one ObvsConfigurationException listing every problem with its fix. For example, a service with no transport, or a service name used twice.
  • ServiceBus.Dispose() is now safe to call twice. The container tracks the bus behind both of its registrations, so it was being disposed twice, and real transports may not tolerate that.

UseEndpointProvider lets every existing v6 transport work straight away. Each transport's own Use<Transport>() method, with options from configuration, comes in a later increment.

Dependencies

The core Obvs package now references Microsoft.Extensions.DependencyInjection.Abstractions and Microsoft.Extensions.Hosting.Abstractions 10.0.13. Both support net462+ and netstandard2.0, so no targets are dropped.

Tests (written first)

  • Obvs.Tests/Hosting/TestAddObvs.cs: 13 tests. 12 were agreed before implementation and all failed with NotImplementedException. ShouldDisposeTheBusOnlyOnce was added during implementation and failed with "Expected 1, Actual 2".
  • TestServiceBus.ShouldDisposeEndpointsOnlyOnceWhenDisposedTwice: failed before the Dispose guard.
  • All pass now: a clean build of the solution has 0 warnings across net472, netstandard2.0 and net10.0, and all 143 unit tests pass.

Not in this increment

🤖 Generated with Claude Code

services.AddObvs(obvs => obvs.AddService<TServiceMessage>(name, service =>
service.UseEndpointProvider(...))) registers one singleton bus, resolvable
as both IServiceBus and IServiceBusClient. A hosted service creates it when
the host starts, so configuration errors stop startup; the container
disposes it. Repeated AddObvs calls add to the same bus, AsClient/AsServer
choose which endpoints are created, AddObvs(key, ...) registers a separate
keyed bus, and an invalid configuration fails with one
ObvsConfigurationException listing every problem and its fix.

UseEndpointProvider bridges every existing transport until each gets its
own Use<Transport>() method.

ServiceBus.Dispose is now safe to call twice: the container tracks the bus
behind both of its registrations.

Part of #84.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@christopherread christopherread added this to the v7 milestone Oct 25, 2026
@christopherread christopherread self-assigned this Oct 25, 2026
@christopherread
christopherread merged commit 7a1ca7f into v7 Oct 25, 2026
1 check passed
@christopherread
christopherread deleted the v7-di-hosting branch October 25, 2026 16:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant