Skip to content

Commit e3312f2

Browse files
feat: add an example of paginator with limit and offset
Signed-off-by: Vincenzo Palazzo <[email protected]>
1 parent 7401722 commit e3312f2

File tree

7 files changed

+97
-58
lines changed

7 files changed

+97
-58
lines changed

lightningd/jsonrpc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ struct command {
4545
/* Optional output field filter. */
4646
struct json_filter *filter;
4747
/* Option filtering option */
48-
const struct jsonrpc_paginator *paginator;
48+
struct jsonrpc_paginator *paginator;
4949
};
5050

5151
/**

lightningd/peer_htlcs.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2927,15 +2927,16 @@ void json_add_forwarding_object(struct json_stream *response,
29272927
json_object_end(response);
29282928
}
29292929

2930-
static void listforwardings_add_forwardings(struct json_stream *response,
2931-
struct wallet *wallet,
2930+
static void listforwardings_add_forwardings(struct command *cmd,
2931+
struct json_stream *response,
29322932
enum forward_status status,
29332933
const struct short_channel_id *chan_in,
29342934
const struct short_channel_id *chan_out)
29352935
{
29362936
const struct forwarding *forwardings;
29372937

2938-
forwardings = wallet_forwarded_payments_get(wallet, tmpctx, status, chan_in, chan_out);
2938+
forwardings = wallet_forwarded_payments_get(cmd->ld->wallet, tmpctx, status,
2939+
chan_in, chan_out, cmd->paginator);
29392940

29402941
json_array_start(response, "forwards");
29412942
for (size_t i=0; i<tal_count(forwardings); i++) {
@@ -2978,11 +2979,12 @@ static struct command_result *json_listforwards(struct command *cmd,
29782979
FORWARD_ANY),
29792980
p_opt("in_channel", param_short_channel_id, &chan_in),
29802981
p_opt("out_channel", param_short_channel_id, &chan_out),
2982+
p_paginator(&cmd->paginator),
29812983
NULL))
29822984
return command_param_failed();
29832985

29842986
response = json_stream_success(cmd);
2985-
listforwardings_add_forwardings(response, cmd->ld->wallet, *status, chan_in, chan_out);
2987+
listforwardings_add_forwardings(cmd, response, *status, chan_in, chan_out);
29862988

29872989
return command_success(cmd, response);
29882990
}

plugins/topology.c

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -411,32 +411,6 @@ static struct command_result *json_listchannels(struct command *cmd,
411411
return send_outreq(cmd->plugin, req);
412412
}
413413

414-
static bool node_in_paginator(struct command *cmd, struct node_id *node_id)
415-
{
416-
struct jsonrpc_paginator *p;
417-
418-
p = cmd->paginator;
419-
if (p) {
420-
if (p->batch) {
421-
const char *target_id;
422-
const char *id;
423-
size_t i;
424-
425-
target_id = node_id_to_hexstr(cmd, node_id);
426-
/* FIXME: can we use the hash map to speed up the seach */
427-
for (i = 0; i < tal_count(p->batch); i++) {
428-
id = p->batch[i];
429-
if (strcmp(id, target_id) == 0)
430-
goto done;
431-
plugin_log(cmd->plugin, LOG_DBG, "not match %s != %s", target_id, id);
432-
}
433-
}
434-
return false;
435-
}
436-
done:
437-
return true;
438-
}
439-
440414
static void json_add_node(struct command *cmd,
441415
struct json_stream *js,
442416
const struct gossmap *gossmap,
@@ -446,8 +420,6 @@ static void json_add_node(struct command *cmd,
446420
u8 *nannounce;
447421

448422
gossmap_node_get_id(gossmap, n, &node_id);
449-
if (!node_in_paginator(cmd, &node_id))
450-
return;
451423
json_object_start(js, NULL);
452424
json_add_node_id(js, "nodeid", &node_id);
453425
nannounce = gossmap_node_get_announce(tmpctx, gossmap, n);
@@ -532,6 +504,17 @@ static struct command_result *json_listnodes(struct command *cmd,
532504
struct gossmap_node *n = gossmap_find_node(gossmap, id);
533505
if (n)
534506
json_add_node(cmd, js, gossmap, n);
507+
} else if (cmd->paginator) {
508+
const char **batch = cmd->paginator->batch;
509+
for (size_t i = 0; i < tal_count(batch); i++) {
510+
const char *idstr = batch[i];
511+
id = tal(tmpctx, struct node_id);
512+
; node_id_from_hexstr(idstr, sizeof(idstr), id);
513+
struct gossmap_node *n = gossmap_find_node(gossmap, id);
514+
if (n)
515+
json_add_node(cmd, js, gossmap, n);
516+
tal_free(id);
517+
}
535518
} else {
536519
for (struct gossmap_node *n = gossmap_first_node(gossmap);
537520
n;

tests/test_paginator.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
I think I'm getting to excited for this paginator API
33
that I think this deserve a own python test file!
44
"""
5+
import unittest
56
from fixtures import * # noqua: F401,F403
6-
7+
from utils import COMPAT
78

89
def test_listnodes_paginator(node_factory):
910
"""
@@ -13,9 +14,28 @@ def test_listnodes_paginator(node_factory):
1314
l1, l2, l3, _ = node_factory.line_graph(4, fundchannel=True, wait_for_announce=True)
1415
l1.rpc.jsonschemas = {}
1516

16-
nodes = l1.rpc.call("listnodes", { "batch": [l3.info["id"], l2.info["id"]] })
17+
nodes = l1.rpc.call("listnodes", { "paginator": { "batch": [l3.info["id"], l2.info["id"]] } })
1718
nodes_nobatch = l1.rpc.listnodes()
1819
print(nodes)
1920
print(nodes_nobatch)
2021
assert len(nodes["nodes"]) == 2
2122
assert len(nodes_nobatch["nodes"]) == 4
23+
24+
25+
@unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "Canned db used")
26+
@unittest.skipIf(not COMPAT, "needs COMPAT to convert obsolete db")
27+
@unittest.skipIf(TEST_NETWORK != 'regtest', "The DB migration is network specific due to the chain var.")
28+
def test_filter_listforwards_from_db(bitcoind, node_factory):
29+
"""This test is taken from the test_db and adapt to support the
30+
paginator API. This allow to have a static way to assert over the
31+
forwards without doing crazy things."""
32+
bitcoind.generate_block(113)
33+
l1 = node_factory.get_node(dbfile='v0.12.1-forward.sqlite3.xz',
34+
options={'database-upgrade': True})
35+
36+
assert l1.rpc.getinfo()['fees_collected_msat'] == 4
37+
assert len(l1.rpc.listforwards()['forwards']) == 4
38+
filter_forwards = l1.rpc.call("listforwards", { "paginator": { "limit": 2, "offset": 0 } })['forwards']
39+
assert len(filter_forwards) == 2
40+
41+

wallet/test/run-wallet.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include "config.h"
2-
#include <lightningd/log.h>
3-
2+
#include <lightningd/log.h>
43
#include "test_utils.h"
54
#include <ccan/tal/str/str.h>
65
#include <db/common.h>
@@ -617,7 +616,11 @@ struct command_result *param_bool(struct command *cmd UNNEEDED, const char *name
617616
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
618617
bool **b UNNEEDED)
619618
{ fprintf(stderr, "param_bool called!\n"); abort(); }
620-
/* Generated stub for param_channel_id */
619+
/* Generated stub for param_bool */
620+
struct command_result *param_paginator(struct command *cmd UNNEEDED, const char *name UNNEEDED,
621+
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
622+
struct jsonrpc_paginator **b UNNEEDED)
623+
{ fprintf(stderr, "param_paginator called!\n"); abort(); }/* Generated stub for param_channel_id */
621624
struct command_result *param_channel_id(struct command *cmd UNNEEDED,
622625
const char *name UNNEEDED,
623626
const char *buffer UNNEEDED,

wallet/wallet.c

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4528,7 +4528,8 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w,
45284528
const tal_t *ctx,
45294529
enum forward_status status,
45304530
const struct short_channel_id *chan_in,
4531-
const struct short_channel_id *chan_out)
4531+
const struct short_channel_id *chan_out,
4532+
const struct jsonrpc_paginator *paginator)
45324533
{
45334534
struct forwarding *results = tal_arr(ctx, struct forwarding, 0);
45344535
size_t count = 0;
@@ -4537,24 +4538,46 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w,
45374538
// placeholder for any parameter, the value doesn't matter because it's discarded by sql
45384539
const int any = -1;
45394540

4540-
stmt = db_prepare_v2(
4541-
w->db,
4542-
SQL("SELECT"
4543-
" state"
4544-
", in_msatoshi"
4545-
", out_msatoshi"
4546-
", in_channel_scid"
4547-
", out_channel_scid"
4548-
", in_htlc_id"
4549-
", out_htlc_id"
4550-
", received_time"
4551-
", resolved_time"
4552-
", failcode "
4553-
", forward_style "
4554-
"FROM forwards "
4555-
"WHERE (1 = ? OR state = ?) AND "
4556-
"(1 = ? OR in_channel_scid = ?) AND "
4557-
"(1 = ? OR out_channel_scid = ?)"));
4541+
if (paginator) {
4542+
stmt = db_prepare_v2(
4543+
w->db,
4544+
SQL("SELECT"
4545+
" state"
4546+
", in_msatoshi"
4547+
", out_msatoshi"
4548+
", in_channel_scid"
4549+
", out_channel_scid"
4550+
", in_htlc_id"
4551+
", out_htlc_id"
4552+
", received_time"
4553+
", resolved_time"
4554+
", failcode "
4555+
", forward_style "
4556+
"FROM forwards "
4557+
"WHERE (1 = ? OR state = ?) AND "
4558+
"(1 = ? OR in_channel_scid = ?) AND "
4559+
"(1 = ? OR out_channel_scid = ?)"
4560+
"LIMIT ? OFFSET ?"));
4561+
} else {
4562+
stmt = db_prepare_v2(
4563+
w->db,
4564+
SQL("SELECT"
4565+
" state"
4566+
", in_msatoshi"
4567+
", out_msatoshi"
4568+
", in_channel_scid"
4569+
", out_channel_scid"
4570+
", in_htlc_id"
4571+
", out_htlc_id"
4572+
", received_time"
4573+
", resolved_time"
4574+
", failcode "
4575+
", forward_style "
4576+
"FROM forwards "
4577+
"WHERE (1 = ? OR state = ?) AND "
4578+
"(1 = ? OR in_channel_scid = ?) AND "
4579+
"(1 = ? OR out_channel_scid = ?)"));
4580+
}
45584581

45594582
if (status == FORWARD_ANY) {
45604583
// any status
@@ -4586,6 +4609,12 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w,
45864609
db_bind_int(stmt, 5, any);
45874610
}
45884611

4612+
if (paginator) {
4613+
assert(paginator->limit && paginator->offset);
4614+
db_bind_int(stmt, 6, *paginator->limit);
4615+
db_bind_int(stmt, 7, *paginator->offset);
4616+
}
4617+
45894618
db_query_prepared(stmt);
45904619

45914620
for (count=0; db_step(stmt); count++) {

wallet/wallet.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <common/onion_encode.h>
77
#include <common/penalty_base.h>
88
#include <common/utxo.h>
9+
#include <common/jsonrpc_paginator.h>
910
#include <common/wallet.h>
1011
#include <lightningd/bitcoind.h>
1112
#include <lightningd/log.h>
@@ -1359,7 +1360,8 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w,
13591360
const tal_t *ctx,
13601361
enum forward_status state,
13611362
const struct short_channel_id *chan_in,
1362-
const struct short_channel_id *chan_out);
1363+
const struct short_channel_id *chan_out,
1364+
const struct jsonrpc_paginator *paginator);
13631365

13641366
/**
13651367
* Delete a particular forward entry

0 commit comments

Comments
 (0)