Files
k-frame/docs/adr/0001-event-driven-cqrs.md
Gabriel Kaszewski 6ad76b98a2 add domain glossary, design spec, and ADRs
CONTEXT.md: domain model with entities (WidgetConfig, DataSource, LayoutPreset),
value objects (Layout, LayoutNode, KeyMapping, WidgetState, Sizing),
architecture decisions (CQRS, static dispatch, postcard), client domain model,
and design constraints.
2026-06-18 18:05:19 +02:00

1.4 KiB

0001 — Event-driven CQRS

Status: accepted Date: 2026-06-18

Context

K-Frame has a natural write/read split: the write model is config (widgets, data sources, layout) mutated via web UI, the read model is runtime state (current widget data, active layout) pushed to display clients. We need a mechanism to bridge the two — when config changes, runtime behavior must update (restart polling loops, push new layout to clients).

Decision

Full event-driven CQRS. Commands mutate config and emit domain events. The read side projects current state from events and DataSource poll results. Events drive side effects: restarting poll loops, pushing updates to connected clients.

Alternatives considered

Imperative approach — commands mutate config, then application layer imperatively calls "restart poll loop" / "push to clients." Simpler, but tangles command handling with side-effect orchestration. Adding new reactions to config changes requires modifying command handlers.

Consequences

  • Clean separation: command handlers only mutate config and emit events, never trigger side effects directly.
  • New reactions to config changes are just new event listeners — no command handler modification.
  • More moving parts than the imperative approach — event bus, event handlers, projections.
  • Events are in-memory only (no event store / event sourcing). This is CQRS, not ES.