Skip to content

Commit 7a620ea

Browse files
authored
Merge pull request #912 from kornpow/listswaps_paginate
add simple pagination to the ListSwaps command
2 parents 84820f2 + 6b3f270 commit 7a620ea

File tree

7 files changed

+1293
-862
lines changed

7 files changed

+1293
-862
lines changed

cmd/loop/swaps.go

+19
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

+46-5
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 {

0 commit comments

Comments
 (0)