Skip to content

feat: sync operator app skeleton - #16

Open
sadiq1971 wants to merge 1 commit into
feat/dedicated-syncfrom
feat/sync-operator-node
Open

feat: sync operator app skeleton#16
sadiq1971 wants to merge 1 commit into
feat/dedicated-syncfrom
feat/sync-operator-node

Conversation

@sadiq1971

@sadiq1971 sadiq1971 commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

What this does

  • New apps/syncoperator module, modelled on apps/splitwell: config, store, automation host, metrics, bootstrap, health.
  • SyncOperatorStore ingests MemberTraffic where this operator is the observer, and exposes getTotalPurchasedMemberTraffic(member) off an indexed column, as DbSvDsoStore does.
  • SyncOperatorApp connects 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.
  • New sync_operator_acs_store table and two SpliceDbLockCounters.

How it's verified

apps-syncoperator/compile, Test/compile and scalafmtCheck pass, as do apps-common and apps-sv.

SyncOperatorStoreTest covers 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 via SplicePostgresTest and 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.

@sadiq1971 sadiq1971 changed the title feat: sync operator app skeleton (Scala) feat: sync operator app skeleton Aug 19, 2026
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]>
}
}

class DbSyncOperatorStoreTest

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants