ots: stop at ctx.Done() (#8790)

This commit is contained in:
Alex Sharov 2023-11-23 08:49:33 +07:00 committed by GitHub
parent 57bcbaa21f
commit e390b0e182
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 49 additions and 10 deletions

View File

@ -5,9 +5,9 @@ import (
"errors"
"fmt"
"math/big"
"sync"
hexutil2 "github.com/ledgerwatch/erigon-lib/common/hexutil"
"golang.org/x/sync/errgroup"
"github.com/holiman/uint256"
"github.com/ledgerwatch/log/v3"
@ -435,8 +435,6 @@ func (api *OtterscanAPIImpl) SearchTransactionsAfter(ctx context.Context, addr c
}
func (api *OtterscanAPIImpl) traceBlocks(ctx context.Context, addr common.Address, chainConfig *chain.Config, pageSize, resultCount uint16, callFromToProvider BlockProvider) ([]*TransactionsWithReceipts, bool, error) {
var wg sync.WaitGroup
// Estimate the common case of user address having at most 1 interaction/block and
// trace N := remaining page matches as number of blocks to trace concurrently.
// TODO: this is not optimimal for big contract addresses; implement some better heuristics.
@ -445,7 +443,11 @@ func (api *OtterscanAPIImpl) traceBlocks(ctx context.Context, addr common.Addres
totalBlocksTraced := 0
hasMore := true
eg, ctx := errgroup.WithContext(ctx)
eg.SetLimit(1024) // we don't want limit much here, but protecting from infinity attack
for i := 0; i < int(estBlocksToTrace); i++ {
i := i // we will pass it to goroutine
var nextBlock uint64
var err error
nextBlock, hasMore, err = callFromToProvider()
@ -457,11 +459,19 @@ func (api *OtterscanAPIImpl) traceBlocks(ctx context.Context, addr common.Addres
break
}
wg.Add(1)
totalBlocksTraced++
go api.searchTraceBlock(ctx, &wg, addr, chainConfig, i, nextBlock, results)
eg.Go(func() error {
// don't return error from searchTraceBlock - to avoid 1 block fail impact to other blocks
// if return error - `errgroup` will interrupt all other goroutines
// but passing `ctx` - then user still can cancel request
api.searchTraceBlock(ctx, addr, chainConfig, i, nextBlock, results)
return nil
})
}
if err := eg.Wait(); err != nil {
return nil, false, err
}
wg.Wait()
return results[:totalBlocksTraced], hasMore, nil
}

View File

@ -211,6 +211,12 @@ func (api *OtterscanAPIImpl) GetContractCreator(ctx context.Context, addr common
defer bitmapdb.ReturnToPool64(bm)
prevShardMaxBl := uint64(0)
for {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
_, err := bm.ReadFrom(bytes.NewReader(v))
if err != nil {
return nil, err

View File

@ -84,6 +84,12 @@ func (api *OtterscanAPIImpl) genericTracer(dbtx kv.Tx, ctx context.Context, bloc
rules := chainConfig.Rules(block.NumberU64(), header.Time)
signer := types.MakeSigner(chainConfig, blockNum, header.Time)
for idx, tx := range block.Transactions() {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
ibs.SetTxContext(tx.Hash(), block.Hash(), idx)
msg, _ := tx.AsMessage(*signer, header.BaseFee, rules)

View File

@ -2,7 +2,7 @@ package jsonrpc
import (
"context"
"sync"
"fmt"
"github.com/ledgerwatch/erigon-lib/chain"
"github.com/ledgerwatch/erigon-lib/common"
@ -18,9 +18,7 @@ import (
"github.com/ledgerwatch/erigon/turbo/shards"
)
func (api *OtterscanAPIImpl) searchTraceBlock(ctx context.Context, wg *sync.WaitGroup, addr common.Address, chainConfig *chain.Config, idx int, bNum uint64, results []*TransactionsWithReceipts) {
defer wg.Done()
func (api *OtterscanAPIImpl) searchTraceBlock(ctx context.Context, addr common.Address, chainConfig *chain.Config, idx int, bNum uint64, results []*TransactionsWithReceipts) {
// Trace block for Txs
newdbtx, err := api.db.BeginRo(ctx)
if err != nil {
@ -80,6 +78,11 @@ func (api *OtterscanAPIImpl) traceBlock(dbtx kv.Tx, ctx context.Context, blockNu
rules := chainConfig.Rules(block.NumberU64(), header.Time)
found := false
for idx, tx := range block.Transactions() {
select {
case <-ctx.Done():
return false, nil, ctx.Err()
default:
}
ibs.SetTxContext(tx.Hash(), block.Hash(), idx)
msg, _ := tx.AsMessage(*signer, header.BaseFee, rules)
@ -95,6 +98,14 @@ func (api *OtterscanAPIImpl) traceBlock(dbtx kv.Tx, ctx context.Context, blockNu
_ = ibs.FinalizeTx(rules, cachedWriter)
if tracer.Found {
if idx > len(blockReceipts) {
select { // it may happen because request canceled, then return canelation error
case <-ctx.Done():
return false, nil, ctx.Err()
default:
}
return false, nil, fmt.Errorf("requested receipt idx %d, but have only %d", idx, len(blockReceipts)) // otherwise return some error for debugging
}
rpcTx := NewRPCTransaction(tx, block.Hash(), blockNum, uint64(idx), block.BaseFee())
mReceipt := marshalReceipt(blockReceipts[idx], tx, chainConfig, block.HeaderNoCopy(), tx.Hash(), true)
mReceipt["timestamp"] = block.Time()

View File

@ -173,6 +173,12 @@ func (api *OtterscanAPIImpl) GetTransactionBySenderAndNonce(ctx context.Context,
maxBlPrevChunk := uint64(0)
for {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
if k == nil || !bytes.HasPrefix(k, addr.Bytes()) {
// Check plain state
data, err := tx.GetOne(kv.PlainState, addr.Bytes())