ores.cpp.history-provider-registrar
Table of Contents
This page is the node for the ores.cpp.history-provider-registrar
facet of the codegen template library, part of the
ores.cpp
technical space. Each archetype
below is documented, and holds its mustache source, in its own
linked page. This page is the facet-level summary and the routing
table to them.
1. Summary
Two templates forming the per-entity history-provider registrar pair.
The header declares register_<entity>_history_provider(). The
implementation builds the entity's history provider and registers it
into the ores::history::service::dispatch_registry the caller
passes in. The provider reads the entity's version history through
its service and renders each version through its field mapper. The
per-component service registrar delegates to each per-entity
registrar, so a compile failure in one entity's provider cannot block
registration of the rest. Consumed by the default (no --address)
generation set for every domain_entity.
2. The ores.cpp.history-provider-registrar facet
Projects the entity model onto its generic-history registration
surface: the entity_type key the generic history.v1.get subject
dispatches on, the service read that produces the version history,
and the field mapper that renders each version for display. It
consumes the same domain_entity model and the same
presentation::render_<entity>_fields mapper the
ores.cpp.presentation
facet emits. It derives its entity_type key identically to the
entity_name the
notify_trigger SQL facet
stamps on each row change (product_component_entity_singular), so
the two sides of the pipeline can never drift out of sync.
2.1. Junctions
A junction is stored with its history: each link has a version, an author, a
reason and a validity range, and a closing ends the range and deletes nothing.
Until a junction asked for it, nothing read that history back. A junction model
states :history: true in its * Flags to get the surface below. It is opt-in,
because a provider nothing wires into its component's registrar is dead code.
- A link has two keys, so a provider cannot be read by one link's id. A junction's
provider is read by the id of its parent side (the side that states
:list_by:, the left when both or neither does) and answers every version of every link of that parent, closed links included. The facet adds the repository readread_all_by_<parent>, which returns a<junction>_history_row. - The history row holds the domain type beside
closed_at, and the actor and the time flat, which is what the history builder reads. The domain type is final, so the row composes it. A link is closed by ending its validity, not by writing a version, so a version that ended because the link was closed carriesclosed_at, and a version that a later version replaced does not. The store records when a link ended and not who ended it, so a closing has no author. - The field mapper names the link by both keys in its first field,
ID, so the versions of one link pair up in a stream that holds many. The provider numbers and diffs each link on its own, because a version number is a link's. - The provider needs the junction's own read code
(
<component>::<name>:read), or the code the model names with:history_read_permission:. A history holds every version of the rows its reads serve, so it must not be easier to read than they are. - A junction column is rendered by type. A type the table in
core.py(_HISTORY_VALUE_EXPRESSIONS) does not name is refused when the model is generated, so a history never leaves a field out without saying so.
The per-component registrar.cpp still lists each provider by hand. Add the
include and the call when a junction states :history: true.
Replaces the pattern of hand-wiring one ~10-line
register_history_provider() lambda per entity directly into each
component's registrar.cpp. That hand-maintained surface has already
drifted: refdata's registrar registers only 53 of its 64
mapper-bearing entities. A small per-component aggregator (not
generated; it mirrors ores::refdata::core::messaging::registrar)
calls each generated per-entity function, the same way it already
calls the CRUD register_<entity>_handlers() functions. refdata's
registrar keeps its current 53 calls, so the registered key set is
unchanged. The 11 mapper-bearing entities with no provider today stay
unregistered, with identical runtime behaviour, until their own
wiring work adds them.
3. Archetypes
| Archetype | Description |
|---|---|
| ores.cpp.history-provider-registrar.history_provider_registrar_header | Per-entity history-provider registrar header declaring register_<entity>_history_provider(). |
| ores.cpp.history-provider-registrar.history_provider_registrar_implementation | Per-entity history-provider registrar implementation registering the provider body into the dispatch registry. |
4. See also
- ores.cpp.presentation — the mapper this facet's provider renders through.
- Entity-composed registrars — the architecture meta-pattern this facet is the history instance of.
- ores.cpp.nats-sub-registrar — the request/response registrar pair this facet sits alongside in
.coremessaging. - Codegen template library — the groups overview.