Skip to content

Effects Composition

The AuditModule is an [EffectsModule(typeof(IAuditStore))] that generates Eff<RT, T> effect methods for audit logging.

Capability Interface

public interface IHasAuditStore
{
    IAuditStore AuditStore { get; }
}

Effect Methods

public static partial class AuditModule
{
    public static partial class Audit
    {
        public static Eff<RT, Unit> SaveAsync<RT>(AuditEntry entry)
            where RT : IHasAuditStore => ...

        public static Eff<RT, IReadOnlyList<AuditEntry>> GetByEntityAsync<RT>(
            string entityType, string entityId, int offset = 0, int limit = 20)
            where RT : IHasAuditStore => ...

        public static Eff<RT, IReadOnlyList<AuditEntry>> GetByActorAsync<RT>(
            string actor, int offset = 0, int limit = 20)
            where RT : IHasAuditStore => ...

        public static Eff<RT, IReadOnlyList<AuditEntry>> GetByActionAsync<RT>(
            string action, DateTimeOffset from, DateTimeOffset to, int offset = 0, int limit = 20)
            where RT : IHasAuditStore => ...
    }
}

Effect Pipeline Examples

Log an action after a command

var updateOrder =
    from order in AppStore.Orders.GetById<AppRuntime>(orderId)
        .Require(Error.New(404, "Order not found"))
    from _ in AppStore.Orders.Save<AppRuntime>(order with { Status = OrderStatus.Shipped })
    from __ in AuditModule.Audit.SaveAsync<AppRuntime>(new AuditEntry
    {
        EntityType = "Order",
        EntityId = orderId.ToString(),
        Action = "shipped",
        Actor = CorrelationContext.Current?.UserId ?? "system",
        Timestamp = DateTimeOffset.UtcNow
    })
    select unit;

Query audit history

var getHistory =
    from entries in AuditModule.Audit.GetByEntityAsync<AppRuntime>(
        "Order", orderId.ToString(), limit: 50)
    select entries;