Architecture

Sourcing is built on Raku's powerful metaprogramming capabilities. It uses custom metaclasses, roles, and traits to provide a declarative API for event sourcing.

Component Diagram

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Sourcing.rakumod                      β”‚
β”‚  (exports: sourcing, traits, EXPORTHOW/DECLARE)          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                β”‚                      β”‚
                β–Ό                      β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  Roles           β”‚   β”‚  Metamodel/              β”‚
    β”‚  - Projection    β”‚   β”‚  - ProjectionHOW         β”‚
    β”‚  - Aggregation   β”‚   β”‚  - AggregationHOW        β”‚
    β”‚  - ProjectionId  β”‚   β”‚  - ProjectionIdContainer β”‚
    β”‚  - ProjectionIdMapβ”‚  β”‚  - EventHandlerContainer β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                β”‚
                β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  Sourcing/               β”‚
    β”‚  - Plugin                β”‚
    β”‚  - Plugin::Memory        β”‚
    β”‚  - ProjectionStorage     β”‚
    β”‚  - X::OptimisticLocked   β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Runtime Flow

Command ──► Aggregation ──► emit(event) ──► Plugin (Event Store)
                β”‚                                β”‚
                β”‚ validates                      β”‚ appends to @!events
                β”‚ enforces invariants            β”‚ broadcasts on Supply
                β–Ό                                β–Ό
            (state from events)          ProjectionStorage
                                              β”‚
                                        routes events
                                              β–Ό
                                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                    ↓                   ↓
                              Projection 1        Projection 2
                              (dashboard)         (analytics)

Key Design Decisions

DecisionRationale
Metaclass-basedCustom HOWs add introspection capabilities and auto-generate methods
Role compositionFunctionality is composed through roles for flexibility
Trait-drivenRaku's trait_mod:<is> enables declarative configuration
Supply-based streamingRaku's Supply provides reactive event distribution
Plugin architectureStorage backends are pluggable (Memory, future: SQLite, PostgreSQL)

File Structure

lib/
β”œβ”€β”€ Sourcing.rakumod              # Main module, exports, traits
β”œβ”€β”€ Sourcing/
β”‚   β”œβ”€β”€ Projection.rakumod        # Role for projections
β”‚   β”œβ”€β”€ Aggregation.rakumod       # Marker role for aggregations
β”‚   β”œβ”€β”€ ProjectionId.rakumod      # Role for ID attributes
β”‚   β”œβ”€β”€ ProjectionIdMap.rakumod   # Role for ID mapping
β”‚   β”œβ”€β”€ ProjectionStorage.rakumod # Event router / registry
β”‚   β”œβ”€β”€ Plugin.rakumod            # Abstract plugin interface
β”‚   β”œβ”€β”€ Plugin/
β”‚   β”‚   └── Memory.rakumod        # In-memory implementation
β”‚   └── X/
β”‚       └── OptimisticLocked.rakumod # Exception class
└── Metamodel/
    β”œβ”€β”€ ProjectionHOW.rakumod     # Metaclass for projections
    β”œβ”€β”€ AggregationHOW.rakumod    # Metaclass for aggregations
    β”œβ”€β”€ ProjectionIdContainer.rakumod  # ID introspection
    └── EventHandlerContainer.rakumod  # Event handler introspection

Next Steps