Skip to content

Commit e218873

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 e218873

File tree

5 files changed

+986
-862
lines changed

5 files changed

+986
-862
lines changed

cmd/loop/swaps.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ 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 in nanoseconds to select swaps initiated " +
45+
"after this time",
46+
},
3847
},
3948
}
4049

@@ -99,9 +108,19 @@ func listSwaps(ctx *cli.Context) error {
99108
filter.Label = ctx.String(labelFlag.Name)
100109
}
101110

111+
// Parse start timestamp if set.
112+
if ctx.IsSet("start_time_ns") {
113+
startTimestamp, err := strconv.ParseInt(ctx.String("start_time_ns"), 10, 64)
114+
if err != nil {
115+
return fmt.Errorf("error parsing start timestamp: %w", err)
116+
}
117+
filter.StartTimestampNs = startTimestamp
118+
}
119+
102120
resp, err := client.ListSwaps(
103121
context.Background(), &looprpc.ListSwapsRequest{
104122
ListSwapFilter: filter,
123+
MaxSwaps: ctx.Uint64("max_swaps"),
105124
},
106125
)
107126
if err != nil {

loopd/swapclient_server.go

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package loopd
22

33
import (
44
"bytes"
5+
"cmp"
56
"context"
67
"encoding/hex"
78
"errors"
89
"fmt"
910
"reflect"
11+
"slices"
1012
"sort"
1113
"strings"
1214
"sync"
@@ -563,8 +565,11 @@ func (s *swapClientServer) ListSwaps(ctx context.Context,
563565
req *looprpc.ListSwapsRequest) (*looprpc.ListSwapsResponse, error) {
564566

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

570575
s.swapsLock.Lock()
@@ -580,14 +585,40 @@ func (s *swapClientServer) ListSwaps(ctx context.Context,
580585
continue
581586
}
582587

583-
rpcSwap, err := s.marshallSwap(ctx, &swp)
588+
rpcSwapInfo = append(rpcSwapInfo, &swp)
589+
}
590+
591+
// Sort the swaps by initiation time in ascending order (oldest first).
592+
slices.SortFunc(rpcSwapInfo, func(a, b *loop.SwapInfo) int {
593+
return cmp.Compare(a.InitiationTime.UnixNano(), b.InitiationTime.UnixNano())
594+
})
595+
596+
// Apply the maxSwaps limit if specified.
597+
if maxSwaps > 0 && len(rpcSwapInfo) > maxSwaps {
598+
canPage = true
599+
rpcSwapInfo = rpcSwapInfo[:maxSwaps]
600+
}
601+
602+
// Marshal the filtered and limited swaps.
603+
for _, swp := range rpcSwapInfo {
604+
rpcSwap, err := s.marshallSwap(ctx, swp)
584605
if err != nil {
585606
return nil, err
586607
}
587608
rpcSwaps = append(rpcSwaps, rpcSwap)
588-
idx++
589609
}
590-
return &looprpc.ListSwapsResponse{Swaps: rpcSwaps}, nil
610+
611+
// Set the next start time for pagination if needed.
612+
if canPage && len(rpcSwaps) > 0 {
613+
// Use the initiation time of the last swap plus 1 nanosecond.
614+
nextStartTime = rpcSwaps[len(rpcSwaps)-1].InitiationTime + 1
615+
}
616+
617+
response := looprpc.ListSwapsResponse{
618+
Swaps: rpcSwaps,
619+
NextStartTime: nextStartTime,
620+
}
621+
return &response, nil
591622
}
592623

593624
// filterSwap filters the given swap based on the provided filter.
@@ -617,6 +648,11 @@ func filterSwap(swapInfo *loop.SwapInfo, filter *looprpc.ListSwapsFilter) bool {
617648
return false
618649
}
619650

651+
// If timestamp filters are set, only return swaps within the specified time range.
652+
if filter.StartTimestampNs > 0 && swapInfo.InitiationTime.UnixNano() < filter.StartTimestampNs {
653+
return false
654+
}
655+
620656
// If the swap is of type loop out and the outgoing channel filter is
621657
// set, we only return swaps that match the filter.
622658
if swapInfo.SwapType == swap.TypeOut && filter.OutgoingChanSet != nil {

0 commit comments

Comments
 (0)