feat: sync operator app skeleton - #16
Conversation
Adds the apps/syncoperator module: config, store, automation host and health, ingesting the MemberTraffic purchases the operator observes for its own synchronizer and holding the sequencer admin connection the reconciliation will grant on. Ingestion is deliberately not filtered by the node's own migration id, since a registered synchronizer is pinned to migration id 0. Signed-off-by: sadiq1971 <[email protected]>
dea0d60 to
bf74782
Compare
| } | ||
| } | ||
|
|
||
| class DbSyncOperatorStoreTest |
There was a problem hiding this comment.
This test never actually runs: CI picks tests from the checked-in test-full-class-names-*.log lists, and this class is in none of them (checked both without-canton shard logs on this run — zero mentions). The lists are generated by sbt updateTestConfigForParallelRuns, and static_tests verifies they're current — but that verify step never ran here because the same sbt command died earlier at scalafmtCheck, so one red masked the other. Fixing only the formatting will make static_tests fail again on the stale lists. Suggest one pass: sbt scalafmtAll updateTestConfigForParallelRuns and commit both results — the task slots this class into test-full-class-names-non-integration.log (the without-canton group), and since the PR notes it hasn't run locally either, that run in CI would be this test's first execution anywhere.
| MultiDomainAcsStore.SimpleContractFilter( | ||
| key.operatorParty, | ||
| Map( | ||
| // Not filtered by this node's own migration id, unlike the SV store. A registered |
There was a problem hiding this comment.
Good call making this a payload check against 0 rather than the node's migration id, and saying why in the comment — this is exactly the canton-network#60 bug fenced off at the new store's front door, with the test cases to hold it.
| // The sequencers of the synchronizer this node serves. A single entry is the expected | ||
| // configuration; the field is a sequence so that a BFT synchronizer, which needs one reconciler | ||
| // per sequencer, does not require a config migration. | ||
| case class SyncOperatorSynchronizerConfig( |
There was a problem hiding this comment.
Nice touch that the config is already a list of sequencers while the app enforces exactly one — matches the one-reconciler-per-sequencer BFT shape you documented on #15, and spares a config migration later.
What this does
apps/syncoperatormodule, modelled onapps/splitwell: config, store, automation host, metrics, bootstrap, health.SyncOperatorStoreingestsMemberTrafficwhere this operator is the observer, and exposesgetTotalPurchasedMemberTraffic(member)off an indexed column, asDbSvDsoStoredoes.SyncOperatorAppconnects to Scan and its own sequencer, and refuses to start if that sequencer does not serve the configured synchronizer, rather than leaving a miswired node to discover it one purchase at a time.sync_operator_acs_storetable and twoSpliceDbLockCounters.How it's verified
apps-syncoperator/compile,Test/compileandscalafmtCheckpass, as doapps-commonandapps-sv.SyncOperatorStoreTestcovers the filter: sums across purchases, keeps members apart, and ignores purchases for another synchronizer, another operator, no operator, and a non-zero migration id. It needs Postgres viaSplicePostgresTestand has not been run locally.Not covered: that the store survives a decentralized-synchronizer migration without dropping records. That is part of the acceptance for canton-network#35 and needs a fixture that changes the migration id mid-test.
Tracked in
Implements P2-E5.2. Unblocks P2-E5.3, which also needs P2-E5.1 (#15 here). Relies on the migration-id policy in P2-E1.5.