Skip to content

Commit b8c50d9

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

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
@@ -2948,15 +2948,16 @@ void json_add_forwarding_object(struct json_stream *response,
29482948
json_object_end(response);
29492949
}
29502950

2951-
static void listforwardings_add_forwardings(struct json_stream *response,
2952-
struct wallet *wallet,
2951+
static void listforwardings_add_forwardings(struct command *cmd,
2952+
struct json_stream *response,
29532953
enum forward_status status,
29542954
const struct short_channel_id *chan_in,
29552955
const struct short_channel_id *chan_out)
29562956
{
29572957
const struct forwarding *forwardings;
29582958

2959-
forwardings = wallet_forwarded_payments_get(wallet, tmpctx, status, chan_in, chan_out);
2959+
forwardings = wallet_forwarded_payments_get(cmd->ld->wallet, tmpctx, status,
2960+
chan_in, chan_out, cmd->paginator);
29602961

29612962
json_array_start(response, "forwards");
29622963
for (size_t i=0; i<tal_count(forwardings); i++) {
@@ -2999,11 +3000,12 @@ static struct command_result *json_listforwards(struct command *cmd,
29993000
FORWARD_ANY),
30003001
p_opt("in_channel", param_short_channel_id, &chan_in),
30013002
p_opt("out_channel", param_short_channel_id, &chan_out),
3003+
p_paginator(&cmd->paginator),
30023004
NULL))
30033005
return command_param_failed();
30043006

30053007
response = json_stream_success(cmd);
3006-
listforwardings_add_forwardings(response, cmd->ld->wallet, *status, chan_in, chan_out);
3008+
listforwardings_add_forwardings(cmd, response, *status, chan_in, chan_out);
30073009

30083010
return command_success(cmd, response);
30093011
}

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>
@@ -620,7 +619,11 @@ struct command_result *param_bool(struct command *cmd UNNEEDED, const char *name
620619
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
621620
bool **b UNNEEDED)
622621
{ fprintf(stderr, "param_bool called!\n"); abort(); }
623-
/* Generated stub for param_channel_id */
622+
/* Generated stub for param_bool */
623+
struct command_result *param_paginator(struct command *cmd UNNEEDED, const char *name UNNEEDED,
624+
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
625+
struct jsonrpc_paginator **b UNNEEDED)
626+
{ fprintf(stderr, "param_paginator called!\n"); abort(); }/* Generated stub for param_channel_id */
624627
struct command_result *param_channel_id(struct command *cmd UNNEEDED,
625628
const char *name UNNEEDED,
626629
const char *buffer UNNEEDED,

wallet/wallet.c

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4599,7 +4599,8 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w,
45994599
const tal_t *ctx,
46004600
enum forward_status status,
46014601
const struct short_channel_id *chan_in,
4602-
const struct short_channel_id *chan_out)
4602+
const struct short_channel_id *chan_out,
4603+
const struct jsonrpc_paginator *paginator)
46034604
{
46044605
struct forwarding *results = tal_arr(ctx, struct forwarding, 0);
46054606
size_t count = 0;
@@ -4608,24 +4609,46 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w,
46084609
// placeholder for any parameter, the value doesn't matter because it's discarded by sql
46094610
const int any = -1;
46104611

4611-
stmt = db_prepare_v2(
4612-
w->db,
4613-
SQL("SELECT"
4614-
" state"
4615-
", in_msatoshi"
4616-
", out_msatoshi"
4617-
", in_channel_scid"
4618-
", out_channel_scid"
4619-
", in_htlc_id"
4620-
", out_htlc_id"
4621-
", received_time"
4622-
", resolved_time"
4623-
", failcode "
4624-
", forward_style "
4625-
"FROM forwards "
4626-
"WHERE (1 = ? OR state = ?) AND "
4627-
"(1 = ? OR in_channel_scid = ?) AND "
4628-
"(1 = ? OR out_channel_scid = ?)"));
4612+
if (paginator) {
4613+
stmt = db_prepare_v2(
4614+
w->db,
4615+
SQL("SELECT"
4616+
" state"
4617+
", in_msatoshi"
4618+
", out_msatoshi"
4619+
", in_channel_scid"
4620+
", out_channel_scid"
4621+
", in_htlc_id"
4622+
", out_htlc_id"
4623+
", received_time"
4624+
", resolved_time"
4625+
", failcode "
4626+
", forward_style "
4627+
"FROM forwards "
4628+
"WHERE (1 = ? OR state = ?) AND "
4629+
"(1 = ? OR in_channel_scid = ?) AND "
4630+
"(1 = ? OR out_channel_scid = ?)"
4631+
"LIMIT ? OFFSET ?"));
4632+
} else {
4633+
stmt = db_prepare_v2(
4634+
w->db,
4635+
SQL("SELECT"
4636+
" state"
4637+
", in_msatoshi"
4638+
", out_msatoshi"
4639+
", in_channel_scid"
4640+
", out_channel_scid"
4641+
", in_htlc_id"
4642+
", out_htlc_id"
4643+
", received_time"
4644+
", resolved_time"
4645+
", failcode "
4646+
", forward_style "
4647+
"FROM forwards "
4648+
"WHERE (1 = ? OR state = ?) AND "
4649+
"(1 = ? OR in_channel_scid = ?) AND "
4650+
"(1 = ? OR out_channel_scid = ?)"));
4651+
}
46294652

46304653
if (status == FORWARD_ANY) {
46314654
// any status
@@ -4657,6 +4680,12 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w,
46574680
db_bind_int(stmt, 5, any);
46584681
}
46594682

4683+
if (paginator) {
4684+
assert(paginator->limit && paginator->offset);
4685+
db_bind_int(stmt, 6, *paginator->limit);
4686+
db_bind_int(stmt, 7, *paginator->offset);
4687+
}
4688+
46604689
db_query_prepared(stmt);
46614690

46624691
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>
@@ -1369,7 +1370,8 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w,
13691370
const tal_t *ctx,
13701371
enum forward_status state,
13711372
const struct short_channel_id *chan_in,
1372-
const struct short_channel_id *chan_out);
1373+
const struct short_channel_id *chan_out,
1374+
const struct jsonrpc_paginator *paginator);
13731375

13741376
/**
13751377
* Delete a particular forward entry

0 commit comments

Comments
 (0)