Indiko.Blocks.EventBus.Abstractions 2.1.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Indiko.Blocks.EventBus.Abstractions --version 2.1.0
                    
NuGet\Install-Package Indiko.Blocks.EventBus.Abstractions -Version 2.1.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="Indiko.Blocks.EventBus.Abstractions" Version="2.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Indiko.Blocks.EventBus.Abstractions" Version="2.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Indiko.Blocks.EventBus.Abstractions" />
                    
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 Indiko.Blocks.EventBus.Abstractions --version 2.1.0
                    
#r "nuget: Indiko.Blocks.EventBus.Abstractions, 2.1.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 Indiko.Blocks.EventBus.Abstractions@2.1.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=Indiko.Blocks.EventBus.Abstractions&version=2.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Indiko.Blocks.EventBus.Abstractions&version=2.1.0
                    
Install as a Cake Tool

Indiko.Blocks.EventBus.Abstractions

Core abstractions for event-driven architecture and publish-subscribe messaging in the Indiko framework.

Overview

This package defines the fundamental contracts for implementing event bus systems, enabling decoupled communication between application components through asynchronous event publishing and handling.

Features

  • IEventBus Interface: Core contract for event bus implementations
  • IEvent Interface: Marker interface for event messages
  • IEventHandler<TEvent>: Generic event handler interface
  • Event Registration: Dynamic event handler registration
  • Publish-Subscribe Pattern: Decoupled event-driven communication
  • Async/Await Support: Full asynchronous event handling
  • Multiple Handlers: Support for multiple handlers per event type
  • Builder Pattern: Fluent API for event bus configuration

Installation

dotnet add package Indiko.Blocks.EventBus.Abstractions

Key Interfaces

IEventBus

Main interface for event bus operations.

public interface IEventBus
{
    // Connection management
    Task<bool> ConnectAsync(CancellationToken cancellationToken = default);
    Task DisconnectAsync(CancellationToken cancellationToken = default);
    
    // Publish events
    void Publish<TEvent>(TEvent eventMessage) where TEvent : IEvent;
    ValueTask PublishAsync<TEvent>(TEvent @event, CancellationToken cancellationToken = default) 
        where TEvent : IEvent;
    
    // Handler registration
    void RegisterEventHandler<TEvent>(IEventHandler<TEvent> eventHandler) 
        where TEvent : IEvent;
    void RegisterEventHandlers<TEvent>(params IEventHandler<TEvent>[] eventHandlers) 
        where TEvent : IEvent;
    void UnRegisterEventHandler<TEvent>() where TEvent : IEvent;
    void UnRegisterAllEventHandlers();
}

IEvent

Marker interface for event messages.

public interface IEvent
{
    // Marker interface - events inherit from this
}

IEventHandler<TEvent>

Interface for handling specific event types.

public interface IEventHandler<TEvent> where TEvent : IEvent
{
    Task HandleAsync(TEvent @event, CancellationToken cancellationToken = default);
}

Usage Examples

Define Events

using Indiko.Blocks.EventBus.Abstractions.Interfaces;

// Simple event
public class UserCreatedEvent : IEvent
{
    public Guid UserId { get; set; }
    public string Email { get; set; }
    public DateTime CreatedAt { get; set; }
}

// Event with rich data
public class OrderPlacedEvent : IEvent
{
    public Guid OrderId { get; set; }
    public Guid UserId { get; set; }
    public List<OrderItem> Items { get; set; }
    public decimal TotalAmount { get; set; }
    public DateTime OrderDate { get; set; }
}

public class OrderItem
{
    public Guid ProductId { get; set; }
    public string ProductName { get; set; }
    public int Quantity { get; set; }
    public decimal Price { get; set; }
}

Implement Event Handlers

// Single event handler
public class SendWelcomeEmailHandler : IEventHandler<UserCreatedEvent>
{
    private readonly IEmailService _emailService;

    public SendWelcomeEmailHandler(IEmailService emailService)
    {
        _emailService = emailService;
    }

    public async Task HandleAsync(UserCreatedEvent @event, CancellationToken cancellationToken = default)
    {
        await _emailService.SendWelcomeEmailAsync(@event.Email, cancellationToken);
    }
}

// Another handler for the same event
public class CreateUserProfileHandler : IEventHandler<UserCreatedEvent>
{
    private readonly IProfileService _profileService;

    public CreateUserProfileHandler(IProfileService profileService)
    {
        _profileService = profileService;
    }

    public async Task HandleAsync(UserCreatedEvent @event, CancellationToken cancellationToken = default)
    {
        await _profileService.CreateDefaultProfileAsync(@event.UserId, cancellationToken);
    }
}

Register Handlers

public class Startup : WebStartup
{
    public override void ConfigureServices(IServiceCollection services)
    {
        base.ConfigureServices(services);
        
        // Register event handlers
        services.AddScoped<IEventHandler<UserCreatedEvent>, SendWelcomeEmailHandler>();
        services.AddScoped<IEventHandler<UserCreatedEvent>, CreateUserProfileHandler>();
        services.AddScoped<IEventHandler<OrderPlacedEvent>, ProcessOrderHandler>();
    }
}

Publish Events

public class UserService
{
    private readonly IEventBus _eventBus;
    private readonly IUserRepository _userRepository;

    public UserService(IEventBus eventBus, IUserRepository userRepository)
    {
        _eventBus = eventBus;
        _userRepository = userRepository;
    }

    public async Task<User> CreateUserAsync(string email, string password)
    {
        var user = new User
        {
            Id = Guid.NewGuid(),
            Email = email,
            CreatedAt = DateTime.UtcNow
        };
        
        await _userRepository.AddAsync(user);
        
        // Publish event - all registered handlers will be invoked
        await _eventBus.PublishAsync(new UserCreatedEvent
        {
            UserId = user.Id,
            Email = user.Email,
            CreatedAt = user.CreatedAt
        });
        
        return user;
    }
}

Event Handler Patterns

Fire and Forget

public class AuditLogHandler : IEventHandler<UserCreatedEvent>
{
    private readonly IAuditService _auditService;

    public async Task HandleAsync(UserCreatedEvent @event, CancellationToken cancellationToken = default)
    {
        // Non-critical operation - log and continue
        try
        {
            await _auditService.LogUserCreationAsync(@event.UserId);
        }
        catch (Exception ex)
        {
            // Log error but don't throw
            Console.WriteLine($"Audit logging failed: {ex.Message}");
        }
    }
}

Critical Handler with Retry

public class SendOrderConfirmationHandler : IEventHandler<OrderPlacedEvent>
{
    private readonly IEmailService _emailService;
    private readonly ILogger<SendOrderConfirmationHandler> _logger;

    public async Task HandleAsync(OrderPlacedEvent @event, CancellationToken cancellationToken = default)
    {
        int maxRetries = 3;
        for (int attempt = 0; attempt < maxRetries; attempt++)
        {
            try
            {
                await _emailService.SendOrderConfirmationAsync(@event, cancellationToken);
                return; // Success
            }
            catch (Exception ex)
            {
                _logger.LogWarning($"Attempt {attempt + 1} failed: {ex.Message}");
                
                if (attempt == maxRetries - 1)
                    throw; // Final attempt failed
                
                await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)), cancellationToken);
            }
        }
    }
}

Conditional Handler

public class PremiumUserBonusHandler : IEventHandler<OrderPlacedEvent>
{
    private readonly IUserService _userService;
    private readonly IRewardService _rewardService;

    public async Task HandleAsync(OrderPlacedEvent @event, CancellationToken cancellationToken = default)
    {
        var user = await _userService.GetUserAsync(@event.UserId);
        
        // Only process for premium users
        if (user.IsPremium && @event.TotalAmount >= 100)
        {
            await _rewardService.AddBonusPointsAsync(@event.UserId, @event.TotalAmount * 0.1m);
        }
    }
}

Builder Pattern

EventBusBuilder

Fluent API for configuring event bus.

public class EventBusBuilder : IEventBusBuilder
{
    public IEventBusBuilder AddHandler<TEvent, THandler>() 
        where TEvent : IEvent 
        where THandler : IEventHandler<TEvent>;
    
    public IEventBusBuilder Configure(Action<EventBusOptions> options);
    
    public IEventBus Build();
}

Usage

var eventBus = new EventBusBuilder()
    .AddHandler<UserCreatedEvent, SendWelcomeEmailHandler>()
    .AddHandler<UserCreatedEvent, CreateUserProfileHandler>()
    .AddHandler<OrderPlacedEvent, ProcessOrderHandler>()
    .Configure(options =>
    {
        options.MaxConcurrentHandlers = 10;
        options.EnableRetry = true;
    })
    .Build();

Best Practices

  1. Keep Events Immutable: Use read-only properties
  2. Event Naming: Use past tense (UserCreated, OrderPlaced, PaymentProcessed)
  3. Handler Independence: Handlers should not depend on execution order
  4. Error Handling: Always handle exceptions in handlers
  5. Idempotency: Design handlers to be idempotent
  6. Single Responsibility: One handler, one responsibility
  7. Event Versioning: Plan for event schema evolution

Event Patterns

Domain Events

public abstract class DomainEvent : IEvent
{
    public Guid EventId { get; } = Guid.NewGuid();
    public DateTime OccurredAt { get; } = DateTime.UtcNow;
    public string EventType => GetType().Name;
}

public class ProductStockChangedEvent : DomainEvent
{
    public Guid ProductId { get; set; }
    public int OldQuantity { get; set; }
    public int NewQuantity { get; set; }
    public string Reason { get; set; }
}

Integration Events

public abstract class IntegrationEvent : IEvent
{
    public Guid Id { get; set; } = Guid.NewGuid();
    public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
    public string CorrelationId { get; set; }
}

public class PaymentCompletedEvent : IntegrationEvent
{
    public Guid OrderId { get; set; }
    public decimal Amount { get; set; }
    public string TransactionId { get; set; }
}

Configuration Options

EventBusOptions

public class EventBusOptions
{
    public int MaxConcurrentHandlers { get; set; } = 10;
    public bool EnableRetry { get; set; } = true;
    public int MaxRetryAttempts { get; set; } = 3;
    public TimeSpan RetryDelay { get; set; } = TimeSpan.FromSeconds(1);
    public bool ThrowOnHandlerError { get; set; } = false;
}

Target Framework

  • .NET 10

Dependencies

  • Indiko.Blocks.Common.Abstractions

License

See LICENSE file in the repository root.

  • Indiko.Blocks.EventBus.InMemory - In-memory event bus implementation
  • Indiko.Blocks.EventBus.RabbitMQ - RabbitMQ-based event bus
  • Indiko.Blocks.Mediation.Abstractions - CQRS and mediator pattern
  • Indiko.Blocks.Common.Management - Block management system
Product Compatible and additional computed target framework versions.
.NET 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 (2)

Showing the top 2 NuGet packages that depend on Indiko.Blocks.EventBus.Abstractions:

Package Downloads
Indiko.Blocks.EventBus.RabbitMQ

Building Blocks EventBus RabbitMQ

Indiko.Blocks.EventBus.InMemory

Building Blocks EventBus InMemory

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.1.2 304 12/18/2025
2.1.1 698 12/2/2025
2.1.0 686 12/2/2025
2.0.0 326 9/17/2025
1.7.23 202 9/8/2025
1.7.22 191 9/8/2025
1.7.21 192 8/14/2025
1.7.20 224 6/23/2025
1.7.19 207 6/3/2025
1.7.18 216 5/29/2025
1.7.17 213 5/26/2025
1.7.15 154 4/12/2025
1.7.14 177 4/11/2025
1.7.13 167 3/29/2025
1.7.12 177 3/28/2025
1.7.11 193 3/28/2025
1.7.10 178 3/28/2025
1.7.9 173 3/28/2025
1.7.8 193 3/28/2025
1.7.5 214 3/17/2025
1.7.4 193 3/16/2025
1.7.3 199 3/16/2025
1.7.2 211 3/16/2025
1.7.1 220 3/11/2025
1.6.8 245 3/11/2025
1.6.7 282 3/4/2025
1.6.6 176 2/26/2025
1.6.5 183 2/20/2025
1.6.4 173 2/20/2025
1.6.3 169 2/5/2025
1.6.2 159 1/24/2025
1.6.1 165 1/24/2025
1.6.0 156 1/16/2025
1.5.2 153 1/16/2025
1.5.1 192 11/3/2024
1.5.0 180 10/26/2024
1.3.2 196 10/24/2024
1.3.0 205 10/10/2024
1.2.5 176 10/9/2024
1.2.4 183 10/8/2024
1.2.1 167 10/3/2024
1.2.0 189 9/29/2024
1.1.1 183 9/23/2024
1.1.0 191 9/18/2024
1.0.33 187 9/15/2024
1.0.28 177 8/28/2024
1.0.27 206 8/24/2024
1.0.26 188 7/7/2024
1.0.25 202 7/6/2024
1.0.24 151 6/25/2024
1.0.23 175 6/1/2024
1.0.22 161 5/14/2024
1.0.21 135 5/14/2024
1.0.20 181 4/8/2024
1.0.19 178 4/3/2024
1.0.18 202 3/23/2024
1.0.17 210 3/19/2024
1.0.16 192 3/19/2024
1.0.15 212 3/11/2024
1.0.14 194 3/10/2024
1.0.13 195 3/6/2024
1.0.12 204 3/1/2024
1.0.11 195 3/1/2024
1.0.10 192 3/1/2024
1.0.9 225 3/1/2024
1.0.8 209 2/19/2024
1.0.7 212 2/17/2024
1.0.6 195 2/17/2024
1.0.5 173 2/17/2024
1.0.4 202 2/7/2024
1.0.3 173 2/6/2024
1.0.1 157 2/6/2024
1.0.0 228 1/9/2024
1.0.0-preview99 226 12/22/2023
1.0.0-preview98 178 12/21/2023
1.0.0-preview97 186 12/21/2023
1.0.0-preview96 193 12/20/2023
1.0.0-preview94 183 12/18/2023
1.0.0-preview93 366 12/13/2023
1.0.0-preview92 177 12/13/2023
1.0.0-preview91 201 12/12/2023
1.0.0-preview90 176 12/11/2023
1.0.0-preview89 171 12/11/2023
1.0.0-preview88 248 12/6/2023
1.0.0-preview87 182 12/6/2023
1.0.0-preview86 181 12/6/2023
1.0.0-preview85 204 12/6/2023
1.0.0-preview84 182 12/5/2023
1.0.0-preview83 211 12/5/2023
1.0.0-preview82 201 12/5/2023
1.0.0-preview81 177 12/4/2023
1.0.0-preview80 167 12/1/2023
1.0.0-preview77 185 12/1/2023
1.0.0-preview76 190 12/1/2023
1.0.0-preview75 167 12/1/2023
1.0.0-preview74 209 11/26/2023
1.0.0-preview73 203 11/7/2023
1.0.0-preview72 190 11/6/2023
1.0.0-preview71 164 11/3/2023
1.0.0-preview70 183 11/2/2023
1.0.0-preview69 184 11/2/2023
1.0.0-preview68 190 11/2/2023
1.0.0-preview67 190 11/2/2023
1.0.0-preview66 138 11/2/2023
1.0.0-preview65 170 11/2/2023
1.0.0-preview64 192 11/2/2023
1.0.0-preview63 188 11/2/2023
1.0.0-preview62 176 11/1/2023
1.0.0-preview61 176 11/1/2023
1.0.0-preview60 174 11/1/2023
1.0.0-preview59 165 11/1/2023
1.0.0-preview58 192 10/31/2023
1.0.0-preview57 180 10/31/2023
1.0.0-preview56 184 10/31/2023
1.0.0-preview55 175 10/31/2023
1.0.0-preview54 195 10/31/2023
1.0.0-preview53 159 10/31/2023
1.0.0-preview52 164 10/31/2023
1.0.0-preview51 179 10/31/2023
1.0.0-preview50 184 10/31/2023
1.0.0-preview48 171 10/31/2023
1.0.0-preview46 181 10/31/2023
1.0.0-preview45 190 10/31/2023
1.0.0-preview44 175 10/31/2023
1.0.0-preview43 182 10/31/2023
1.0.0-preview42 196 10/30/2023
1.0.0-preview41 180 10/30/2023
1.0.0-preview40 206 10/27/2023
1.0.0-preview39 191 10/27/2023
1.0.0-preview38 203 10/27/2023
1.0.0-preview37 196 10/27/2023
1.0.0-preview36 180 10/27/2023
1.0.0-preview35 186 10/27/2023
1.0.0-preview34 170 10/27/2023
1.0.0-preview33 191 10/26/2023
1.0.0-preview32 197 10/26/2023
1.0.0-preview31 199 10/26/2023
1.0.0-preview30 186 10/26/2023
1.0.0-preview29 183 10/26/2023
1.0.0-preview28 190 10/26/2023
1.0.0-preview27 188 10/26/2023
1.0.0-preview26 159 10/25/2023
1.0.0-preview25 170 10/23/2023
1.0.0-preview24 195 10/23/2023
1.0.0-preview23 181 10/23/2023
1.0.0-preview22 174 10/23/2023
1.0.0-preview21 174 10/23/2023
1.0.0-preview20 169 10/20/2023
1.0.0-preview19 191 10/19/2023
1.0.0-preview18 191 10/18/2023
1.0.0-preview16 167 10/11/2023
1.0.0-preview14 199 10/10/2023
1.0.0-preview13 191 10/10/2023
1.0.0-preview12 194 10/9/2023
1.0.0-preview101 172 1/5/2024