/
transaction.go
112 lines (90 loc) · 3.18 KB
/
transaction.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
101
102
103
104
105
106
107
108
109
110
111
112
package interactors
import (
"context"
"sync"
"time"
"github.com/multiversx/mx-chain-core-go/core/check"
"github.com/multiversx/mx-chain-core-go/data/transaction"
logger "github.com/multiversx/mx-chain-logger-go"
)
var log = logger.GetOrCreate("mx-sdk-go/interactors")
const defaultTimeBetweenBunches = time.Second
type transactionInteractor struct {
Proxy
GuardedTxBuilder
mutTxAccumulator sync.RWMutex
mutTimeBetweenBunches sync.RWMutex
timeBetweenBunches time.Duration
txAccumulator []*transaction.FrontendTransaction
}
// NewTransactionInteractor will create an interactor that extends the proxy functionality with some transaction-oriented functionality
func NewTransactionInteractor(proxy Proxy, txBuilder GuardedTxBuilder) (*transactionInteractor, error) {
if check.IfNil(proxy) {
return nil, ErrNilProxy
}
if check.IfNil(txBuilder) {
return nil, ErrNilTxBuilder
}
return &transactionInteractor{
Proxy: proxy,
GuardedTxBuilder: txBuilder,
timeBetweenBunches: defaultTimeBetweenBunches,
}, nil
}
// SetTimeBetweenBunches sets the time between bunch sends
func (ti *transactionInteractor) SetTimeBetweenBunches(timeBetweenBunches time.Duration) {
ti.mutTimeBetweenBunches.Lock()
ti.timeBetweenBunches = timeBetweenBunches
ti.mutTimeBetweenBunches.Unlock()
}
// AddTransaction will add the provided transaction in the transaction accumulator
func (ti *transactionInteractor) AddTransaction(tx *transaction.FrontendTransaction) {
if tx == nil {
return
}
ti.mutTxAccumulator.Lock()
ti.txAccumulator = append(ti.txAccumulator, tx)
ti.mutTxAccumulator.Unlock()
}
// PopAccumulatedTransactions will return the whole accumulated contents emptying the accumulator
func (ti *transactionInteractor) PopAccumulatedTransactions() []*transaction.FrontendTransaction {
ti.mutTxAccumulator.Lock()
result := make([]*transaction.FrontendTransaction, len(ti.txAccumulator))
copy(result, ti.txAccumulator)
ti.txAccumulator = make([]*transaction.FrontendTransaction, 0)
ti.mutTxAccumulator.Unlock()
return result
}
// SendTransactionsAsBunch will send all stored transactions as bunches
func (ti *transactionInteractor) SendTransactionsAsBunch(ctx context.Context, bunchSize int) ([]string, error) {
if bunchSize <= 0 {
return nil, ErrInvalidValue
}
ti.mutTimeBetweenBunches.RLock()
timeBetweenBunches := ti.timeBetweenBunches
ti.mutTimeBetweenBunches.RUnlock()
transactions := ti.PopAccumulatedTransactions()
allHashes := make([]string, 0)
for bunchIndex := 0; len(transactions) > 0; bunchIndex++ {
var bunch []*transaction.FrontendTransaction
log.Debug("sending bunch", "index", bunchIndex)
if len(transactions) > bunchSize {
bunch = transactions[0:bunchSize]
transactions = transactions[bunchSize:]
} else {
bunch = transactions
transactions = make([]*transaction.FrontendTransaction, 0)
}
hashes, err := ti.Proxy.SendTransactions(ctx, bunch)
if err != nil {
return nil, err
}
allHashes = append(allHashes, hashes...)
time.Sleep(timeBetweenBunches)
}
return allHashes, nil
}
// IsInterfaceNil returns true if there is no value under the interface
func (ti *transactionInteractor) IsInterfaceNil() bool {
return ti == nil
}