Skip to content

Commit de72953

Browse files
committed
looprpc: add simple pagination to the ListSwaps command
This commit adds the ability to set a max_swaps and an index_offset flag to the ListSwaps command. These new fields are applied AFTER the initial filtering step. The response also now passes additional information about the index count and total swaps filtered.
1 parent 84820f2 commit de72953

File tree

5 files changed

+990
-862
lines changed

5 files changed

+990
-862
lines changed

cmd/loop/swaps.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ var listSwapsCommand = cli.Command{
3535
labelFlag,
3636
channelFlag,
3737
lastHopFlag,
38+
cli.Uint64Flag{
39+
Name: "max_swaps",
40+
Usage: "Max number of swaps to return after filtering",
41+
},
42+
cli.Int64Flag{
43+
Name: "start_time_ns",
44+
Usage: "Unix timestamp to start listing swaps from (default: 0, meaning no start time filter)",
45+
},
3846
},
3947
}
4048

@@ -99,9 +107,19 @@ func listSwaps(ctx *cli.Context) error {
99107
filter.Label = ctx.String(labelFlag.Name)
100108
}
101109

110+
// Parse start timestamp if set.
111+
if ctx.IsSet("start_time_ns") {
112+
startTimestamp, err := strconv.ParseInt(ctx.String("start_time_ns"), 10, 64)
113+
if err != nil {
114+
return fmt.Errorf("error parsing start timestamp: %w", err)
115+
}
116+
filter.StartTimestampNs = startTimestamp
117+
}
118+
102119
resp, err := client.ListSwaps(
103120
context.Background(), &looprpc.ListSwapsRequest{
104121
ListSwapFilter: filter,
122+
MaxSwaps: ctx.Uint64("max_swaps"),
105123
},
106124
)
107125
if err != nil {

loopd/swapclient_server.go

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"errors"
88
"fmt"
99
"reflect"
10+
"slices"
1011
"sort"
1112
"strings"
1213
"sync"
@@ -563,8 +564,11 @@ func (s *swapClientServer) ListSwaps(ctx context.Context,
563564
req *looprpc.ListSwapsRequest) (*looprpc.ListSwapsResponse, error) {
564565

565566
var (
566-
rpcSwaps = []*looprpc.SwapStatus{}
567-
idx = 0
567+
rpcSwaps = []*looprpc.SwapStatus{}
568+
rpcSwapInfo = []*loop.SwapInfo{}
569+
maxSwaps = int(req.MaxSwaps)
570+
nextStartTime = int64(0)
571+
canPage = false
568572
)
569573

570574
s.swapsLock.Lock()
@@ -580,14 +584,46 @@ func (s *swapClientServer) ListSwaps(ctx context.Context,
580584
continue
581585
}
582586

583-
rpcSwap, err := s.marshallSwap(ctx, &swp)
587+
rpcSwapInfo = append(rpcSwapInfo, &swp)
588+
}
589+
590+
// Sort the swaps by initiation time in ascending order (oldest first).
591+
slices.SortFunc(rpcSwapInfo, func(a, b *loop.SwapInfo) int {
592+
if a.InitiationTime.UnixNano() > b.InitiationTime.UnixNano() {
593+
return 1
594+
}
595+
if a.InitiationTime.UnixNano() < b.InitiationTime.UnixNano() {
596+
return -1
597+
}
598+
return 0
599+
})
600+
601+
// Apply the maxSwaps limit if specified.
602+
if maxSwaps > 0 && len(rpcSwapInfo) > maxSwaps {
603+
canPage = true
604+
rpcSwapInfo = rpcSwapInfo[:maxSwaps]
605+
}
606+
607+
// Marshal the filtered and limited swaps.
608+
for _, swp := range rpcSwapInfo {
609+
rpcSwap, err := s.marshallSwap(ctx, swp)
584610
if err != nil {
585611
return nil, err
586612
}
587613
rpcSwaps = append(rpcSwaps, rpcSwap)
588-
idx++
589614
}
590-
return &looprpc.ListSwapsResponse{Swaps: rpcSwaps}, nil
615+
616+
// Set the next start time for pagination if needed.
617+
if canPage && len(rpcSwaps) > 0 {
618+
// Use the initiation time of the last swap plus 1 nanosecond.
619+
nextStartTime = rpcSwaps[len(rpcSwaps)-1].InitiationTime + 1
620+
}
621+
622+
response := looprpc.ListSwapsResponse{
623+
Swaps: rpcSwaps,
624+
NextStartTime: nextStartTime,
625+
}
626+
return &response, nil
591627
}
592628

593629
// filterSwap filters the given swap based on the provided filter.
@@ -617,6 +653,11 @@ func filterSwap(swapInfo *loop.SwapInfo, filter *looprpc.ListSwapsFilter) bool {
617653
return false
618654
}
619655

656+
// If timestamp filters are set, only return swaps within the specified time range.
657+
if filter.StartTimestampNs > 0 && swapInfo.InitiationTime.UnixNano() < filter.StartTimestampNs {
658+
return false
659+
}
660+
620661
// If the swap is of type loop out and the outgoing channel filter is
621662
// set, we only return swaps that match the filter.
622663
if swapInfo.SwapType == swap.TypeOut && filter.OutgoingChanSet != nil {

0 commit comments

Comments
 (0)