Skip to content

Commit ee2637c

Browse files
authored
Replace mutex with sync.Map for ABI caching (#218)
### TL;DR Replace mutex-protected map with sync.Map for ABI caching to improve concurrency. ### What changed? - Replaced the manual mutex-protected map implementation with Go's built-in `sync.Map` for ABI caching - Modified `GetABIForContractWithCache` to use `sync.Map` methods (`Load`, `Store`) instead of manual locking - Removed mutex parameters from function signatures in `DecodeLogs` and `DecodeTransactions` - Simplified the concurrent processing of logs and transactions by eliminating explicit mutex handling ### How to test? 1. Run concurrent processing of logs and transactions to verify that ABI caching works correctly 2. Verify that decoded logs and transactions contain the expected data 3. Check for any race conditions or deadlocks that might have been introduced ### Why make this change? The previous implementation used a manual mutex to protect a map during concurrent access, which can lead to contention and reduced performance. `sync.Map` is specifically designed for concurrent use cases where items are frequently read but infrequently updated, which matches the ABI caching pattern. This change improves code safety and performance by using a more appropriate concurrency primitive. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Refactor** - Improved concurrency handling for ABI caching, resulting in more reliable and efficient processing of logs and transactions. - Simplified internal logic for decoding logs and transactions, reducing potential synchronization issues. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
2 parents 4ae507a + 5196a3f commit ee2637c

File tree

3 files changed

+27
-32
lines changed

3 files changed

+27
-32
lines changed

internal/common/abi.go

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,20 @@ func getHTTPClient() *http.Client {
3434
return httpClient
3535
}
3636

37-
func GetABIForContractWithCache(chainId string, contract string, abiCache map[string]*abi.ABI, mut *sync.Mutex) *abi.ABI {
38-
abi, ok := abiCache[contract]
39-
if !ok {
40-
abiResult, err := GetABIForContract(chainId, contract)
41-
if err != nil {
42-
mut.Lock()
43-
abiCache[contract] = nil
44-
mut.Unlock()
45-
return nil
46-
} else {
47-
mut.Lock()
48-
abiCache[contract] = abiResult
49-
mut.Unlock()
50-
abi = abiResult
37+
func GetABIForContractWithCache(chainId string, contract string, abiCache *sync.Map) *abi.ABI {
38+
if abiValue, ok := abiCache.Load(contract); ok {
39+
if abi, ok := abiValue.(*abi.ABI); ok {
40+
return abi
5141
}
5242
}
53-
return abi
43+
44+
abiResult, err := GetABIForContract(chainId, contract)
45+
if err != nil {
46+
abiCache.Store(contract, nil)
47+
return nil
48+
}
49+
abiCache.Store(contract, abiResult)
50+
return abiResult
5451
}
5552

5653
func GetABIForContract(chainId string, contract string) (*abi.ABI, error) {

internal/common/log.go

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ type DecodedLog struct {
8787

8888
func DecodeLogs(chainId string, logs []Log) []*DecodedLog {
8989
decodedLogs := make([]*DecodedLog, len(logs))
90-
abiCache := make(map[string]*abi.ABI)
90+
abiCache := &sync.Map{}
9191

92-
decodeLogFunc := func(eventLog *Log, mut *sync.Mutex) *DecodedLog {
92+
decodeLogFunc := func(eventLog *Log) *DecodedLog {
9393
decodedLog := DecodedLog{Log: *eventLog}
94-
abi := GetABIForContractWithCache(chainId, eventLog.Address, abiCache, mut)
94+
abi := GetABIForContractWithCache(chainId, eventLog.Address, abiCache)
9595
if abi == nil {
9696
return &decodedLog
9797
}
@@ -108,27 +108,26 @@ func DecodeLogs(chainId string, logs []Log) []*DecodedLog {
108108
}
109109

110110
var wg sync.WaitGroup
111-
var mut sync.Mutex
112111
for idx, eventLog := range logs {
113112
wg.Add(1)
114-
go func(idx int, eventLog Log, mut *sync.Mutex) {
113+
go func(idx int, eventLog Log) {
115114
defer func() {
116115
if err := recover(); err != nil {
117116
log.Error().
118117
Any("chainId", chainId).
119-
Any("Logs", logs).
120-
Int("logIndex", idx).
118+
Str("txHash", eventLog.TransactionHash).
119+
Uint64("logIndex", eventLog.LogIndex).
121120
Str("logAddress", eventLog.Address).
122121
Str("logTopic0", eventLog.Topic0).
123122
Err(fmt.Errorf("%v", err)).
124123
Msg("Caught panic in DecodeLogs, possibly in decodeLogFunc")
124+
decodedLogs[idx] = &DecodedLog{Log: eventLog}
125125
}
126-
decodedLogs[idx] = &DecodedLog{Log: eventLog}
127126
}()
128127
defer wg.Done()
129-
decodedLog := decodeLogFunc(&eventLog, mut)
128+
decodedLog := decodeLogFunc(&eventLog)
130129
decodedLogs[idx] = decodedLog
131-
}(idx, eventLog, &mut)
130+
}(idx, eventLog)
132131
}
133132
wg.Wait()
134133
return decodedLogs

internal/common/transaction.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,10 @@ type DecodedTransactionModel struct {
110110

111111
func DecodeTransactions(chainId string, txs []Transaction) []*DecodedTransaction {
112112
decodedTxs := make([]*DecodedTransaction, len(txs))
113-
abiCache := make(map[string]*abi.ABI)
114-
decodeTxFunc := func(transaction *Transaction, mut *sync.Mutex) *DecodedTransaction {
113+
abiCache := &sync.Map{}
114+
decodeTxFunc := func(transaction *Transaction) *DecodedTransaction {
115115
decodedTransaction := DecodedTransaction{Transaction: *transaction}
116-
abi := GetABIForContractWithCache(chainId, transaction.ToAddress, abiCache, mut)
116+
abi := GetABIForContractWithCache(chainId, transaction.ToAddress, abiCache)
117117
if abi == nil {
118118
return &decodedTransaction
119119
}
@@ -139,14 +139,13 @@ func DecodeTransactions(chainId string, txs []Transaction) []*DecodedTransaction
139139
}
140140

141141
var wg sync.WaitGroup
142-
mut := &sync.Mutex{}
143142
for idx, transaction := range txs {
144143
wg.Add(1)
145-
go func(idx int, transaction Transaction, mut *sync.Mutex) {
144+
go func(idx int, transaction Transaction) {
146145
defer wg.Done()
147-
decodedTx := decodeTxFunc(&transaction, mut)
146+
decodedTx := decodeTxFunc(&transaction)
148147
decodedTxs[idx] = decodedTx
149-
}(idx, transaction, mut)
148+
}(idx, transaction)
150149
}
151150
wg.Wait()
152151
return decodedTxs

0 commit comments

Comments
 (0)