Documentation
¶
Overview ¶
Package composition is the ADR-0019 S4 composition root (endgame P4): the ONE place tq's runtime meets go-cqrs-lite's system/ package. It builds system.New over a durable sqlite engine at the projection home (<db>.readmodel.db) with an EMPTY domain BY DESIGN — the queue engine's fact journal IS the journal since S2, so system's own event adapter stays unused (no second source of truth; the split-brain gate of the archived composition map §3).
Viewpoint — Consumer: `tq serve` and future surfaces that need the platform runtime assembled; Concern: the S4 composition root — ONE system.New over the projection-home engine, close ordering for the surfaces that adopt it, and the sanctioned growth seams (timers, deciders, system.Lookup/metaengine queries); Non-goals: domain logic (the domain is EMPTY by design) and any second source of truth.
Cross-package map (lifecycle × concern): docs/architecture-understanding/2026-10-23_lifecycle-concern-grid.md
What the System owns here (the map's sanctioned shape):
- the projection-home engine (deployment decision, one DeploymentConfig place: swap sqlite -> postgres by editing Engines, never domain code);
- close ordering for the surfaces that adopt it (GracefulClose after the runactor actors stop — serve today, per §4c "adopt per surface");
- the growth seam: timers (§4a ruled: sweeper ticking STAYS runactor until a genuinely timer-shaped feature lands), deciders, and system.Lookup/metaengine query declarations attach to THIS root.
What it deliberately does NOT own: the tq queue.Store (S1's thin-driver seam, injected as today), the worker claim loops, the sweepers, and the readmodel's fold projector (a tq-side projection over the QUEUE journal; its collections live on the same projection-home file through their own metaengine Plan).
Index ¶
Constants ¶
const DefaultEngineName = "projections"
DefaultEngineName is the projection-home engine's deployment name.
Variables ¶
This section is empty.
Functions ¶
func New ¶
New composes the system root for one deployment. The sqlite queue database path decides the projection home (derived beside it) and the deployment's resolved sync tier drives the engine's pragmas — the config.Deployment is the ONE deployment description (ADR-0022 deployment lane); the projection home itself stays sqlite-embedded.
Types ¶
type ProjectionRuntime ¶ added in v0.3.4
type ProjectionRuntime struct {
Model *readmodel.Model
Host *readmodel.ProjectionHost
// contains filtered or unexported fields
}
ProjectionRuntime bundles the ADR-0019 S3 fold surfaces one serve run owns: the model, the poison-fact sidecar (nil when it could not be opened — warn-and-continue), and the managed projection host. Close tears them down in LIFO order (host stop+close, sidecar, model), the ordering the serve wiring previously hand-rolled with stacked defers.
func NewProjectionRuntime ¶ added in v0.3.4
func NewProjectionRuntime(ctx context.Context, src queue.Store, cfg config.Deployment) (*ProjectionRuntime, error)
NewProjectionRuntime composes the projection runtime for one deployment's projection home (derived beside cfg.DBPath) over the queue journal (src): elect the single folder through the projection home's fold lock (a bounded wait rides out transient holders; a lost election mounts the runtime READ-ONLY — model without host), then for the folder: open the ONE tq-owned engine for the projection home (the deployment's resolved pragma union — the single-opener seam, the composition root is the only tq constructor call site), open the model over it with a durable cursor, best-effort the DLQ sidecar beside it, and build the managed host wired with the sidecar. Starting stays the caller's job (Host.Start) so the runactor actor keeps its own lifecycle; on a build error nothing is left open.
func (*ProjectionRuntime) Close ¶ added in v0.3.4
func (r *ProjectionRuntime) Close() error
Close releases the runtime in reverse construction order: host stop and close, then the DLQ sidecar, then the model. Idempotent: each field is nil'd after release, so a second Close is a no-op (the serve wiring relies on this — the pump's deferred Close runs after cmdServe's).