Indiko.Blocks.EventBus.Abstractions 2.1.1

dotnet add package Indiko.Blocks.EventBus.Abstractions --version 2.1.1
                    
NuGet\Install-Package Indiko.Blocks.EventBus.Abstractions -Version 2.1.1
                    
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.1" />
                    
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.1" />
                    
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.1
                    
#r "nuget: Indiko.Blocks.EventBus.Abstractions, 2.1.1"
                    
#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.1
                    
#: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.1
                    
Install as a Cake Addin
#tool nuget:?package=Indiko.Blocks.EventBus.Abstractions&version=2.1.1
                    
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.1 49 12/2/2025
2.1.0 53 12/2/2025
2.0.0 314 9/17/2025
1.7.23 189 9/8/2025
1.7.22 176 9/8/2025
1.7.21 176 8/14/2025
1.7.20 211 6/23/2025
1.7.19 195 6/3/2025
1.7.18 200 5/29/2025
1.7.17 198 5/26/2025
1.7.15 143 4/12/2025
1.7.14 164 4/11/2025
1.7.13 152 3/29/2025
1.7.12 166 3/28/2025
1.7.11 181 3/28/2025
1.7.10 167 3/28/2025
1.7.9 168 3/28/2025
1.7.8 181 3/28/2025
1.7.5 207 3/17/2025
1.7.4 179 3/16/2025
1.7.3 183 3/16/2025
1.7.2 196 3/16/2025
1.7.1 206 3/11/2025
1.6.8 232 3/11/2025
1.6.7 265 3/4/2025
1.6.6 164 2/26/2025
1.6.5 168 2/20/2025
1.6.4 163 2/20/2025
1.6.3 153 2/5/2025
1.6.2 147 1/24/2025
1.6.1 152 1/24/2025
1.6.0 142 1/16/2025
1.5.2 143 1/16/2025
1.5.1 182 11/3/2024
1.5.0 167 10/26/2024
1.3.2 185 10/24/2024
1.3.0 193 10/10/2024
1.2.5 167 10/9/2024
1.2.4 171 10/8/2024
1.2.1 153 10/3/2024
1.2.0 178 9/29/2024
1.1.1 169 9/23/2024
1.1.0 180 9/18/2024
1.0.33 176 9/15/2024
1.0.28 166 8/28/2024
1.0.27 199 8/24/2024
1.0.26 176 7/7/2024
1.0.25 193 7/6/2024
1.0.24 141 6/25/2024
1.0.23 161 6/1/2024
1.0.22 145 5/14/2024
1.0.21 128 5/14/2024
1.0.20 168 4/8/2024
1.0.19 164 4/3/2024
1.0.18 186 3/23/2024
1.0.17 202 3/19/2024
1.0.16 177 3/19/2024
1.0.15 196 3/11/2024
1.0.14 187 3/10/2024
1.0.13 182 3/6/2024
1.0.12 184 3/1/2024
1.0.11 180 3/1/2024
1.0.10 179 3/1/2024
1.0.9 207 3/1/2024
1.0.8 196 2/19/2024
1.0.7 192 2/17/2024
1.0.6 180 2/17/2024
1.0.5 156 2/17/2024
1.0.4 191 2/7/2024
1.0.3 163 2/6/2024
1.0.1 147 2/6/2024
1.0.0 214 1/9/2024
1.0.0-preview99 213 12/22/2023
1.0.0-preview98 166 12/21/2023
1.0.0-preview97 170 12/21/2023
1.0.0-preview96 180 12/20/2023
1.0.0-preview94 171 12/18/2023
1.0.0-preview93 353 12/13/2023
1.0.0-preview92 165 12/13/2023
1.0.0-preview91 192 12/12/2023
1.0.0-preview90 162 12/11/2023
1.0.0-preview89 152 12/11/2023
1.0.0-preview88 237 12/6/2023
1.0.0-preview87 170 12/6/2023
1.0.0-preview86 168 12/6/2023
1.0.0-preview85 187 12/6/2023
1.0.0-preview84 168 12/5/2023
1.0.0-preview83 198 12/5/2023
1.0.0-preview82 193 12/5/2023
1.0.0-preview81 168 12/4/2023
1.0.0-preview80 155 12/1/2023
1.0.0-preview77 173 12/1/2023
1.0.0-preview76 181 12/1/2023
1.0.0-preview75 160 12/1/2023
1.0.0-preview74 194 11/26/2023
1.0.0-preview73 190 11/7/2023
1.0.0-preview72 176 11/6/2023
1.0.0-preview71 153 11/3/2023
1.0.0-preview70 171 11/2/2023
1.0.0-preview69 176 11/2/2023
1.0.0-preview68 171 11/2/2023
1.0.0-preview67 180 11/2/2023
1.0.0-preview66 128 11/2/2023
1.0.0-preview65 161 11/2/2023
1.0.0-preview64 178 11/2/2023
1.0.0-preview63 179 11/2/2023
1.0.0-preview62 167 11/1/2023
1.0.0-preview61 163 11/1/2023
1.0.0-preview60 169 11/1/2023
1.0.0-preview59 156 11/1/2023
1.0.0-preview58 175 10/31/2023
1.0.0-preview57 167 10/31/2023
1.0.0-preview56 176 10/31/2023
1.0.0-preview55 163 10/31/2023
1.0.0-preview54 183 10/31/2023
1.0.0-preview53 153 10/31/2023
1.0.0-preview52 158 10/31/2023
1.0.0-preview51 161 10/31/2023
1.0.0-preview50 174 10/31/2023
1.0.0-preview48 158 10/31/2023
1.0.0-preview46 169 10/31/2023
1.0.0-preview45 177 10/31/2023
1.0.0-preview44 166 10/31/2023
1.0.0-preview43 172 10/31/2023
1.0.0-preview42 181 10/30/2023
1.0.0-preview41 171 10/30/2023
1.0.0-preview40 195 10/27/2023
1.0.0-preview39 178 10/27/2023
1.0.0-preview38 188 10/27/2023
1.0.0-preview37 187 10/27/2023
1.0.0-preview36 169 10/27/2023
1.0.0-preview35 175 10/27/2023
1.0.0-preview34 155 10/27/2023
1.0.0-preview33 183 10/26/2023
1.0.0-preview32 185 10/26/2023
1.0.0-preview31 190 10/26/2023
1.0.0-preview30 171 10/26/2023
1.0.0-preview29 174 10/26/2023
1.0.0-preview28 177 10/26/2023
1.0.0-preview27 180 10/26/2023
1.0.0-preview26 154 10/25/2023
1.0.0-preview25 160 10/23/2023
1.0.0-preview24 185 10/23/2023
1.0.0-preview23 168 10/23/2023
1.0.0-preview22 162 10/23/2023
1.0.0-preview21 167 10/23/2023
1.0.0-preview20 158 10/20/2023
1.0.0-preview19 183 10/19/2023
1.0.0-preview18 182 10/18/2023
1.0.0-preview16 158 10/11/2023
1.0.0-preview14 185 10/10/2023
1.0.0-preview13 178 10/10/2023
1.0.0-preview12 180 10/9/2023
1.0.0-preview101 155 1/5/2024