diff --git a/fetch_test.go b/fetch_test.go index 18ca076..a973b67 100644 --- a/fetch_test.go +++ b/fetch_test.go @@ -13,6 +13,43 @@ import ( "github.com/viccon/sturdyc" ) +func TestGetOrFetchMissingRecordCacheAny(t *testing.T) { + t.Parallel() + + ctx := context.Background() + capacity := 5 + numShards := 2 + ttl := time.Minute + evictionPercentage := 10 + c := sturdyc.New[any](capacity, numShards, ttl, evictionPercentage, + sturdyc.WithNoContinuousEvictions(), + sturdyc.WithMissingRecordStorage(), + ) + + id := "1" + fetchObserver := NewFetchObserver(1) + fetchObserver.Err(sturdyc.ErrNotFound) + + // The first time we call Get, it should call the fetchFn to retrieve the value. + _, err := sturdyc.GetOrFetch(ctx, c, id, fetchObserver.Fetch) + if !errors.Is(err, sturdyc.ErrMissingRecord) { + t.Fatalf("expected missing record error, got %v", err) + } + + <-fetchObserver.FetchCompleted + fetchObserver.AssertFetchCount(t, 1) + fetchObserver.Err(sturdyc.ErrNotFound) + + // The second time we call Get, we should still get the missing record + _, err = sturdyc.GetOrFetch(ctx, c, id, fetchObserver.Fetch) + if !errors.Is(err, sturdyc.ErrMissingRecord) { + t.Fatalf("expected missing record error, got %v", err) + } + + // And only no more fetch should have been made + fetchObserver.AssertFetchCount(t, 1) +} + func TestGetOrFetch(t *testing.T) { t.Parallel() diff --git a/safe.go b/safe.go index ed33c30..5b6860e 100644 --- a/safe.go +++ b/safe.go @@ -36,6 +36,11 @@ func wrap[T, V any](fetchFn FetchFn[V]) FetchFn[T] { } func unwrap[V, T any](val T, err error) (V, error) { + if errors.Is(err, ErrMissingRecord) || errors.Is(err, ErrNotFound) { + var zero V + return zero, err + } + v, ok := any(val).(V) if !ok { return v, ErrInvalidType