mako-engine 0.3.0

Event-sourced process engine for German energy market communication (MaKo)
Documentation

mako-engine — event-sourced process runtime for German energy market communication (MaKo).

Architecture

Raw EDIFACT bytes (AS4 transport)
        │
        ▼
[edi-energy] parse · validate
        │
        ▼  Command (typed, validated)
EngineContext::spawn / ::resume → Process::execute / ::execute_with / ::execute_with_retry
        │
        ├─ load events → reconstruct state (Workflow::apply + upcast)
        ├─ handle command (Workflow::handle — pure, deterministic)
        └─ append EventEnvelope batch (optimistic concurrency)

EventStore ──► ProjectionRunner ──► Read models
SnapshotStore ──► Process::state_with_snapshot (O(k) replay)
OutboxStore ──► delivery worker ──► AS4 endpoint
DeadlineStore ──► scheduler ──► TimeoutDeadline command
ProcessRegistry ──► inbound message routing ──► Process

Quick start

use mako_engine::{
    builder::EngineBuilder,
    ids::TenantId,
    version::WorkflowId,
    event_store::InMemoryEventStore,
};

let ctx = EngineBuilder::new()
    .with_event_store(InMemoryEventStore::new())
    .build();

// Spawn a new process.
let process = ctx.spawn::<MyWorkflow>(TenantId::new(), WorkflowId::new("", "FV2024-10-01"));
let envelopes = process.execute(my_command).await?;

// Reconstruct typed state by replaying all events.
let state = process.state().await?;

// Persist routing information and resume on the next message.
ctx.registry().register(tenant, &conv_id.to_string(), process.identity()).await?;
let identity = ctx.registry().lookup(tenant, &conv_id.to_string()).await?.unwrap();
let resumed  = ctx.resume::<MyWorkflow>(identity);

Crate modules

Module Contents
[ids] Typed identifier newtypes (EventId, StreamId, ProcessId, ProcessIdentity, DeadlineId, …)
[types] Semantic domain identifiers (MaLo, MeLo, MarktpartnerCode, MessageRef, DeviceId, BkvId, UenbId, BillingPeriod)
[version] FormatVersion, WorkflowId, and WorkflowVersionPolicy
[envelope] EventEnvelope and NewEvent
[error] EngineError, WorkflowError
[event_store] EventStore trait (with stream_version) + InMemoryEventStore
[workflow] Workflow trait, EventPayload, CommandContext
[message_adapter] MessageAdapter trait, AdapterRegistry, FnAdapter — cross-FV command translation
[process] Process<W,S> — ergonomic typed process handle
[projection] Projection trait + ProjectionRunner (single-stream and multi-stream) + GlobalProjectionCheckpoint
[snapshot] Snapshot, SnapshotStore + InMemorySnapshotStore / NoopSnapshotStore
[outbox] OutboxMessage, OutboxStore + InMemoryOutboxStore / NoopOutboxStore
[inbox] InboxStore trait + InMemoryInboxStore for AS4 retry deduplication
[deadline] Deadline, DeadlineStore + InMemoryDeadlineStore / NoopDeadlineStore
[registry] ProcessRegistry + InMemoryProcessRegistry / NoopProcessRegistry
[pid_router] PidRouter — maps Prüfidentifikator values to workflow names
[fristen] Regulatory deadline helpers: add_hours (GPKE 24h), add_werktage (WiM/GeLi/MABIS)
[dead_letter] DeadLetterSink trait + LogDeadLetterSink / NoopDeadLetterSink
[erp] ErpAdapter, ErpCommandSource, ErpEvent — ERP/backend integration contract (BO4E)
[builder] EngineModule trait, EngineBuilder, EngineContext