( retries int, retryStrategy func() time.Duration, beginStrategy func() (ITransaction, error), fn func(ITransaction) error, )
| 108 | } |
| 109 | |
| 110 | func WithinTemplate( |
| 111 | retries int, |
| 112 | retryStrategy func() time.Duration, |
| 113 | beginStrategy func() (ITransaction, error), |
| 114 | fn func(ITransaction) error, |
| 115 | ) error { |
| 116 | var err error |
| 117 | for attempt := 0; attempt <= retries; attempt++ { |
| 118 | if err = tryWithinTx(beginStrategy, fn); err == nil || !IsDeadlock(err) { |
| 119 | return err |
| 120 | } |
| 121 | retryInterval := GetRetryInterval(retryStrategy()) |
| 122 | log.Warning( |
| 123 | "scoped transaction deadlocked, retrying %d / %d, after %dms", |
| 124 | attempt, |
| 125 | retries, |
| 126 | retryInterval.Nanoseconds()/int64(time.Millisecond), |
| 127 | ) |
| 128 | if retryInterval > 0 { |
| 129 | time.Sleep(retryInterval) |
| 130 | } |
| 131 | } |
| 132 | log.Warning( |
| 133 | "scoped transaction still deadlocked after %d retries; gave up", |
| 134 | retries, |
| 135 | ) |
| 136 | return err |
| 137 | } |
| 138 | |
| 139 | func GetRetryInterval(retryInterval time.Duration) time.Duration { |
| 140 | if retryInterval > 0 { |
no test coverage detected