| 18 | ) |
| 19 | |
| 20 | func TestSerializedRetry(t *testing.T) { |
| 21 | t.Parallel() |
| 22 | if testing.Short() { |
| 23 | t.SkipNow() |
| 24 | } |
| 25 | |
| 26 | sqlDB := testSQLDB(t) |
| 27 | db := database.New(sqlDB) |
| 28 | |
| 29 | called := 0 |
| 30 | txOpts := &database.TxOptions{Isolation: sql.LevelSerializable} |
| 31 | err := db.InTx(func(tx database.Store) error { |
| 32 | // Test nested error |
| 33 | return tx.InTx(func(tx database.Store) error { |
| 34 | // The easiest way to mock a serialization failure is to |
| 35 | // return a serialization failure error. |
| 36 | called++ |
| 37 | return &pq.Error{ |
| 38 | Code: "40001", |
| 39 | Message: "serialization_failure", |
| 40 | } |
| 41 | }, txOpts) |
| 42 | }, txOpts) |
| 43 | require.Error(t, err, "should fail") |
| 44 | // The double "execute transaction: execute transaction" is from the nested transactions. |
| 45 | // Just want to make sure we don't try 9 times. |
| 46 | require.Equal(t, err.Error(), "transaction failed after 3 attempts: execute transaction: execute transaction: pq: serialization_failure", "error message") |
| 47 | require.Equal(t, called, 3, "should retry 3 times") |
| 48 | } |
| 49 | |
| 50 | func TestNestedInTx(t *testing.T) { |
| 51 | t.Parallel() |