/
tx_retry.go
100 lines (80 loc) · 1.86 KB
/
tx_retry.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package beacon
import (
"context"
"sync"
"github.com/cenkalti/backoff/v4"
cmnBackoff "github.com/oasisprotocol/oasis-core/go/common/backoff"
"github.com/oasisprotocol/oasis-core/go/common/identity"
"github.com/oasisprotocol/oasis-core/go/common/logging"
consensus "github.com/oasisprotocol/oasis-core/go/consensus/api"
"github.com/oasisprotocol/oasis-core/go/consensus/api/transaction"
)
type txRetry struct {
sync.Mutex
logger *logging.Logger
consensus consensus.Backend
identity *identity.Identity
cancelFn context.CancelFunc
}
func (rtr *txRetry) newRetryCtx(ctx context.Context) context.Context {
rtr.Lock()
defer rtr.Unlock()
if rtr.cancelFn != nil {
rtr.cancelFn()
}
var subCtx context.Context
subCtx, rtr.cancelFn = context.WithCancel(ctx)
return subCtx
}
func (rtr *txRetry) Cancel() {
rtr.Lock()
defer rtr.Unlock()
if rtr.cancelFn != nil {
rtr.cancelFn()
rtr.cancelFn = nil
}
}
func (rtr *txRetry) SubmitTx(
baseCtx context.Context,
tx *transaction.Transaction,
checkFn func(context.Context) error,
) {
ctx := rtr.newRetryCtx(baseCtx)
off := backoff.WithContext(cmnBackoff.NewExponentialBackOff(), ctx)
fn := func() error {
if err := checkFn(ctx); err != nil {
return err
}
err := consensus.SignAndSubmitTx(
ctx,
rtr.consensus,
rtr.identity.NodeSigner,
tx,
)
if err == nil {
rtr.logger.Debug("tx submitted",
"method", tx.Method,
)
}
return err
}
// Optimistically try to just submit the Tx in-line.
if err := fn(); err != nil {
rtr.logger.Debug("in-line tx submit failed, scheduling retries",
"err", err,
"method", tx.Method,
)
go backoff.Retry(fn, off) //nolint: errcheck
}
}
func newTxRetry(
logger *logging.Logger,
consensus consensus.Backend,
identity *identity.Identity,
) *txRetry {
return &txRetry{
logger: logger,
consensus: consensus,
identity: identity,
}
}