diff --git a/internal/dao/query_find_create.go b/internal/dao/query_find_create.go index c83d43a8..11c05f8d 100644 --- a/internal/dao/query_find_create.go +++ b/internal/dao/query_find_create.go @@ -25,19 +25,13 @@ func FindCreateAction[T EntityHasIsEmpty]( createAction func() (T, error), ) (T, error) { result, err, _ := findCreateSingleFlightGroup.Do(key, func() (any, error) { - r, err := findAction() - if err != nil { - return nil, err - } - if r.IsEmpty() { - if r, err = createAction(); err != nil { - return nil, err - } + if r, err := findAction(); err != nil || !r.IsEmpty() { + return r, err } - return r, nil + return createAction() }) if err != nil { - log.Error("[FindCreate] ", err) + log.Errorf("[FindCreateAction] key: %s, error: %v", key, err) return *new(T), err } return result.(T), nil diff --git a/internal/dao/query_find_create_test.go b/internal/dao/query_find_create_test.go index 2533d9ca..7fe5b695 100644 --- a/internal/dao/query_find_create_test.go +++ b/internal/dao/query_find_create_test.go @@ -181,24 +181,22 @@ func TestFindCreateAction(t *testing.T) { t.Run("Concurrent FindCreateAction", func(t *testing.T) { var wg sync.WaitGroup - var result mockEntity + var atomicResult atomic.Value // Assume that Find and Create actions is Thread-safe + atomicResult.Store(mockEntity{}) findCreateFunc := func() (mockEntity, error) { return dao.FindCreateAction("key", func() (mockEntity, error) { // findAction - time.Sleep(10 * time.Millisecond) - return result, nil + time.Sleep(10 * time.Millisecond) // Simulate a slow find action + r := atomicResult.Load().(mockEntity) // Thread-safe read result + return r, nil }, func() (mockEntity, error) { // createAction - atomic.AddInt32(&calledTimes, 1) - - time.Sleep(10 * time.Millisecond) - result = mockEntity{ - ID: 1, - Name: "create", - } - - return result, nil + atomic.AddInt32(&calledTimes, 1) // Record the number of times createAction is called + time.Sleep(10 * time.Millisecond) // Simulate a slow create action + r := mockEntity{ID: 1, Name: "create"} + atomicResult.Store(r) // Thread-safe update result + return r, nil }) }