diff --git a/client/cmd/saveHistoryEntry.go b/client/cmd/saveHistoryEntry.go index e454352..b0fbadb 100644 --- a/client/cmd/saveHistoryEntry.go +++ b/client/cmd/saveHistoryEntry.go @@ -206,10 +206,16 @@ func deletePresavedEntries(ctx context.Context, entry *data.HistoryEntry) error matchingEntryQuery = matchingEntryQuery.Where("command = ?", entry.Command).Session(&gorm.Session{}) // Get the presaved entry since we need it for doing remote deletes - var presavedEntry data.HistoryEntry - res := matchingEntryQuery.Find(&presavedEntry) - if res.Error != nil { - return fmt.Errorf("failed to search for presaved entry for cmd=%#v: %w", entry.Command, res.Error) + presavedEntry, err := lib.RetryingDbFunctionWithResult(func() (data.HistoryEntry, error) { + var presavedEntry data.HistoryEntry + res := matchingEntryQuery.Find(&presavedEntry) + if res.Error != nil { + return presavedEntry, fmt.Errorf("failed to search for presaved entry for cmd=%#v: %w", entry.Command, res.Error) + } + return presavedEntry, nil + }) + if err != nil { + return err } // Delete presaved entries locally diff --git a/client/lib/lib.go b/client/lib/lib.go index ad0915a..49fb064 100644 --- a/client/lib/lib.go +++ b/client/lib/lib.go @@ -507,6 +507,25 @@ func RetryingDbFunction(dbFunc func() error) error { return fmt.Errorf("failed to execute DB transaction even with %d retries: %w", i, err) } +func RetryingDbFunctionWithResult[T any](dbFunc func() (T, error)) (T, error) { + var t T + var err error = nil + i := 0 + for i = 0; i < 10; i++ { + t, err = dbFunc() + if err == nil { + return t, nil + } + errMsg := err.Error() + if strings.Contains(errMsg, SQLITE_LOCKED_ERR_MSG) { + time.Sleep(time.Duration(i*rand.Intn(100)) * time.Millisecond) + continue + } + return t, fmt.Errorf("unrecoverable sqlite error: %w", err) + } + return t, fmt.Errorf("failed to execute DB transaction even with %d retries: %w", i, err) +} + func ReliableDbCreate(db *gorm.DB, entry data.HistoryEntry) error { entry = normalizeEntryTimezone(entry) return RetryingDbFunction(func() error {