Task: Wire NATS eventing templates into codegen and generate DB-write-to-NATS integration tests
Table of Contents
This page documents a task in the Port trading instruments to codegen story. It captures the goal, current status, acceptance, and any notes or results.
Goal
Originally scoped as "wire the NATS eventing templates into codegen"
— investigation found that facet (ores.cpp.nats-eventing /
ores.cpp.nats-event-registrar) already exists, is already wired
into the physical-space graph's default "supported set", and is
already proven live (purpose_type, PR #1451/#1459; every other
refdata entity too). The real gap: the 6 already-converted trading
instrument entities were never generated through the graph's true
default set (whatever command was actually used for their
conversion, it wasn't the documented =–address ores.cpp=/no-address
form), so they're silently missing eventing, request/response
messaging, and presentation-history facets the resolver says they're
entitled to. Revised goal, three parts, in order:
- Regenerate the 6 already-converted trading instrument entities
through the true default "supported set" (no
--addressrestriction), closing the gap. Eventing and presentation are clean additive gaps; request/response messaging collides with a pre-existing hand-craftedsave_*path per entity (same struct, same subject, same service call) — delete the hand-crafted duplicate and adopt the generated registrar instead. - Fix the
ores.cpp.presentation.history_field_mappertemplate, the one facet that never learned thehas_identity_group=/ =has_audit_groupnested-struct branching every other facet (domain, mapper, repository, service) already has — bring it to parity rather than special-case trading. - Add a new test facet that generates the "write entity, observe
its NATS entity-changed notification" integration test proven by
hand in
business_unit_eventing_integration_tests.cpp, so every eventing-enabled entity gets this regression coverage for free.
Explicitly out of scope for this task (filed separately once this is
proven): migrating refdata and any other flat-generated component to
the nested identity=/=audit shape, so the flat branches in every
facet template can eventually be deleted and the whole codebase
converges on one entity shape.
Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Port trading instruments to codegen |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-08-06 |
Acceptance
- All 6 already-converted trading instrument entities
(
equity_position_instrument,equity_variance_swap_instrument,fx_forward_instrument,equity_forward_instrument,fx_accumulator_instrument,fx_vanilla_option_instrument) regenerated through the true default supported set; every changed file diffed per standing policy, no orphaned hand-crafted files left behind. - Each entity's hand-crafted
save_<entity>_instrument_request/ responsestruct pair + handler method + queue-subscribe line deleted and replaced by the generated per-entity registrar (list/save/history/remove). ores.trading.core'sCMakeLists.txtgains theores.diff.libdependency the presentation facet needs (mirroring refdata).ores.cpp.presentation.history_field_mappertemplate fixed to branch onhas_identity_group=/=has_audit_groupexactly like the mapper/repository/service templates already do — no more conditional deletion of generated output to work around it.- Each entity's generated eventing registrar wired into
ores.trading.service'sapplication.cppeventing pipeline; each entity's generated request/response registrar wired into the relevantregistrar_<asset-class>.cpp. - Second regen pass on every touched entity produces zero further diff (standard codegen drift check).
- Full build + affected ctest suites (trading.*, ore.service, refdata.* untouched) green before PR.
- New integration-test facet generates a Catch2 test matching the
shape of
business_unit_eventing_integration_tests.cpp, parameterised per entity, wired into the component's testscomponent_files.cmake. - A follow-up task filed (not implemented here) to migrate refdata
and any other flat-generated component to the nested
identity=/=auditshape.
Plan
- Fix
ores.cpp.presentation.history_field_mapper_impl.org(tangles tocpp_history_field_mapper.cpp.mustache): branch primary-key, per-column, and audit-block emission onhas_identity_group=/ =has_audit_group— same mechanismcpp_domain_type_mapper.cpp.mustachealready uses (v.identity.xxx=/=v.audit.xxxvs flat). Retangle viacompass build --direct tangle_codegen_templates, diff the tangled.mustacheoutput. - Prove it on
equity_position_instrument: restore the presentation facet output (regenerate--address ores.cpp.presentation), confirm it now compiles against the nested domain shape. - Finish
equity_position_instrumentend to end: delete its hand-craftedsave_equity_position_instrument_request/response(ininstrument_protocol.hpp), deletetyped_equity_instrument_handler::save_position+ its queue-subscribe line inregistrar_equity.cpp, wire the generated registrar in instead; wire the generated event registrar intoapplication.cpp; fix any other hand-crafted consumer of the deleted struct (found:ores.ore/service/.../ore_import_execute_handler.cpp, needs the generated protocol header included instead); addores.diff.libtoores.trading.core'sCMakeLists.txt; regenerate CMake component file lists; build + test; diff every changed file; commit. - Repeat step 3 for the other 5 entities, one at a time (mechanical once the template fix and pattern are proven), each its own commit.
- Design and add the eventing-integration-test facet (parameterise
the proven
business_unit_eventing_integration_tests.cpppattern), generate it for at least one trading entity now that trading has real eventing wired, wire intocomponent_files.cmake. - File the refdata-migration follow-up task; do not implement it here.
Notes
Test Scenarios
Manual QA scenarios (scaffolded via compass add test_scenario, run
through the QA Validation Runner panel) that verify this task. Link
new ones here as they're created; the scenario doc itself links back
via its "Verifies task" field.
| Scenario | State | Notes |
|---|---|---|
PRs
| PR | Title |
|---|---|
| #1896 | [codegen,trading,ci] Close the eventing/messaging/presentation gap and add the eventing integration-test facet |
Review
| # | Comment summary | File | Decision | Notes |
|---|---|---|---|---|
| 1 | CI NATS readiness poll doesn't fail fast if nats-server never starts | .github/workflows/continuous-*.yml, nightly-linux.yml | Accepted | Added explicit exit 1 with a clear error after the poll loop, all 4 files |
| 2 | postgres_event_source::start() appends to registered_entities_ without clearing first | projects/ores.eventing/core/src/service/postgres_event_source.cpp | Accepted | Added registered_entities_.clear() at the top of start() |
| 3 | Include ordering not alphabetical in several touched files (paper cut, would be auto-fixed by nightly-format) | 6 files across ores.trading/ores.qt/ores.ore | Accepted | Ran clang-format on all 6 rather than waiting for nightly-format |
Result
Delivered all three revised-goal parts, plus two discoveries fixed along the way:
- Regenerated all 6 already-converted trading instrument entities
(
equity_position_instrument,equity_variance_swap_instrument,fx_forward_instrument,equity_forward_instrument,fx_accumulator_instrument,fx_vanilla_option_instrument) through the true default codegen supported set, closing the eventing/messaging/presentation gap; each entity's hand-crafted duplicatesave_*struct/handler/subscription deleted in favour of the generated registrar. Every file diffed, zero drift on second regen, one commit per entity. - Fixed
ores.cpp.presentation.history_field_mapperto branch onhas_identity_group=/=has_audit_grouplike every other C1202-aware facet — it was the one holdout still assuming a flat entity shape. - Added the new
ores.cpp.eventing-integration-testfacet (opt-in): generates a per-entity Catch2 test proving the DB-write -> pg_notify -> postgres_event_source -> event_bus -> NATS-publish chain end to end, no mocks. Enabled and proven (standalone run against live Postgres + NATS, 3/3 assertions each) on all 6 trading instrument entities. - Discovered and fixed: none of the three CI platforms
(continuous-linux/macos/windows, plus nightly-linux) actually
started a NATS server — only installed/downloaded the binary. Was
latent until this task's tests needed a live NATS; fixed by
starting
nats-serverwith the configcompass env configurealready generates, on all four affected workflows. - Filed a follow-up task (Migrate all codegen entities to the nested identity/audit struct shape) to eventually converge every entity (refdata included) on the C1202 shape and drop the flat branches everywhere.
Full build + full ctest suite (71/71) green before raising the PR.