Skip to content

Commit 802ddb7

Browse files
committed
feat(cmd): add catalog syncer
1 parent 0892ddc commit 802ddb7

6 files changed

Lines changed: 681 additions & 11 deletions

File tree

.changeset/loud-spiders-end.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
"chainlink-deployments-framework": major
3+
---
4+
5+
feat!: add catalog service integration for datastore operations
6+
7+
BREAKING CHANGES:
8+
- `EnvDir.MergeMigrationDataStore` now requires `context.Context` as first parameter and `datastore.CatalogStore` as last parameter
9+
- Signature changed from `MergeMigrationDataStore(migkey, timestamp string)` to `MergeMigrationDataStore(ctx context.Context, migkey, timestamp string, catalog datastore.CatalogStore)`
10+
11+
Features:
12+
- Add catalog service support for datastore management
13+
- Add `SyncDataStoreToCatalog` function to push entire local datastore to catalog
14+
- Add `MergeDataStoreToCatalog` function to merge migration datastores to catalog
15+
- All catalog operations are transactional to prevent data inconsistencies
16+
- Add `DatastoreType` configuration option to switch between `file` and `catalog` modes

datastore/catalog_syncer.go

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package datastore
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
)
8+
9+
// SyncDataStoreToCatalog pushes all data from a local DataStore to a remote CatalogStore within
10+
// a transaction. This ensures atomic updates - either all data is successfully synced or the
11+
// entire operation is rolled back on failure.
12+
//
13+
// This function is the inverse of LoadDataStoreFromCatalog - while that function reads from
14+
// catalog to local, this function writes from local to catalog.
15+
func SyncDataStoreToCatalog(ctx context.Context, localDS DataStore, catalog CatalogStore) error {
16+
return catalog.WithTransaction(ctx, func(ctx context.Context, txCatalog BaseCatalogStore) error {
17+
// Sync all address references to the catalog
18+
addressRefs, err := localDS.Addresses().Fetch()
19+
if err != nil {
20+
return fmt.Errorf("failed to fetch address references from local store: %w", err)
21+
}
22+
23+
for _, ref := range addressRefs {
24+
if upsertErr := txCatalog.Addresses().Upsert(ctx, ref); upsertErr != nil {
25+
return fmt.Errorf("failed to upsert address reference to catalog: %w", upsertErr)
26+
}
27+
}
28+
29+
// Sync all chain metadata to the catalog
30+
chainMetadata, err := localDS.ChainMetadata().Fetch()
31+
if err != nil {
32+
return fmt.Errorf("failed to fetch chain metadata from local store: %w", err)
33+
}
34+
35+
for _, metadata := range chainMetadata {
36+
key := NewChainMetadataKey(metadata.ChainSelector)
37+
if upsertErr := txCatalog.ChainMetadata().Upsert(ctx, key, metadata.Metadata); upsertErr != nil {
38+
return fmt.Errorf("failed to upsert chain metadata to catalog: %w", upsertErr)
39+
}
40+
}
41+
42+
// Sync all contract metadata to the catalog
43+
contractMetadata, err := localDS.ContractMetadata().Fetch()
44+
if err != nil {
45+
return fmt.Errorf("failed to fetch contract metadata from local store: %w", err)
46+
}
47+
48+
for _, metadata := range contractMetadata {
49+
key := NewContractMetadataKey(metadata.ChainSelector, metadata.Address)
50+
if upsertErr := txCatalog.ContractMetadata().Upsert(ctx, key, metadata.Metadata); upsertErr != nil {
51+
return fmt.Errorf("failed to upsert contract metadata to catalog: %w", upsertErr)
52+
}
53+
}
54+
55+
// Sync environment metadata to the catalog
56+
envMetadata, err := localDS.EnvMetadata().Get()
57+
if err != nil {
58+
// EnvMetadata might not be set, which is okay
59+
if !errors.Is(err, ErrEnvMetadataNotSet) {
60+
return fmt.Errorf("failed to fetch environment metadata from local store: %w", err)
61+
}
62+
// If it's ErrEnvMetadataNotSet, skip syncing env metadata
63+
return nil
64+
}
65+
66+
// Sync the environment metadata
67+
if setErr := txCatalog.EnvMetadata().Set(ctx, envMetadata.Metadata); setErr != nil {
68+
return fmt.Errorf("failed to set environment metadata in catalog: %w", setErr)
69+
}
70+
71+
return nil
72+
})
73+
}
74+
75+
// MergeDataStoreToCatalog merges data from a migration/changeset DataStore into the catalog
76+
// within a transaction. This is used after a migration/changeset execution to persist new
77+
// contract deployments and metadata to the catalog.
78+
func MergeDataStoreToCatalog(ctx context.Context, migrationDS DataStore, catalog CatalogStore) error {
79+
return catalog.WithTransaction(ctx, func(ctx context.Context, txCatalog BaseCatalogStore) error {
80+
// Merge all address references to the catalog
81+
addressRefs, err := migrationDS.Addresses().Fetch()
82+
if err != nil {
83+
return fmt.Errorf("failed to fetch address references from migration store: %w", err)
84+
}
85+
86+
for _, ref := range addressRefs {
87+
if upsertErr := txCatalog.Addresses().Upsert(ctx, ref); upsertErr != nil {
88+
return fmt.Errorf("failed to upsert address reference to catalog: %w", upsertErr)
89+
}
90+
}
91+
92+
// Merge all chain metadata to the catalog
93+
chainMetadata, err := migrationDS.ChainMetadata().Fetch()
94+
if err != nil {
95+
return fmt.Errorf("failed to fetch chain metadata from migration store: %w", err)
96+
}
97+
98+
for _, metadata := range chainMetadata {
99+
key := NewChainMetadataKey(metadata.ChainSelector)
100+
if upsertErr := txCatalog.ChainMetadata().Upsert(ctx, key, metadata.Metadata); upsertErr != nil {
101+
return fmt.Errorf("failed to upsert chain metadata to catalog: %w", upsertErr)
102+
}
103+
}
104+
105+
// Merge all contract metadata to the catalog
106+
contractMetadata, err := migrationDS.ContractMetadata().Fetch()
107+
if err != nil {
108+
return fmt.Errorf("failed to fetch contract metadata from migration store: %w", err)
109+
}
110+
111+
for _, metadata := range contractMetadata {
112+
key := NewContractMetadataKey(metadata.ChainSelector, metadata.Address)
113+
if upsertErr := txCatalog.ContractMetadata().Upsert(ctx, key, metadata.Metadata); upsertErr != nil {
114+
return fmt.Errorf("failed to upsert contract metadata to catalog: %w", upsertErr)
115+
}
116+
}
117+
118+
// Merge environment metadata to the catalog
119+
envMetadata, err := migrationDS.EnvMetadata().Get()
120+
if err != nil {
121+
if !errors.Is(err, ErrEnvMetadataNotSet) {
122+
return fmt.Errorf("failed to fetch environment metadata from migration store: %w", err)
123+
}
124+
125+
return nil
126+
}
127+
128+
// Merge the environment metadata (upsert semantics)
129+
if setErr := txCatalog.EnvMetadata().Set(ctx, envMetadata.Metadata); setErr != nil {
130+
return fmt.Errorf("failed to set environment metadata in catalog: %w", setErr)
131+
}
132+
133+
return nil
134+
})
135+
}

0 commit comments

Comments
 (0)