Skip to content

Commit cf4de66

Browse files
authored
fix(catalog): updates errors in remote implementation (#551)
`LoadDataStoreFromCatalog` should not produce an error when fetching parts of the datastore for a specific domain environment if no records are returned. The implementation treats `ErrAddressRefNotFound`, `ErrChainMetadataNotFound`, `ErrContractMetadataNotFound`, and `ErrEnvMetadataNotSet` as valid cases of an empty datastore. This is useful when a domain environment has no data during the first execution. However, the remote catalog implementation fails to return `ErrAddressRefNotFound`, `ErrChainMetadataNotFound`, `ErrContractMetadataNotFound`, and `ErrEnvMetadataNotSet` correctly, causing `LoadDataStoreFromCatalog` to fail when no records are found.
1 parent 1b9e949 commit cf4de66

9 files changed

Lines changed: 236 additions & 104 deletions
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"chainlink-deployments-framework": patch
3+
---
4+
5+
fix(catalog): updates errors in remote implementation

datastore/catalog/remote/address_ref_store.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,17 @@ func (s *catalogAddressRefStore) Fetch(_ context.Context) ([]datastore.AddressRe
156156
}
157157

158158
// Check for errors in the response
159-
if err := parseResponseStatus(response.Status); err != nil {
160-
return nil, fmt.Errorf("fetch address refs failed: %w", err)
159+
if statusErr := parseResponseStatus(response.Status); statusErr != nil {
160+
st, sterr := parseStatusError(statusErr)
161+
if sterr != nil {
162+
return nil, sterr
163+
}
164+
165+
if st.Code() == codes.NotFound {
166+
return nil, datastore.ErrAddressRefNotFound
167+
}
168+
169+
return nil, fmt.Errorf("fetch address refs failed: %w", statusErr)
161170
}
162171

163172
// Extract the address find response

datastore/catalog/remote/address_ref_store_test.go

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func TestCatalogAddressRefStore_Get(t *testing.T) {
5959
t.Run(tt.name, func(t *testing.T) {
6060
t.Parallel()
6161
// Create a fresh store for each test case to avoid concurrency issues
62-
store := setupTestStore(t)
62+
store := setupTestStore(t, "test-domain", "catalog_testing")
6363

6464
key := tt.setup(store)
6565

@@ -116,7 +116,7 @@ func TestCatalogAddressRefStore_Add(t *testing.T) {
116116
t.Run(tt.name, func(t *testing.T) {
117117
t.Parallel()
118118
// Create a fresh store for each test case to avoid concurrency issues
119-
store := setupTestStore(t)
119+
store := setupTestStore(t, "test-domain", "catalog_testing")
120120

121121
addressRef := tt.setup(store)
122122

@@ -197,7 +197,7 @@ func TestCatalogAddressRefStore_Update(t *testing.T) {
197197
t.Run(tt.name, func(t *testing.T) {
198198
t.Parallel()
199199
// Create a fresh store for each test case to avoid concurrency issues
200-
store := setupTestStore(t)
200+
store := setupTestStore(t, "test-domain", "catalog_testing")
201201

202202
addressRef := tt.setup(store)
203203

@@ -272,7 +272,7 @@ func TestCatalogAddressRefStore_Upsert(t *testing.T) {
272272
t.Run(tt.name, func(t *testing.T) {
273273
t.Parallel()
274274
// Create a fresh store for each test case to avoid concurrency issues
275-
store := setupTestStore(t)
275+
store := setupTestStore(t, "test-domain", "catalog_testing")
276276

277277
addressRef := tt.setup(store)
278278

@@ -288,7 +288,7 @@ func TestCatalogAddressRefStore_Upsert(t *testing.T) {
288288

289289
func TestCatalogAddressRefStore_Delete(t *testing.T) {
290290
t.Parallel()
291-
store := setupTestStore(t)
291+
store := setupTestStore(t, "", "")
292292

293293
version := semver.MustParse("1.0.0")
294294
key := datastore.NewAddressRefKey(12345, "LinkToken", version, "test")
@@ -309,11 +309,17 @@ func TestCatalogAddressRefStore_FetchAndFilter(t *testing.T) {
309309
setup func(store *catalogAddressRefStore) (datastore.AddressRef, datastore.AddressRef)
310310
createFilter func(addressRef1, addressRef2 datastore.AddressRef) datastore.FilterFunc[datastore.AddressRefKey, datastore.AddressRef]
311311
minExpected int
312+
expectError bool
313+
errorType error
314+
domain string
315+
environment string
312316
verify func(t *testing.T, results []datastore.AddressRef, addressRef1, addressRef2 datastore.AddressRef)
313317
}{
314318
{
315-
name: "fetch_all",
316-
operation: "fetch",
319+
name: "fetch_all",
320+
operation: "fetch",
321+
domain: "test-domain",
322+
environment: "catalog_testing",
317323
setup: func(store *catalogAddressRefStore) (datastore.AddressRef, datastore.AddressRef) {
318324
// Setup test data with unique chain selectors
319325
addressRef1 := newRandomAddressRef()
@@ -354,8 +360,10 @@ func TestCatalogAddressRefStore_FetchAndFilter(t *testing.T) {
354360
},
355361
},
356362
{
357-
name: "filter_by_chain_selector",
358-
operation: "filter",
363+
name: "filter_by_chain_selector",
364+
operation: "filter",
365+
domain: "test-domain",
366+
environment: "catalog_testing",
359367
setup: func(store *catalogAddressRefStore) (datastore.AddressRef, datastore.AddressRef) {
360368
// Setup test data with unique chain selectors
361369
addressRef1 := newRandomAddressRef()
@@ -390,8 +398,10 @@ func TestCatalogAddressRefStore_FetchAndFilter(t *testing.T) {
390398
},
391399
},
392400
{
393-
name: "filter_by_address",
394-
operation: "filter",
401+
name: "filter_by_address",
402+
operation: "filter",
403+
domain: "test-domain",
404+
environment: "catalog_testing",
395405
setup: func(store *catalogAddressRefStore) (datastore.AddressRef, datastore.AddressRef) {
396406
// Setup test data with unique addresses
397407
addressRef1 := newRandomAddressRef()
@@ -418,8 +428,10 @@ func TestCatalogAddressRefStore_FetchAndFilter(t *testing.T) {
418428
},
419429
},
420430
{
421-
name: "filter_by_contract_type",
422-
operation: "filter",
431+
name: "filter_by_contract_type",
432+
operation: "filter",
433+
domain: "test-domain",
434+
environment: "catalog_testing",
423435
setup: func(store *catalogAddressRefStore) (datastore.AddressRef, datastore.AddressRef) {
424436
// Setup test data with different contract types
425437
addressRef1 := newRandomAddressRef()
@@ -447,14 +459,27 @@ func TestCatalogAddressRefStore_FetchAndFilter(t *testing.T) {
447459
}
448460
},
449461
},
462+
{
463+
name: "fetch_not_found",
464+
operation: "fetch",
465+
setup: func(store *catalogAddressRefStore) (datastore.AddressRef, datastore.AddressRef) {
466+
return datastore.AddressRef{}, datastore.AddressRef{}
467+
},
468+
createFilter: nil,
469+
minExpected: 0,
470+
expectError: true,
471+
errorType: datastore.ErrAddressRefNotFound,
472+
domain: "empty-domain-for-testing",
473+
environment: "empty-env-for-testing",
474+
},
450475
}
451476

452477
for _, tt := range tests {
453478
t.Run(tt.name, func(t *testing.T) {
454479
t.Parallel()
455-
// Create a fresh store for each test case to avoid concurrency issues
456-
store := setupTestStore(t)
457480

481+
// Create a fresh store for each test case to avoid concurrency issues
482+
store := setupTestStore(t, tt.domain, tt.environment)
458483
addressRef1, addressRef2 := tt.setup(store)
459484

460485
var results []datastore.AddressRef
@@ -473,10 +498,18 @@ func TestCatalogAddressRefStore_FetchAndFilter(t *testing.T) {
473498
}
474499

475500
// Verify
476-
require.NoError(t, err)
477-
require.GreaterOrEqual(t, len(results), tt.minExpected)
478-
if tt.verify != nil {
479-
tt.verify(t, results, addressRef1, addressRef2)
501+
if tt.expectError {
502+
require.Error(t, err)
503+
if tt.errorType != nil {
504+
require.ErrorIs(t, err, tt.errorType)
505+
}
506+
require.Nil(t, results)
507+
} else {
508+
require.NoError(t, err)
509+
require.GreaterOrEqual(t, len(results), tt.minExpected)
510+
if tt.verify != nil {
511+
tt.verify(t, results, addressRef1, addressRef2)
512+
}
480513
}
481514
})
482515
}
@@ -576,16 +609,17 @@ func TestCatalogAddressRefStore_ConversionHelpers(t *testing.T) {
576609
t.Run(tt.name, func(t *testing.T) {
577610
t.Parallel()
578611
// Create a fresh store for each test case to avoid concurrency issues
579-
store := setupTestStore(t)
612+
store := setupTestStore(t, "test-domain", "catalog_testing")
580613

581614
tt.test(t, store)
582615
})
583616
}
584617
}
585618

586619
// setupTestStore creates a real gRPC client connection to a local service
587-
func setupTestStore(t *testing.T) *catalogAddressRefStore {
620+
func setupTestStore(t *testing.T, domain, environment string) *catalogAddressRefStore {
588621
t.Helper()
622+
589623
// Get gRPC address from environment or use default
590624
address := os.Getenv("CATALOG_GRPC_ADDRESS")
591625
if address == "" {
@@ -614,8 +648,8 @@ func setupTestStore(t *testing.T) *catalogAddressRefStore {
614648

615649
// Create store
616650
store := newCatalogAddressRefStore(catalogAddressRefStoreConfig{
617-
Domain: "test-domain",
618-
Environment: "catalog_testing",
651+
Domain: domain,
652+
Environment: environment,
619653
Client: catalogClient,
620654
})
621655

datastore/catalog/remote/chain_metadata_store.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,17 @@ func (s *catalogChainMetadataStore) Fetch(_ context.Context) ([]datastore.ChainM
209209
}
210210

211211
// Check for errors in the response
212-
if err := parseResponseStatus(resp.Status); err != nil {
213-
return nil, fmt.Errorf("fetch chain metadata failed: %w", err)
212+
if statusErr := parseResponseStatus(resp.Status); statusErr != nil {
213+
st, sterr := parseStatusError(statusErr)
214+
if sterr != nil {
215+
return nil, sterr
216+
}
217+
218+
if st.Code() == codes.NotFound {
219+
return nil, fmt.Errorf("%w: %s", datastore.ErrChainMetadataNotFound, statusErr.Error())
220+
}
221+
222+
return nil, fmt.Errorf("fetch chain metadata failed: %w", statusErr)
214223
}
215224

216225
findResp := resp.GetChainMetadataFindResponse()

0 commit comments

Comments
 (0)