Skip to content

Replace custom IEventBus with Wolverine#114

Merged
antosubash merged 6 commits intomainfrom
feature/compassionate-morse
Apr 15, 2026
Merged

Replace custom IEventBus with Wolverine#114
antosubash merged 6 commits intomainfrom
feature/compassionate-morse

Conversation

@antosubash
Copy link
Copy Markdown
Owner

Summary

Replaces the custom 424-LOC event-bus implementation (IEventBus,
EventBus, BackgroundEventChannel, BackgroundEventDispatcher,
IEventHandler<T>, IEventPipelineBehavior<T>) with
WolverineFx 5.31. The IEvent marker
interface is retained as a boundary hint, since keeping it costs
nothing and removing it would churn all 26 event-definition files.

  • Net delta: −1,232 LOC across 56 files
  • Package: WolverineFx 5.31.0 + Scrutor 7.0.0 (Scrutor is used
    to decorate IMessageBus for audit capture)
  • Publish semantic: all 22 module call sites map to Wolverine's
    PublishAsync (fire-and-forget to the local queue). No modules
    currently register handlers, so the distinction between the old
    PublishAsync/PublishInBackground is academic in practice.

Commit-by-commit

  1. 3809a139 — add WolverineFx + wire UseWolverine alongside existing IEventBus
  2. 1cd31b23 — route Wolverine IMessageBus through AuditingMessageBus decorator (via Scrutor); DomainEventInterceptor now dispatches via IMessageBus
  3. c22bda92 — migrate all 22 module publishers to IMessageBus; test fixtures swap to TestMessageBus / NSubstitute; CLI scaffolder updated
  4. 899aae81 — delete the old event-bus code, the shared TestEventBus, and AuditingEventBus + its tests; SM0010 diagnostic rewritten
  5. 40e83ec9 — doc cleanup (cross-module skill, stale cref)

Design decisions

  • Kept IEvent marker. Boundary-enforcement hint with no runtime cost.
  • AuditingMessageBus is a Scrutor decorator, not a Wolverine middleware/handler.
    Wolverine handler chains only run when a handler exists; auditing here must fire on
    every publish regardless of handlers.
  • Kept Lazy<IMessageBus> in SettingsService. The
    SettingsService → IMessageBus → AuditingMessageBus → ISettingsContracts
    cycle still exists with Scrutor decoration, so Lazy<> indirection is still required.
  • DomainEventInterceptor passes domain events by their boxed IEvent type; Wolverine's
    PublishAsync<T> routes on message.GetType() internally, so the concrete-type
    reflection dance the old interceptor performed is no longer needed.

Test plan

  • dotnet build — 0 errors
  • dotnet test — all tests pass across every module project (AuditLogs, BackgroundJobs,
    Chat, Core, Database, DevTools, Email, FeatureFlags, FileStorage, Generator,
    Localization, Map, Marketplace, OpenIddict, Orders, PageBuilder, Permissions, Products,
    RateLimiting, Settings, Tenants, Users, Admin, Datasets, Rag)
  • Zero hits for IEventBus|EventBus|BackgroundEventChannel|BackgroundEventDispatcher|IEventHandler<|IEventPipelineBehavior in production code
  • WebApplicationFactory DI-resolution guard test now targets IMessageBus
  • Run load tests against the new stack (out of scope for this PR)
  • Manual smoke: publish an audit-captured event, verify it shows up in the audit log

Phase 1 of the IEventBus -> Wolverine migration. Introduces WolverineFx
5.31 and Scrutor 7.0 packages. The old custom EventBus/BackgroundEvent
infrastructure remains registered so no runtime behavior changes yet;
subsequent phases will migrate modules to IMessageBus and delete the
custom implementation.
Adds a new AuditingMessageBus that decorates Wolverine's IMessageBus
via Scrutor and captures an AuditEntry for every IEvent published,
sent, or invoked. The audit-extraction logic is factored out into a
shared AuditEntryExtractor so AuditingEventBus and AuditingMessageBus
produce identical entries during the migration; AuditingEventBus is
deleted in a later phase once modules stop using IEventBus.

DomainEventInterceptor now dispatches via IMessageBus. Wolverine
routes by the runtime type of the message (message.GetType()), so
no reflection is needed to preserve concrete-type dispatch.
Sweeps 22 files across Users, Tenants, Products, Orders, PageBuilder,
FileStorage, Email, Datasets, FeatureFlags, and Settings. The default
publish semantic is Wolverine's PublishAsync (fire-and-forget to the
local queue), which matches the fact that no modules currently
register IEventHandler<T> handlers — events are broadcast-only today.

PublishInBackground (formerly fire-and-forget on the custom bus) and
PublishAsync (formerly sync-with-propagation) both map to Wolverine's
PublishAsync since no callers actually observe handler failures today.

SettingsService keeps its Lazy<> indirection (now Lazy<IMessageBus>)
to break the SettingsService -> AuditingMessageBus -> ISettingsContracts
construction cycle. Test stubs migrate to a shared TestMessageBus and
to NSubstitute. The old IEventBus registration and AuditingEventBus
remain in place until Phase 4 cleans them up.

The CLI module template (ModuleTemplates.cs) now scaffolds IMessageBus
for new modules.
Phase 4 of the Wolverine migration. Removes the now-unused custom
event bus, its tests, the shared TestEventBus fake, and AuditingEventBus
(replaced by AuditingMessageBus in phase 2). The IEvent marker interface
is kept — it costs nothing and remains a documentation hint about
which types are domain events.

The SM0010 circular-dependency diagnostic now suggests Wolverine
handlers instead of IEventHandler<T>. Doc comments on IHasDomainEvents
and AuditableAggregateRoot updated to reference IMessageBus.

Net deletion: ~600 LOC across seven framework files, four framework
tests, the shared fake, and AuditingEventBus + its tests.
Rewrites the event-bus section of .claude/skills/simplemodule/
references/cross-module.md to describe Wolverine's IMessageBus,
convention-based handler discovery, and inline/queued publish
semantics. Also fixes a dangling cref on AuditEntryExtractor that
pointed to the deleted AuditingEventBus class.
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Apr 15, 2026

Deploying simplemodule-website with  Cloudflare Pages  Cloudflare Pages

Latest commit: 47542e9
Status: ✅  Deploy successful!
Preview URL: https://04d248a0.simplemodule-website.pages.dev
Branch Preview URL: https://feature-compassionate-morse.simplemodule-website.pages.dev

View logs

…-morse

# Conflicts:
#	framework/SimpleModule.Generator/Emitters/DiagnosticEmitter.cs
@antosubash antosubash merged commit e0c973d into main Apr 15, 2026
5 checks passed
@antosubash antosubash deleted the feature/compassionate-morse branch April 15, 2026 21:12
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