LiteBus v4.0 Release Notes
LiteBus v4 is a major release that introduces a fundamental architectural redesign, powerful new features, and significant improvements to flexibility and extensibility. The core focus of this release is to decouple the library from specific Dependency Injection (DI) containers, introduce a durable Command Inbox for guaranteed processing, and provide advanced control over event mediation.
🚀 New Features
1. Dependency Injection Abstraction (LiteBus.Runtime
)
The entire library has been refactored to be DI-agnostic. A new set of core projects (LiteBus.Runtime
and LiteBus.Runtime.Abstractions
) provides a common foundation. LiteBus now integrates with DI containers via a lightweight adapter pattern.
- DI-Agnostic Modules:
CommandModule
,QueryModule
, andEventModule
no longer depend on a specific DI container. They build against the newIModuleConfiguration
andIDependencyRegistry
abstractions. - Improved Encapsulation: Modules now only register the handlers they discover, preventing redundant DI registrations and improving startup performance.
2. First-Class Autofac Support
Alongside the existing Microsoft Dependency Injection support, LiteBus v4 now offers a dedicated integration package for Autofac.
- New Package:
LiteBus.Extensions.Autofac
provides seamless integration. - Consistent API: The registration API (
builder.AddLiteBus(...)
) is consistent with the Microsoft DI extension.
3. Durable Command Inbox
A new Command Inbox feature has been added to support durable, out-of-process, or deferred command execution. This is ideal for ensuring command processing in distributed systems or long-running workflows.
[StoreInInbox]
Attribute: Decorate anyICommand
class with this attribute to automatically divert it to a durable store instead of immediate processing.- Core Abstractions:
ICommandInbox
,ICommandInboxProcessor
, andICommandInboxBatch
provide the contracts for implementing a custom inbox store and processor. - Hosted Service:
CommandInboxProcessorHostedService
provides a ready-to-useIHostedService
for processing inbox commands in the background.
4. Advanced Event Mediation Control
Event mediation has been completely overhauled to provide granular control over handler execution.
- Handler Execution Priority: The new
[HandlerPriority(priority)]
attribute replaces[HandlerOrder]
. Handlers are grouped by priority, with lower numbers executing first. - Configurable Concurrency:
EventMediationSettings
now includes anExecution
property to control concurrency at two levels:PriorityGroupsConcurrencyMode
: Run different priority groups sequentially or in parallel.HandlersWithinSamePriorityConcurrencyMode
: Run handlers within the same priority group sequentially or in parallel.
- Powerful Handler Filtering: The
HandlerPredicate
now receives a fullIHandlerDescriptor
, allowing for advanced filtering based on handler type, priority, tags, and message type.
✨ Improvements
- Simplified Module Registration: The
AddCommandModule
,AddEventModule
, andAddQueryModule
extension methods will now automatically register the coreMessageModule
if it hasn't been registered, reducing boilerplate configuration. - Robust Message & Handler Registry: The internal
MessageRegistry
has been re-engineered for better performance and correctness, ensuring handlers are correctly associated with messages regardless of registration order. - Clearer API: Many interfaces and classes have been renamed for better clarity and intent (e.g.,
Handlers
->MainHandlers
,Order
->Priority
). - New
IMessageRegistry.Clear()
method: Useful for test environments to ensure a clean state between test runs.
💥 Breaking Changes
This is a major release with significant architectural changes. Please follow the migration guide below carefully.
- Project Structure & NuGet Packages: The project structure has been refactored. You will need to update your package references.
- DI Registration: The
AddLiteBus
registration process has changed. HandlerOrderAttribute
is nowHandlerPriorityAttribute
: The attribute and itsOrder
property have been renamed toPriority
.IMessageDependencies
Properties Renamed:Handlers
andIndirectHandlers
are nowMainHandlers
andIndirectMainHandlers
. This primarily affects custom mediation strategies.- Context
Items
Dictionary Key Type: The key for theItems
dictionary onExecutionContext
,CommandMediationSettings
, andQueryMediationSettings
has been changed fromobject
tostring
for better type safety and consistency. EventMediationSettings
Redesigned: The structure ofEventMediationSettings
has been completely changed to support advanced priority and concurrency features.
Migration Guide from v3 to v4
Follow these steps to upgrade your project to LiteBus v4.
Step 1: Update NuGet Packages
The package structure has been reorganized. You will need to remove old packages and add new ones.
1. Remove old packages:
LiteBus.Extensions.MicrosoftDependencyInjection
LiteBus.Commands.Extensions.MicrosoftDependencyInjection
LiteBus.Events.Extensions.MicrosoftDependencyInjection
LiteBus.Queries.Extensions.MicrosoftDependencyInjection
2. Add new packages:
For Microsoft.Extensions.DependencyInjection:
LiteBus.Extensions.Microsoft.DependencyInjection
LiteBus.Commands.Extensions.Microsoft.DependencyInjection
LiteBus.Events.Extensions.Microsoft.DependencyInjection
LiteBus.Queries.Extensions.Microsoft.DependencyInjection
For Autofac:
LiteBus.Extensions.Autofac
LiteBus.Commands.Extensions.Autofac
LiteBus.Events.Extensions.Autofac
LiteBus.Queries.Extensions.Autofac
Step 2: Update AddLiteBus
Registration
The registration API has been streamlined. The AddLiteBus
method is now in LiteBus.Extensions.Microsoft.DependencyInjection
or LiteBus.Extensions.Autofac
. The module-specific extensions (AddCommandModule
, etc.) are now located in their respective core projects.
Before (v3):
// using LiteBus.Messaging.Extensions.MicrosoftDependencyInjection;
// using LiteBus.Commands.Extensions.MicrosoftDependencyInjection;
services.AddLiteBus(modules =>
{
modules.AddMessageModule(msg => msg.RegisterFromAssembly(typeof(MyHandler).Assembly));
modules.AddCommandModule(cmd => cmd.RegisterFromAssembly(typeof(MyCommand).Assembly));
});
After (v4):
The core MessageModule
is now added automatically if not present.
// using LiteBus.Extensions.Microsoft.DependencyInjection;
// using LiteBus.Commands; // Note the namespace change
services.AddLiteBus(modules =>
{
// No need to add MessageModule unless you have specific global handlers to register.
// It will be added automatically by AddCommandModule.
modules.AddCommandModule(cmd => cmd.RegisterFromAssembly(typeof(MyCommand).Assembly));
});
If you need to configure the MessageModule
explicitly, ensure it is called first:
services.AddLiteBus(modules =>
{
modules.AddMessageModule(msg => msg.Register(typeof(MyGlobalErrorHandler)));
modules.AddCommandModule(cmd => cmd.RegisterFromAssembly(typeof(MyCommand).Assembly));
modules.AddEventModule(evt => evt.RegisterFromAssembly(typeof(MyEvent).Assembly));
});
Step 3: Rename HandlerOrderAttribute
to HandlerPriorityAttribute
This is a direct name change. You can perform a project-wide find and replace.
Before (v3):
[HandlerOrder(1)]
public class MyHandler : ICommandHandler<MyCommand>
{
// ...
}
After (v4):
using LiteBus.Messaging.Abstractions;
[HandlerPriority(1)]
public class MyHandler : ICommandHandler<MyCommand>
{
// ...
}
Step 4: Update Items
Dictionary Key
The key type for the Items
collection on mediation settings and execution context has been changed from object
to string
.
Before (v3):
var settings = new CommandMediationSettings();
var myKey = new object();
settings.Items[myKey] = "my-value";
// In a handler:
var myValue = AmbientExecutionContext.Current.Items[myKey];
After (v4):
var settings = new CommandMediationSettings();
settings.Items["my-key"] = "my-value";
// In a handler:
var myValue = AmbientExecutionContext.Current.Items["my-key"];
Step 5: Update EventMediationSettings
The structure of EventMediationSettings
has been completely redesigned to support the new execution features.
Before (v3):
The old settings were flat and had a simple handler predicate.
var settings = new EventMediationSettings
{
ThrowIfNoHandlerFound = true,
Filters =
{
Tags = new[] { "tag1" },
HandlerPredicate = type => type.Namespace.StartsWith("MyProject.Core")
}
};
await eventMediator.PublishAsync(myEvent, settings);
After (v4):
The settings are now split into Routing
and Execution
. The HandlerPredicate
is more powerful, receiving the full IHandlerDescriptor
.
var settings = new EventMediationSettings
{
ThrowIfNoHandlerFound = true,
Routing =
{
Tags = new[] { "tag1" },
// The predicate now receives the full descriptor
HandlerPredicate = descriptor => descriptor.HandlerType.Namespace.StartsWith("MyProject.Core")
},
Execution =
{
// New concurrency controls
PriorityGroupsConcurrencyMode = ConcurrencyMode.Sequential,
HandlersWithinSamePriorityConcurrencyMode = ConcurrencyMode.Parallel
}
};
await eventMediator.PublishAsync(myEvent, settings);
Step 6: Update Custom Mediation Strategies (Advanced)
If you have implemented a custom IMessageMediationStrategy
, you will need to update it to use the renamed properties on IMessageDependencies
.
Before (v3):
public TResult Mediate(TMessage message, IMessageDependencies messageDependencies, ...)
{
var mainHandler = messageDependencies.Handlers.Single();
var indirectHandlers = messageDependencies.IndirectHandlers;
// ...
}
After (v4):
public TResult Mediate(TMessage message, IMessageDependencies messageDependencies, ...)
{
var mainHandler = messageDependencies.MainHandlers.Single();
var indirectHandlers = messageDependencies.IndirectMainHandlers;
// ...
}