You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Today cardano-rosetta-java runs as two Spring Boot services:
yaci-indexer — owns the JPA entities + repositories for block, transaction, address_utxo, metadata_reference_nft, ft_offchain_metadata, and all other yaci-store tables. This is the write side — it consumes Cardano node events and persists them via yaci-store's storage modules.
api — the Rosetta-spec HTTP endpoints. Reads the same tables the indexer writes, but because it doesn't pull in yaci-store's storage jars, it re-defines its own JPA entities and repositories that map to the same column names.
This means every yaci-store schema used by a Rosetta endpoint is duplicated:
Plus duplicate *Repository interfaces and, in some cases, duplicate custom native-SQL queries (e.g. the CIP-68 window-function batch query added in #730 exists both downstream in MetadataReferenceNftRepositoryCustom and upstream in yaci-store-assets-ext).
Why we can kill the duplication
yaci-store supports read-only mode via store.read-only-mode=true — listeners/processors/cron jobs are skipped, repositories are still registered, storage reader beans are still created. That's exactly the shape the Rosetta API needs.
With that knob, a single Spring Boot application — rosetta-app — can:
Run yaci-store in write mode (sync blocks from the node, populate all tables) on the indexer node(s)
Run the same application in read-only mode on the API node(s) — consuming yaci-store's Cip26StorageReader, Cip68StorageReader, AddressUtxoStorageReader, etc. directly without its own entity/repository layer
No behavioral difference for operators — the mode is a single config flag. Horizontal scaling is unchanged (you still run N api replicas + M indexer replicas, they just share the same jar).
Benefits
No more duplicate JPA entities. Schema changes in yaci-store stop being "downstream code must be manually updated" — they flow through the jar dependency.
Single build, single image. Operators deploy one rosetta-app jar with two config profiles instead of two separate artifacts.
Smaller surface for drift bugs. Right now a rename or column-type change in yaci-store-assets-ext can silently break the API's custom entities until runtime — there's no compile-time or build-time guardrail. After the merge, compilation against the yaci-store jar catches it.
Simpler CI. One module to test, not two.
Naming
The merged module will be called rosetta-app — a single Spring Boot application that runs either in Rosetta HTTP read mode (default) or in yaci-store write mode (indexer profile).
What PR #746 already completed (groundwork for this merge)
PR #746 moved index creation natively into yaci-indexer and established clean
ownership boundaries. The following is already done:
indexes package in yaci-indexer owns the full index lifecycle: IndexService, PgIndexService, NoOpIndexService, IndexCatalog, IndexesEndpoint, IndexStallIndicator
Single db-indexes.yaml in yaci-indexer drives both index creation and the
api's index readiness check (kept identical via IndexCatalogParityTest)
Index service migration (specific steps at merge time)
The api has its own parallel index monitoring stack that duplicates logic already
in the yaci-indexer's indexes package. At merge time, consolidate as follows:
1. Wire IndexService into SyncStatusService
// BEFORE — api's SyncStatusService@RequiredArgsConstructorpublicclassSyncStatusService {
privatefinalIndexCreationMonitorindexCreationMonitor;
...
booleanindexesNotReady = indexCreationMonitor.isCreatingIndexes();
}
// AFTER — direct injection of IndexService@RequiredArgsConstructorpublicclassSyncStatusService {
privatefinalIndexServiceindexService;
...
booleanindexesNotReady = indexService.getState() != IndexLifecycleState.READY;
}
getIndexCreationProgress() (used for detailed status) maps to indexService.getIndexStatus() → List<IndexItemStatus>, which is richer than
the old List<IndexCreationProgress> (4 always-null numeric fields).
2. Delete from api
Class / file
Replacement
IndexCreationMonitor (interface)
IndexService
PostgreSQLIndexCreationMonitor
PgIndexService
H2IndexCreationMonitor
NoOpIndexService
RosettaIndexConfig
IndexCatalog
api/.../config/db-indexes.yaml
Single copy in yaci-indexer
IndexCatalogParityTest
No longer two files to compare
Also remove the spring.config.import line from api's application.yaml:
# REMOVE this line
- classpath:config/db-indexes.yaml
3. Profile alignment
Both modules already use the same profile names — no changes needed:
Profile
yaci-indexer (keep)
api (delete)
h2, test-integration
NoOpIndexService
H2IndexCreationMonitor
everything else
PgIndexService
PostgreSQLIndexCreationMonitor
Scope of work
Create the new rosetta-app module by merging api and yaci-indexer
Add com.bloxbean.cardano:yaci-store-* dependencies to rosetta-app
Introduce a Spring profile indexer that enables write-mode yaci-store; default rosetta-app profiles set store.read-only-mode=true
Index service migration (detail above):
Wire IndexService into SyncStatusService
Delete IndexCreationMonitor + both implementations
Delete RosettaIndexConfig from api (getIndexCommands() was already dead code)
refactor: merge API and yaci-indexer into a single "rosetta-app" module
Ref: #731
Problem
Today cardano-rosetta-java runs as two Spring Boot services:
yaci-indexer— owns the JPA entities + repositories forblock,transaction,address_utxo,metadata_reference_nft,ft_offchain_metadata, and all other yaci-store tables. This is the write side — it consumes Cardano node events and persists them via yaci-store's storage modules.api— the Rosetta-spec HTTP endpoints. Reads the same tables the indexer writes, but because it doesn't pull in yaci-store's storage jars, it re-defines its own JPA entities and repositories that map to the same column names.This means every yaci-store schema used by a Rosetta endpoint is duplicated:
AddressUtxoEntity(api) ↔ yaci-store's utxo module entityBlockEntity/TxnEntity/TxInputEntity(api) ↔ yaci-store's blocks module entitiesPoolRegistrationEntity/PoolDelegationEntity/WithdrawalEntity(api) ↔ yaci-store staking moduleTokenMetadataEntity/TokenLogoEntity/MetadataReferenceNftEntity(api) ↔ yaci-store assets-ext entities — added in refactor: replace REST token registry with DB-based assets-ext reads #730Plus duplicate
*Repositoryinterfaces and, in some cases, duplicate custom native-SQL queries (e.g. the CIP-68 window-function batch query added in #730 exists both downstream inMetadataReferenceNftRepositoryCustomand upstream inyaci-store-assets-ext).Why we can kill the duplication
yaci-store supports read-only mode via
store.read-only-mode=true— listeners/processors/cron jobs are skipped, repositories are still registered, storage reader beans are still created. That's exactly the shape the Rosetta API needs.With that knob, a single Spring Boot application —
rosetta-app— can:Cip26StorageReader,Cip68StorageReader,AddressUtxoStorageReader, etc. directly without its own entity/repository layerNo behavioral difference for operators — the mode is a single config flag. Horizontal scaling is unchanged (you still run N api replicas + M indexer replicas, they just share the same jar).
Benefits
@Queryupstream). Post-merge we reuse upstream'sfindBySubjectsdirectly.rosetta-appjar with two config profiles instead of two separate artifacts.Naming
The merged module will be called
rosetta-app— a single Spring Boot application that runs either in Rosetta HTTP read mode (default) or in yaci-store write mode (indexer profile).What PR #746 already completed (groundwork for this merge)
PR #746 moved index creation natively into
yaci-indexerand established cleanownership boundaries. The following is already done:
indexespackage in yaci-indexer owns the full index lifecycle:IndexService,PgIndexService,NoOpIndexService,IndexCatalog,IndexesEndpoint,IndexStallIndicatorindex-appliersidecar deleted — Docker Compose file, Helm Job + ConfigMaptemplates,
apply-indexes.shshell script,jq/yqfrom Postgres Dockerfiledb-indexes.yamlin yaci-indexer drives both index creation and theapi's index readiness check (kept identical via
IndexCatalogParityTest)Index service migration (specific steps at merge time)
The api has its own parallel index monitoring stack that duplicates logic already
in the yaci-indexer's
indexespackage. At merge time, consolidate as follows:1. Wire
IndexServiceintoSyncStatusServicegetIndexCreationProgress()(used for detailed status) maps toindexService.getIndexStatus()→List<IndexItemStatus>, which is richer thanthe old
List<IndexCreationProgress>(4 always-null numeric fields).2. Delete from api
IndexCreationMonitor(interface)IndexServicePostgreSQLIndexCreationMonitorPgIndexServiceH2IndexCreationMonitorNoOpIndexServiceRosettaIndexConfigIndexCatalogapi/.../config/db-indexes.yamlyaci-indexerIndexCatalogParityTestAlso remove the
spring.config.importline from api'sapplication.yaml:3. Profile alignment
Both modules already use the same profile names — no changes needed:
h2,test-integrationNoOpIndexServiceH2IndexCreationMonitorPgIndexServicePostgreSQLIndexCreationMonitorScope of work
rosetta-appmodule by mergingapiandyaci-indexercom.bloxbean.cardano:yaci-store-*dependencies torosetta-appindexerthat enables write-mode yaci-store; defaultrosetta-appprofiles setstore.read-only-mode=trueIndexServiceintoSyncStatusServiceIndexCreationMonitor+ both implementationsRosettaIndexConfigfrom api (getIndexCommands()was already dead code)api/src/main/resources/config/db-indexes.yamlIndexCatalogParityTest*Entity+*Repositoryclasses with references to yaci-store's equivalents, module by module:yaci-store-utxoyaci-store-blocks+yaci-store-transactionyaci-store-stakingyaci-store-governanceyaci-store-epochyaci-store-assets-ext(blocked on refactor: replace REST token registry with DB-based assets-ext reads #730 release)application.propertiescontents intorosetta-appunder theindexerprofileapiandyaci-indexermodulesrosetta-appimage with two differentSPRING_PROFILES_ACTIVEvalues (indexervs default)rosetta-appbinaryDependencies
yaci-store-assets-extmust be released before the token-metadata portion can be cleaned up (currently consumed as a pre-release SNAPSHOT via refactor: replace REST token registry with DB-based assets-ext reads #730)Related
yaci-store-assets-ext+ duplicate JPA entities for CIP-26/CIP-68 metadata tables. Flagged in that PR as tech debt to be cleaned up by this refactor.index-appliersidecar with nativeyaci-indexerindex lifecycle; cleans up package/class naming. Groundwork for this merge.