Indiko.Blocks.EventBus.Abstractions 2.1.2

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