Skip to content

Commit 32b13c5

Browse files
authored
feat(cmd): add catalog syncer (#552)
This pull request introduces a new integration for catalog-based datastore management, allowing the system to use a remote catalog service for data persistence instead of local file storage. The changes are designed to be non-breaking, providing configuration options to select the desired backend and new CLI commands for migration and synchronization. Additionally, several mock implementations are added to support testing of the new functionality. **Catalog Service Integration & Data Management** * Added catalog service support for datastore management, enabling transactional operations and providing an alternative to local file storage. This includes a unified function (`MergeDataStoreToCatalog`) for both initial migration and ongoing merge operations, ensuring atomic updates and preventing data inconsistencies. [[1]](diffhunk://#diff-6183631702722fc2a3ddbc5ec91a559eb5bfcf1f062553cebe75f8e515e6eec7R1-R22) [[2]](diffhunk://#diff-25ea8888f88aec3194cfd2d4390d937364c653f876ed7901f7512012cbd4a9c6R1-R75) * Added a new CLI command `datastore sync-to-catalog` for migrating all local datastore data to the catalog service, supporting CI and operational workflows. **Testing & Mock Implementations** * Added mock implementations for address reference, chain metadata, and contract metadata stores to facilitate testing of catalog integration and datastore operations. These mocks support fetch, get, and filter operations for their respective data types. (`datastore/mock_address_ref_store_test.go` [[1]](diffhunk://#diff-0483d90cec93624656eff1726bc11354658127f5090b2a749711a57699ea69afR1-R201) `datastore/mock_chain_metadata_store_test.go` [[2]](diffhunk://#diff-e5c07878c88ed6de556788eae5b3250f4ec4904e2a700a26399dd056f523bb38R1-R201) `datastore/mock_contract_metadata_store_test.go` [[3]](diffhunk://#diff-516e47a714b875cf2f3d55628994f45e61a5061ecafe106c06589d4af8ca5141R1-R201) https://smartcontract-it.atlassian.net/browse/CLD-782
1 parent e84a39b commit 32b13c5

13 files changed

Lines changed: 2248 additions & 13 deletions

.changeset/loud-spiders-end.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
"chainlink-deployments-framework": minor
3+
---
4+
5+
feat: add catalog service integration for datastore operations
6+
7+
Features:
8+
- Add catalog service support for datastore management as alternative to local file storage
9+
- Add `MergeMigrationDataStoreCatalog` method for catalog-based datastore persistence
10+
- Existing `MergeMigrationDataStore` method continues to work for file-based storage (no breaking changes)
11+
- Add unified `MergeDataStoreToCatalog` function for both initial migration and ongoing merge operations
12+
- All catalog operations are transactional to prevent data inconsistencies
13+
- Add `DatastoreType` configuration option (`file`/`catalog`) in domain.yaml to control storage backend
14+
- Add new CLI command `datastore sync-to-catalog` for initial migration from file-based to catalog storage in CI
15+
- Add `SyncDataStoreToCatalog` method to sync entire local datastore to catalog
16+
- CLI automatically selects the appropriate merge method based on domain.yaml configuration
17+
- Catalog mode does not modify local files - all updates go directly to the catalog service
18+
19+
Configuration:
20+
- Set `datastore: catalog` in domain.yaml to enable catalog mode
21+
- Set `datastore: file` or omit the setting to use traditional file-based storage
22+
- CLI commands automatically detect the configuration and use the appropriate storage backend

datastore/catalog_syncer.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package datastore
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
)
8+
9+
// MergeDataStoreToCatalog merges data from a source DataStore (either full local state or migration-specific)
10+
// into a remote CatalogStore within a transaction. This ensures atomic updates - either all data is
11+
// successfully merged or the entire operation is rolled back on failure.
12+
//
13+
// This function serves two purposes:
14+
// 1. Initial migration: sync entire local datastore to catalog (full state push)
15+
// 2. Ongoing operations: merge migration/changeset artifacts into catalog (incremental updates)
16+
//
17+
// The operation is transactional to prevent partial failures that could lead to data inconsistencies.
18+
func MergeDataStoreToCatalog(ctx context.Context, sourceDS DataStore, catalog CatalogStore) error {
19+
return catalog.WithTransaction(ctx, func(ctx context.Context, txCatalog BaseCatalogStore) error {
20+
// Merge all address references to the catalog
21+
addressRefs, err := sourceDS.Addresses().Fetch()
22+
if err != nil {
23+
return fmt.Errorf("failed to fetch address references from source store: %w", err)
24+
}
25+
26+
for _, ref := range addressRefs {
27+
if upsertErr := txCatalog.Addresses().Upsert(ctx, ref); upsertErr != nil {
28+
return fmt.Errorf("failed to upsert address reference to catalog: %w", upsertErr)
29+
}
30+
}
31+
32+
// Merge all chain metadata to the catalog
33+
chainMetadata, err := sourceDS.ChainMetadata().Fetch()
34+
if err != nil {
35+
return fmt.Errorf("failed to fetch chain metadata from source store: %w", err)
36+
}
37+
38+
for _, metadata := range chainMetadata {
39+
key := NewChainMetadataKey(metadata.ChainSelector)
40+
if upsertErr := txCatalog.ChainMetadata().Upsert(ctx, key, metadata.Metadata); upsertErr != nil {
41+
return fmt.Errorf("failed to upsert chain metadata to catalog: %w", upsertErr)
42+
}
43+
}
44+
45+
// Merge all contract metadata to the catalog
46+
contractMetadata, err := sourceDS.ContractMetadata().Fetch()
47+
if err != nil {
48+
return fmt.Errorf("failed to fetch contract metadata from source store: %w", err)
49+
}
50+
51+
for _, metadata := range contractMetadata {
52+
key := NewContractMetadataKey(metadata.ChainSelector, metadata.Address)
53+
if upsertErr := txCatalog.ContractMetadata().Upsert(ctx, key, metadata.Metadata); upsertErr != nil {
54+
return fmt.Errorf("failed to upsert contract metadata to catalog: %w", upsertErr)
55+
}
56+
}
57+
58+
// Merge environment metadata to the catalog
59+
envMetadata, err := sourceDS.EnvMetadata().Get()
60+
if err != nil {
61+
if !errors.Is(err, ErrEnvMetadataNotSet) {
62+
return fmt.Errorf("failed to fetch environment metadata from source store: %w", err)
63+
}
64+
65+
return nil
66+
}
67+
68+
// Merge the environment metadata (upsert semantics)
69+
if setErr := txCatalog.EnvMetadata().Set(ctx, envMetadata.Metadata); setErr != nil {
70+
return fmt.Errorf("failed to set environment metadata in catalog: %w", setErr)
71+
}
72+
73+
return nil
74+
})
75+
}

0 commit comments

Comments
 (0)