Merge PR #4658: Generalize Querier REST Pagination
This commit is contained in:
parent
b3a8195e31
commit
aba1f649ad
|
@ -0,0 +1,2 @@
|
|||
#4601 Implement generic pangination helper function to be used in
|
||||
REST handlers and queriers.
|
|
@ -0,0 +1,30 @@
|
|||
package client
|
||||
|
||||
// Paginate returns the correct starting and ending index for a paginated query,
|
||||
// given that client provides a desired page and limit of objects and the handler
|
||||
// provides the total number of objects. If the start page is invalid, non-positive
|
||||
// values are returned signaling the request is invalid.
|
||||
//
|
||||
// NOTE: The start page is assumed to be 1-indexed.
|
||||
func Paginate(numObjs, page, limit, defLimit int) (start, end int) {
|
||||
if page == 0 {
|
||||
// invalid start page
|
||||
return -1, -1
|
||||
} else if limit == 0 {
|
||||
limit = defLimit
|
||||
}
|
||||
|
||||
start = (page - 1) * limit
|
||||
end = limit + start
|
||||
|
||||
if end >= numObjs {
|
||||
end = numObjs
|
||||
}
|
||||
|
||||
if start >= numObjs {
|
||||
// page is out of bounds
|
||||
return -1, -1
|
||||
}
|
||||
|
||||
return start, end
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package client_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
)
|
||||
|
||||
func TestPaginate(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
numObjs, page, limit, defLimit int
|
||||
expectedStart, expectedEnd int
|
||||
}{
|
||||
{
|
||||
"all objects in a single page",
|
||||
100, 1, 100, 100,
|
||||
0, 100,
|
||||
},
|
||||
{
|
||||
"page one of three",
|
||||
75, 1, 25, 100,
|
||||
0, 25,
|
||||
},
|
||||
{
|
||||
"page two of three",
|
||||
75, 2, 25, 100,
|
||||
25, 50,
|
||||
},
|
||||
{
|
||||
"page three of three",
|
||||
75, 3, 25, 100,
|
||||
50, 75,
|
||||
},
|
||||
{
|
||||
"end is greater than total number of objects",
|
||||
75, 2, 50, 100,
|
||||
50, 75,
|
||||
},
|
||||
{
|
||||
"invalid start page",
|
||||
75, 4, 25, 100,
|
||||
-1, -1,
|
||||
},
|
||||
{
|
||||
"invalid zero start page",
|
||||
75, 0, 25, 100,
|
||||
-1, -1,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
start, end := client.Paginate(tc.numObjs, tc.page, tc.limit, tc.defLimit)
|
||||
require.Equal(t, tc.expectedStart, start, "invalid result; test case #%d", i)
|
||||
require.Equal(t, tc.expectedEnd, end, "invalid result; test case #%d", i)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
@ -65,11 +66,6 @@ func querySigningInfos(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte
|
|||
return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err))
|
||||
}
|
||||
|
||||
if params.Limit == 0 {
|
||||
// set the default limit to max bonded if no limit was provided
|
||||
params.Limit = int(k.sk.MaxValidators(ctx))
|
||||
}
|
||||
|
||||
var signingInfos []ValidatorSigningInfo
|
||||
|
||||
k.IterateValidatorSigningInfos(ctx, func(consAddr sdk.ConsAddress, info ValidatorSigningInfo) (stop bool) {
|
||||
|
@ -77,15 +73,8 @@ func querySigningInfos(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte
|
|||
return false
|
||||
})
|
||||
|
||||
// get pagination bounds
|
||||
start := (params.Page - 1) * params.Limit
|
||||
end := params.Limit + start
|
||||
if end >= len(signingInfos) {
|
||||
end = len(signingInfos)
|
||||
}
|
||||
|
||||
if start >= len(signingInfos) {
|
||||
// page is out of bounds
|
||||
start, end := client.Paginate(len(signingInfos), params.Page, params.Limit, int(k.sk.MaxValidators(ctx)))
|
||||
if start < 0 || end < 0 {
|
||||
signingInfos = []ValidatorSigningInfo{}
|
||||
} else {
|
||||
signingInfos = signingInfos[start:end]
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
|
@ -55,11 +56,6 @@ func queryValidators(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte,
|
|||
return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err))
|
||||
}
|
||||
|
||||
stakingParams := k.GetParams(ctx)
|
||||
if params.Limit == 0 {
|
||||
params.Limit = int(stakingParams.MaxValidators)
|
||||
}
|
||||
|
||||
validators := k.GetAllValidators(ctx)
|
||||
filteredVals := make([]types.Validator, 0, len(validators))
|
||||
|
||||
|
@ -69,15 +65,8 @@ func queryValidators(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte,
|
|||
}
|
||||
}
|
||||
|
||||
// get pagination bounds
|
||||
start := (params.Page - 1) * params.Limit
|
||||
end := params.Limit + start
|
||||
if end >= len(filteredVals) {
|
||||
end = len(filteredVals)
|
||||
}
|
||||
|
||||
if start >= len(filteredVals) {
|
||||
// page is out of bounds
|
||||
start, end := client.Paginate(len(filteredVals), params.Page, params.Limit, int(k.GetParams(ctx).MaxValidators))
|
||||
if start < 0 || end < 0 {
|
||||
filteredVals = []types.Validator{}
|
||||
} else {
|
||||
filteredVals = filteredVals[start:end]
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/supply/types"
|
||||
)
|
||||
|
@ -32,20 +33,9 @@ func queryTotalSupply(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte,
|
|||
}
|
||||
|
||||
totalSupply := k.GetSupply(ctx).Total
|
||||
totalSupplyLen := len(totalSupply)
|
||||
|
||||
if params.Limit == 0 {
|
||||
params.Limit = totalSupplyLen
|
||||
}
|
||||
|
||||
start := (params.Page - 1) * params.Limit
|
||||
end := params.Limit + start
|
||||
if end >= totalSupplyLen {
|
||||
end = totalSupplyLen
|
||||
}
|
||||
|
||||
if start >= totalSupplyLen {
|
||||
// page is out of bounds
|
||||
start, end := client.Paginate(len(totalSupply), params.Page, params.Limit, 100)
|
||||
if start < 0 || end < 0 {
|
||||
totalSupply = sdk.Coins{}
|
||||
} else {
|
||||
totalSupply = totalSupply[start:end]
|
||||
|
|
Loading…
Reference in New Issue