Skip to content

Commit

Permalink
Add retry support for serializable transactions (#386)
Browse files Browse the repository at this point in the history
## tl;dr

I noticed our `libxmtp` test suite was occasionally failing due to serializable transaction errors. This adds retries, which are required when using the serializable isolation level since errors are common and transient thanks to Postgres' conflict detection
  • Loading branch information
neekolas authored Apr 30, 2024
1 parent ff22ba5 commit 827b3f2
Showing 1 changed file with 18 additions and 1 deletion.
19 changes: 18 additions & 1 deletion pkg/mls/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (s *Store) PublishIdentityUpdate(ctx context.Context, req *identity.Publish
return nil, errors.New("IdentityUpdate is required")
}

if err := s.RunInTx(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable}, func(ctx context.Context, txQueries *queries.Queries) error {
if err := s.RunInSerializableTx(ctx, 3, func(ctx context.Context, txQueries *queries.Queries) error {
inboxLogEntries, err := txQueries.GetAllInboxLogs(ctx, new_update.GetInboxId())
if err != nil {
return err
Expand Down Expand Up @@ -605,3 +605,20 @@ func (s *Store) RunInTx(
done = true
return tx.Commit()
}

func (s *Store) RunInSerializableTx(ctx context.Context, numRetries int, fn func(ctx context.Context, txQueries *queries.Queries) error) error {
var err error
for i := 0; i < numRetries; i++ {
select {
case <-ctx.Done():
return ctx.Err()
default:
err = s.RunInTx(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable}, fn)
if err == nil {
return nil
}
s.log.Warn("Error in serializable tx", zap.Error(err))
}
}
return err
}

0 comments on commit 827b3f2

Please sign in to comment.