docs: add module documentation in AsciiDoc with PlantUML diagrams
Generated by per-group subagents covering all 52 modules across: core (18), infrastructure (10), apps (5), interfaces (3), plugins (7), testing (9) Documentation format: - AsciiDoc (.adoc) files in docs/modules/<group>/ - PlantUML (.puml) files in docs/diagrams/ - .adoc files reference diagrams via include:: directives Each doc covers: purpose, responsibilities, non-responsibilities, key types, event flow, integration points, invariants, PlantUML diagram, known issues, and open questions.
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
= infra-persistence
|
||||
|
||||
== purpose
|
||||
|
||||
Provides concrete `EventStore` implementations for persisting and replaying the event log. Supports in-memory storage (for testing and ephemeral sessions) and SQLite-backed durable storage. Also provides a live artifact repository that subscribes to events and maintains an up-to-date in-memory view of artifact state per session.
|
||||
|
||||
== responsibilities
|
||||
|
||||
* Implement the `EventStore` interface for both transient and durable storage
|
||||
* Enforce duplicate event ID detection and sequence ordering
|
||||
* Provide reactive subscriptions via `Flow<StoredEvent>` per session and globally
|
||||
* Maintain an artifact state projection that stays current via event subscription
|
||||
* Support transactional batch appends for atomic event persistence
|
||||
|
||||
== non-responsibilities
|
||||
|
||||
* Does not define event serialization — uses `JsonEventSerializer` from `core:events`
|
||||
* Does not implement CAS content-addressable storage — that belongs to `infra:artifacts-cas`
|
||||
* Does not handle event compaction or retention
|
||||
* Does not implement cross-session querying beyond `allSessionIds()`
|
||||
|
||||
== key types
|
||||
|
||||
=== InMemoryEventStore
|
||||
* **kind**: class
|
||||
* **purpose**: Thread-safe, in-memory event store backed by `ConcurrentHashMap`. Supports duplicate detection via `seenEventIds` set and session-scoped sequence numbers.
|
||||
* **fields**: `streams` (per-session event lists), `sequences` (per-session sequence counters), `globalSeq` (global counter), `seenEventIds` (dedup set)
|
||||
|
||||
=== SqliteEventStore
|
||||
* **kind**: class
|
||||
* **purpose**: Durable event store backed by a SQLite database with WAL mode. Uses JDBC directly. Emits events to reactive flows after append.
|
||||
* **fields**: `connection` (JDBC SQLite connection), `jsonSerializer` (serialization bridge), `artifactStore` (used for `flushBefore` coordination)
|
||||
|
||||
=== LiveArtifactRepository
|
||||
* **kind**: class
|
||||
* **purpose**: Subscribes to an `EventStore` per session and maintains an up-to-date in-memory `ConcurrentHashMap` of `ArtifactState` values. Supports lookup by session, stage, and artifact ID.
|
||||
* **fields**: `artifactCache` (session → artifactId → state), `stageIndex` (session → artifactId → stageId), `subscriptions` (session → coroutine Job), `projector` (reduces events to state)
|
||||
|
||||
=== JDBCHelper
|
||||
* **kind**: object
|
||||
* **purpose**: Utility providing `Connection.transaction()` inline helper with automatic commit/rollback.
|
||||
|
||||
== event flow
|
||||
|
||||
*Inbound:*
|
||||
* `ArtifactCreatedEvent`, `ArtifactValidatingEvent`, `ArtifactValidatedEvent`, `ArtifactRejectedEvent`, `ArtifactSupersededEvent`, `ArtifactArchivedEvent`, `ArtifactRelationshipAddedEvent` — consumed by `LiveArtifactRepository` to maintain artifact projections
|
||||
* `NewEvent` — appended to event stores via `append()` / `appendAll()`
|
||||
|
||||
*Outbound:*
|
||||
* `StoredEvent` — emitted via `Flow<StoredEvent>` subscriptions after each append
|
||||
|
||||
== integration points
|
||||
|
||||
* `core:events` — `EventStore`, `StoredEvent`, `NewEvent`, all artifact event payloads, `EventId`, `SessionId`
|
||||
* `core:artifacts` — `ArtifactProjector`, `ArtifactReducer`, `ArtifactState`, `ArtifactRepository`
|
||||
* `core:artifactstore` — `ArtifactStore` (used by `SqliteEventStore` for flush coordination)
|
||||
|
||||
== invariants
|
||||
|
||||
* Duplicate `eventId` values are rejected with an error
|
||||
* Session sequence numbers are strictly monotonic — violations throw `error()`
|
||||
* `InMemoryEventStore.append()` is synchronized per session for thread safety
|
||||
* `SqliteEventStore` wraps appends in a JDBC transaction and coordinates with `ArtifactStore.flushBefore()`
|
||||
* `LiveArtifactRepository` lazily subscribes on first query and never unsubscribes
|
||||
|
||||
== PlantUML diagram
|
||||
|
||||
[plantuml, infra-persistence, "png"]
|
||||
----
|
||||
include::../../diagrams/infra-persistence.puml[]
|
||||
----
|
||||
|
||||
|
||||
|
||||
|
||||
== known issues
|
||||
|
||||
* `SqliteEventStore` holds an open JDBC `Connection` for the lifetime of the application
|
||||
* No connection pooling or retry logic for SQLite busy conditions
|
||||
|
||||
== open questions
|
||||
|
||||
* Should event stores support snapshot-based recovery for long event streams?
|
||||
* Should there be a read-replica event store for projections to avoid write-contention?
|
||||
Reference in New Issue
Block a user