Codebelt

Savvyio.EventDriven

Model integration events as first-class requests and publish them through Savvy I/O handlers.

.NET 10.0 / .NET 9.0 MIT v5.0.8 13,548 downloads

Overview

Savvyio.EventDriven adds integration event specific building blocks on top of Savvyio.Core. It gives you an abstract IntegrationEvent base record, an IntegrationEventHandler base class for registering fire-and-forget delegates, and an IntegrationEventDispatcher that publishes IIntegrationEvent instances through Savvy I/O dispatching abstractions.

The package is aimed at applications that want integration events to carry consistent metadata without committing to a transport implementation. Tests show that event instances expose event id, timestamp, and member type metadata, and that published events can be routed to registered handler delegates.

Key APIs

IntegrationEvent is the package's base record for custom integration events. Its protected constructor assigns an event id when none is supplied, stamps the event with DateTime.UtcNow, and merges any supplied metadata into the request.

IntegrationEventHandler is the extension point for consumers who want class-based integration event handlers. You inherit from it and implement RegisterDelegates(IFireForgetRegistry<IIntegrationEvent> handlers) to register handlers for concrete integration event types, while the base constructor creates the Delegates activator that the dispatcher uses.

IntegrationEventDispatcher is the default IIntegrationEventDispatcher implementation. Its Publish and PublishAsync methods guard against null requests and dispatch IIntegrationEvent instances with fire-and-forget semantics by invoking the delegates exposed by registered IIntegrationEventHandler implementations.

IntegrationEventExtensions exposes GetEventId, GetTimestamp, and GetMemberType for reading integration event metadata from the request. The tests use these extensions to verify that integration events surface the metadata expected by the package.

SavvyioOptionsExtensions adds the integration event pieces to SavvyioOptions. AddIntegrationEventHandler<TImplementation>() registers handler types that implement IIntegrationEventHandler, and AddIntegrationEventDispatcher() registers IntegrationEventDispatcher as the default dispatcher implementation.

Basic usage

using System;
using Codebelt.Extensions.Xunit;
using Savvyio.EventDriven;
using Xunit;

namespace MyProject.Tests;

public class IntegrationEventUsage : Test
{
    public IntegrationEventUsage(ITestOutputHelper output) : base(output) { }

    [Fact]
    public void IntegrationEvent_NewInstance_PopulatesMetadata()
    {
        var before = DateTime.UtcNow;
        var @event = new AccountExported("crm", 12);
        var after = DateTime.UtcNow;

        TestOutput.WriteLine($"EventId: {@event.GetEventId()}");
        TestOutput.WriteLine($"Timestamp: {@event.GetTimestamp():O}");
        TestOutput.WriteLine($"MemberType: {@event.GetMemberType()}");

        Assert.Equal("crm", @event.Destination);
        Assert.Equal(12, @event.Count);
        Assert.False(string.IsNullOrWhiteSpace(@event.GetEventId()));
        Assert.InRange(@event.GetTimestamp(), before, after.AddSeconds(1));
        Assert.Contains(nameof(AccountExported), @event.GetMemberType());
    }

    private sealed record AccountExported(string Destination, int Count) : IntegrationEvent();
}

Use this pattern when you want application events to inherit a consistent event identity and timestamp without repeating metadata code in every event type. It matters because the package assigns and exposes that metadata in one place, so consumers can read it through the integration event extensions instead of maintaining parallel event bookkeeping.

Installation

dotnet add package Savvyio.EventDriven

Usage guidance

Choose Savvyio.EventDriven when your application needs a dedicated in-process model for integration events, event-specific handler registration, and the default fire-and-forget dispatcher built on Savvy I/O abstractions. If you only need the lower-level request and handler model, Savvyio.Core is the smaller dependency, and if you need distributed transport concerns such as message wrappers or bus implementations, move up to the sibling messaging layer described by Savvyio.EventDriven.Messaging.

Family packages