Skip to content

Commit bf27bc1

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 bf27bc1

File tree

5 files changed

+991
-863
lines changed

5 files changed

+991
-863
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: 46 additions & 6 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+
swapInfos = []*loop.SwapInfo{}
570+
maxSwaps = int(req.MaxSwaps)
571+
nextStartTime = int64(0)
572+
canPage = false
568573
)
569574

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

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

593627
// filterSwap filters the given swap based on the provided filter.
@@ -617,6 +651,13 @@ func filterSwap(swapInfo *loop.SwapInfo, filter *looprpc.ListSwapsFilter) bool {
617651
return false
618652
}
619653

654+
// If timestamp filters are set, only return swaps within the specified time range.
655+
if filter.StartTimestampNs > 0 &&
656+
swapInfo.InitiationTime.UnixNano() < filter.StartTimestampNs {
657+
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 {
@@ -635,7 +676,6 @@ func filterSwap(swapInfo *loop.SwapInfo, filter *looprpc.ListSwapsFilter) bool {
635676
// which compares the underlying arrays.
636677
if !reflect.DeepEqual(swapInfo.OutgoingChanSet,
637678
filter.OutgoingChanSet) {
638-
639679
return false
640680
}
641681
}

0 commit comments

Comments
 (0)