Reverse the order of db queries in GetActionsByIndex API
@@ -598,6 +598,7 @@ func (api *Server) readState(ctx context.Context, in *iotexapi.ReadStateRequest)
}
// GetActions returns actions within the range
+// This is a workaround for the slow access issue if the start index is very big
func (api *Server) getActions(start uint64, count uint64) (*iotexapi.GetActionsResponse, error) {
if count == 0 || count > api.cfg.RangeQueryLimit {
return nil, status.Error(codes.InvalidArgument, "range exceeds the limit")
@@ -611,23 +612,30 @@ func (api *Server) getActions(start uint64, count uint64) (*iotexapi.GetActionsR
return nil, status.Error(codes.InvalidArgument, "start exceeds the limit")
}
+ // Finding actions in reverse order saves time for querying most recent actions
+ reverseStart := totalActions - (start + count)
+ if totalActions < start+count {
+ reverseStart = uint64(0)
+ count = totalActions - start
+ }
+
var res []*iotexapi.ActionInfo
var hit bool
- for height := uint64(1); height <= api.bc.TipHeight() && count > 0; height++ {
+ for height := api.bc.TipHeight(); height >= 1 && count > 0; height-- {
blk, err := api.bc.GetBlockByHeight(height)
if err != nil {
return nil, status.Error(codes.NotFound, err.Error())
}
- if !hit && start >= uint64(len(blk.Actions)) {
- start -= uint64(len(blk.Actions))
+ if !hit && reverseStart >= uint64(len(blk.Actions)) {
+ reverseStart -= uint64(len(blk.Actions))
continue
}
- // now start < len(blk.Actions), we are going to fetch actions from this block
+ // now reverseStart < len(blk.Actions), we are going to fetch actions from this block
hit = true
- act := api.actionsInBlock(blk, start, count)
- res = append(res, act...)
+ act := api.reverseActionsInBlock(blk, reverseStart, count)
+ res = append(act, res...)
count -= uint64(len(act))
- start = 0
+ reverseStart = 0
}
return &iotexapi.GetActionsResponse{
Total: totalActions,
@@ -919,6 +927,32 @@ func (api *Server) actionsInBlock(blk *block.Block, start, count uint64) []*iote
return res
}
+func (api *Server) reverseActionsInBlock(blk *block.Block, reverseStart, count uint64) []*iotexapi.ActionInfo {
+ h := blk.HashBlock()
+ blkHash := hex.EncodeToString(h[:])
+ blkHeight := blk.Height()
+ ts := blk.Header.BlockHeaderCoreProto().Timestamp
+
+ var res []*iotexapi.ActionInfo
+ for i := reverseStart; i < uint64(len(blk.Actions)) && i < reverseStart+count; i++ {
+ ri := uint64(len(blk.Actions)) - 1 - i
+ selp := blk.Actions[ri]
+ actHash := selp.Hash()
+ sender, _ := address.FromBytes(selp.SrcPubkey().Hash())
+ res = append([]*iotexapi.ActionInfo{
+ {
+ Action: selp.Proto(),
+ ActHash: hex.EncodeToString(actHash[:]),
+ BlkHash: blkHash,
+ BlkHeight: blkHeight,
+ Sender: sender.String(),
+ Timestamp: ts,
+ },
+ }, res...)
+ }
+ return res
+}
+
func getTranferAmountInBlock(blk *block.Block) *big.Int {
totalAmount := big.NewInt(0)
for _, selp := range blk.Actions {
