fix chunking

This commit is contained in:
Caner Çıdam 2023-06-09 21:53:54 +03:00
parent 83a1516841
commit 1436386c67
2 changed files with 84 additions and 10 deletions

View file

@ -78,21 +78,41 @@ func (caller *Caller) Call(opts *bind.CallOpts, calls ...*Call) ([]*Call, error)
// CallChunked makes multiple multicalls by chunking given calls.
func (caller *Caller) CallChunked(opts *bind.CallOpts, chunkSize int, calls ...*Call) ([]*Call, error) {
if chunkSize <= 0 || len(calls) < 2 {
return caller.Call(opts, calls...)
}
callCount := len(calls) / chunkSize
var allCalls []*Call
for i := 0; i < callCount; i++ {
start := i * chunkSize
end := start + chunkSize
chunk, err := caller.Call(opts, calls[start:end]...)
for i, chunk := range chunkInputs(chunkSize, calls) {
chunk, err := caller.Call(opts, chunk...)
if err != nil {
return calls, fmt.Errorf("call chunk [%d] failed: %v", i, err)
}
allCalls = append(allCalls, chunk...)
}
return allCalls, nil
}
func chunkInputs[T any](chunkSize int, inputs []T) (chunks [][]T) {
if len(inputs) == 0 {
return
}
if chunkSize <= 0 || len(inputs) < 2 || chunkSize > len(inputs) {
return [][]T{inputs}
}
lastChunkSize := len(inputs) % chunkSize
chunkCount := len(inputs) / chunkSize
for i := 0; i < chunkCount; i++ {
start := i * chunkSize
end := start + chunkSize
chunks = append(chunks, inputs[start:end])
}
if lastChunkSize > 0 {
start := chunkCount * chunkSize
end := start + lastChunkSize
chunks = append(chunks, inputs[start:end])
}
return
}

View file

@ -325,3 +325,57 @@ func TestDial(t *testing.T) {
r.NoError(err)
r.NotNil(caller)
}
func TestChunkInputs(t *testing.T) {
testCases := []struct {
name string
chunkSize int
inputs []int
expected [][]int
}{
{
name: "zero inputs large chunk size",
chunkSize: 12345,
inputs: []int{},
expected: nil,
},
{
name: "single input large chunk size",
chunkSize: 12345,
inputs: []int{10},
expected: [][]int{{10}},
},
{
name: "2 inputs chunk size 1",
chunkSize: 1,
inputs: []int{10, 20},
expected: [][]int{{10}, {20}},
},
{
name: "2 inputs chunk size 2",
chunkSize: 2,
inputs: []int{10, 20},
expected: [][]int{{10, 20}},
},
{
name: "5 inputs chunk size 3",
chunkSize: 3,
inputs: []int{10, 20, 30, 40, 50},
expected: [][]int{{10, 20, 30}, {40, 50}},
},
{
name: "3 inputs chunk size 5",
chunkSize: 5,
inputs: []int{10, 20, 30},
expected: [][]int{{10, 20, 30}},
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
r := require.New(t)
r.Equal(testCase.expected, chunkInputs(testCase.chunkSize, testCase.inputs))
})
}
}