Skip to content

Commit 23b32d3

Browse files
Merge pull request #419 from YusukeShimizu/rpc/paging-list-swaps-peers
Add paging to ListSwaps/ListPeers (bounded responses)
2 parents b39600d + a373f80 commit 23b32d3

File tree

9 files changed

+779
-337
lines changed

9 files changed

+779
-337
lines changed

cmd/peerswaplnd/pscli/main.go

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,19 @@ var (
9595
Usage: "node ID of the peer",
9696
Required: true,
9797
}
98+
listPageSizeFlag = cli.UintFlag{
99+
Name: "page_size",
100+
Usage: "max number of items to return (0 = all)",
101+
Value: 100,
102+
}
103+
listPageTokenFlag = cli.StringFlag{
104+
Name: "page_token",
105+
Usage: "paging token returned by the previous response",
106+
}
107+
listDescendingFlag = cli.BoolTFlag{
108+
Name: "descending",
109+
Usage: "order by created_at descending (newest first)",
110+
}
98111

99112
swapOutCommand = cli.Command{
100113
Name: "swapout",
@@ -131,15 +144,15 @@ var (
131144

132145
listSwapsCommand = cli.Command{
133146
Name: "listswaps",
134-
Usage: "lists all swaps",
135-
Flags: []cli.Flag{},
147+
Usage: "lists swaps (paged by default)",
148+
Flags: []cli.Flag{listPageSizeFlag, listPageTokenFlag, listDescendingFlag},
136149
Action: listSwaps,
137150
}
138151

139152
listPeersCommand = cli.Command{
140153
Name: "listpeers",
141-
Usage: "lists all peerswap-enabled peers",
142-
Flags: []cli.Flag{},
154+
Usage: "lists peerswap-enabled peers (paged by default)",
155+
Flags: []cli.Flag{listPageSizeFlag, listPageTokenFlag},
143156
Action: listPeers,
144157
}
145158
reloadPolicyFileCommand = cli.Command{
@@ -178,6 +191,7 @@ var (
178191
listActiveSwapsCommand = cli.Command{
179192
Name: "listactiveswaps",
180193
Usage: "list active swaps",
194+
Flags: []cli.Flag{listPageSizeFlag, listPageTokenFlag, listDescendingFlag},
181195
Action: listActiveSwaps,
182196
}
183197
allowSwapRequestsCommand = cli.Command{
@@ -344,7 +358,11 @@ func listSwaps(ctx *cli.Context) error {
344358
}
345359
defer cleanup()
346360

347-
res, err := client.ListSwaps(context.Background(), &peerswaprpc.ListSwapsRequest{})
361+
res, err := client.ListSwaps(context.Background(), &peerswaprpc.ListSwapsRequest{
362+
PageSize: uint32(ctx.Uint(listPageSizeFlag.Name)),
363+
PageToken: ctx.String(listPageTokenFlag.Name),
364+
Descending: ctx.Bool(listDescendingFlag.Name),
365+
})
348366
if err != nil {
349367
return err
350368
}
@@ -359,7 +377,10 @@ func listPeers(ctx *cli.Context) error {
359377
}
360378
defer cleanup()
361379

362-
res, err := client.ListPeers(context.Background(), &peerswaprpc.ListPeersRequest{})
380+
res, err := client.ListPeers(context.Background(), &peerswaprpc.ListPeersRequest{
381+
PageSize: uint32(ctx.Uint(listPageSizeFlag.Name)),
382+
PageToken: ctx.String(listPageTokenFlag.Name),
383+
})
363384
if err != nil {
364385
return err
365386
}
@@ -452,7 +473,11 @@ func listActiveSwaps(ctx *cli.Context) error {
452473
}
453474
defer cleanup()
454475

455-
res, err := client.ListActiveSwaps(context.Background(), &peerswaprpc.ListSwapsRequest{})
476+
res, err := client.ListActiveSwaps(context.Background(), &peerswaprpc.ListSwapsRequest{
477+
PageSize: uint32(ctx.Uint(listPageSizeFlag.Name)),
478+
PageToken: ctx.String(listPageTokenFlag.Name),
479+
Descending: ctx.Bool(listDescendingFlag.Name),
480+
})
456481
if err != nil {
457482
return err
458483
}

docs/usage.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,16 @@ pscli deletepeerpremiumrate --node_id [node_id] --asset [BTC|LBTC] --operation [
173173

174174
`listpeers` - A command that returns peers that support the PeerSwap protocol. It also gives statistics about received and sent swaps to a peer.
175175

176+
For LND:
177+
```bash
178+
# Page through results using next_page_token
179+
pscli listpeers --page_size 100
180+
pscli listpeers --page_size 100 --page_token "<next_page_token from previous response>"
181+
182+
# Return all peers (may be large)
183+
pscli listpeers --page_size 0
184+
```
185+
176186
Example output:
177187
```bash
178188
[
@@ -207,8 +217,24 @@ Example output:
207217

208218
`listswaps [detailed bool (optional)]` - A command that lists all swaps. If _detailed_ is set the output shows the swap data as it is saved in the database
209219

220+
For LND:
221+
```bash
222+
# Page through results using next_page_token (newest first by default)
223+
pscli listswaps --page_size 100
224+
pscli listswaps --page_size 100 --page_token "<next_page_token from previous response>"
225+
226+
# Return all swaps (may be large)
227+
pscli listswaps --page_size 0
228+
```
229+
210230
`listactiveswaps` - List all ongoing swaps, useful to track swaps when upgrading PeerSwap
211231

232+
For LND:
233+
```bash
234+
pscli listactiveswaps --page_size 100
235+
pscli listactiveswaps --page_size 100 --page_token "<next_page_token from previous response>"
236+
```
237+
212238
`listswaprequests` - Lists rejected swaps requested by peer nodes.
213239

214240
Example output:
@@ -278,4 +304,4 @@ Currently, it is not possible to set a label on the cln wallet
278304
For LND:
279305
To check the label attached to a transaction use `lncli listchaintxns`.
280306

281-
For LBTC transactions, elementsd `SetLabel` will attach a label to the associated address.
307+
For LBTC transactions, elementsd `SetLabel` will attach a label to the associated address.

peerswaprpc/paging.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package peerswaprpc
2+
3+
import (
4+
"strconv"
5+
6+
"google.golang.org/grpc/codes"
7+
"google.golang.org/grpc/status"
8+
)
9+
10+
const (
11+
defaultPageSize = 100
12+
maxPageSize = 1000
13+
)
14+
15+
func pagingBounds(total int, pageSize uint32, pageToken string, unpagedIfEmpty bool) (start, end int, nextPageToken string, err error) {
16+
if total < 0 {
17+
return 0, 0, "", status.Error(codes.Internal, "invalid total size")
18+
}
19+
20+
if unpagedIfEmpty && pageSize == 0 && pageToken == "" {
21+
return 0, total, "", nil
22+
}
23+
24+
if pageToken != "" {
25+
offset, err := strconv.Atoi(pageToken)
26+
if err != nil || offset < 0 {
27+
return 0, 0, "", status.Error(codes.InvalidArgument, "invalid page_token")
28+
}
29+
start = offset
30+
}
31+
32+
size := int(pageSize)
33+
if size <= 0 {
34+
size = defaultPageSize
35+
}
36+
if size > maxPageSize {
37+
size = maxPageSize
38+
}
39+
40+
if start > total {
41+
start = total
42+
}
43+
44+
end = start + size
45+
if end > total {
46+
end = total
47+
}
48+
49+
if end < total {
50+
nextPageToken = strconv.Itoa(end)
51+
}
52+
53+
return start, end, nextPageToken, nil
54+
}

peerswaprpc/paging_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package peerswaprpc
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
"google.golang.org/grpc/codes"
8+
"google.golang.org/grpc/status"
9+
)
10+
11+
func TestPagingBounds_UnpagedIfEmpty(t *testing.T) {
12+
start, end, nextToken, err := pagingBounds(10, 0, "", true)
13+
require.NoError(t, err)
14+
require.Equal(t, 0, start)
15+
require.Equal(t, 10, end)
16+
require.Equal(t, "", nextToken)
17+
}
18+
19+
func TestPagingBounds_DefaultPageSizeWhenTokenPresent(t *testing.T) {
20+
start, end, nextToken, err := pagingBounds(150, 0, "0", true)
21+
require.NoError(t, err)
22+
require.Equal(t, 0, start)
23+
require.Equal(t, defaultPageSize, end)
24+
require.Equal(t, "100", nextToken)
25+
}
26+
27+
func TestPagingBounds_PageSizeAndToken(t *testing.T) {
28+
start, end, nextToken, err := pagingBounds(10, 3, "3", true)
29+
require.NoError(t, err)
30+
require.Equal(t, 3, start)
31+
require.Equal(t, 6, end)
32+
require.Equal(t, "6", nextToken)
33+
}
34+
35+
func TestPagingBounds_LastPage(t *testing.T) {
36+
start, end, nextToken, err := pagingBounds(10, 3, "9", true)
37+
require.NoError(t, err)
38+
require.Equal(t, 9, start)
39+
require.Equal(t, 10, end)
40+
require.Equal(t, "", nextToken)
41+
}
42+
43+
func TestPagingBounds_TokenBeyondEnd(t *testing.T) {
44+
start, end, nextToken, err := pagingBounds(10, 3, "20", true)
45+
require.NoError(t, err)
46+
require.Equal(t, 10, start)
47+
require.Equal(t, 10, end)
48+
require.Equal(t, "", nextToken)
49+
}
50+
51+
func TestPagingBounds_InvalidToken(t *testing.T) {
52+
_, _, _, err := pagingBounds(10, 3, "not-a-number", true)
53+
require.Error(t, err)
54+
require.Equal(t, codes.InvalidArgument, status.Code(err))
55+
}
56+
57+
func TestPagingBounds_MaxPageSizeClamp(t *testing.T) {
58+
start, end, nextToken, err := pagingBounds(5000, 50000, "0", true)
59+
require.NoError(t, err)
60+
require.Equal(t, 0, start)
61+
require.Equal(t, maxPageSize, end)
62+
require.Equal(t, "1000", nextToken)
63+
}

0 commit comments

Comments
 (0)