Skip to main content

Register engine overview

Registers are Kandra's analytical/accounting layer — inventory balances, exchange rates, and similar running totals or event logs. See the practical guide's Creating a register for a task-oriented walkthrough; this page is the API-shape summary.

  • BalanceRegister<> (running totals) and the info-register family (InfoRegister/PeriodicInfoRegister/DocumentInfoRegister) are implemented and in active use.
  • TurnoverRegister<> exists as infrastructure but has no live consumer in the reference configuration yet.
  • Concurrency uses a manually-incremented Version optimistic-concurrency column with bounded retry (3 attempts) — a deliberate scope-down from a lock-free provider-specific atomic upsert, documented as such in techdebt/TECH_DEBT.md (TD-004).
  • Register writers are resolved only through ISubmitScope.GetWriter<TWriter>() inside a document behavior's OnSubmitAsync/OnDeleteAsync — never by ordinary constructor injection.
  • BuildEqualityPredicate() (generated, see Source Generators) on IRegisterDimensions<TSelf>, combined with DimensionPredicateBuilder, is the accepted compile-time-typed way to filter to just the touched dimension rows instead of loading a whole balance table — use this pattern anywhere in the register engine rather than reflection-based filtering.

Full design: see the platform's docs/kandra-register-engine-design.md and docs/1c-register-architecture.md.