Skip to content

Commit f04241b

Browse files
committed
bookkeeper: only read listchannelmoves 1000 entries at a time.
If we read all of them, we might get 1.6M at once (after initial migration). Then we submit a few hundred thousand simultaneous requests to lightningd, and it gets upset, queueing them all on the xpay command hook and running out of memory. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Changelog-Fixed: plugins: bookkeeper first invocation after migration from prior to 25.09 with very large databases will not crash.
1 parent 62bbc16 commit f04241b

1 file changed

Lines changed: 27 additions & 8 deletions

File tree

plugins/bkpr/bookkeeper.c

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ static struct refresh_info *use_rinfo(struct refresh_info *rinfo)
5353
return rinfo;
5454
}
5555

56+
/* Recursion */
57+
static struct command_result *limited_listchannelmoves(struct command *cmd,
58+
struct refresh_info *rinfo);
59+
5660
static struct command_result *rinfo_one_done(struct command *cmd,
5761
struct refresh_info *rinfo)
5862
{
@@ -123,16 +127,37 @@ static struct command_result *listchannelmoves_done(struct command *cmd,
123127
&be_index, sizeof(be_index),
124128
"create-or-replace",
125129
datastore_done, NULL, use_rinfo(rinfo));
130+
131+
/* If there might be more, try asking for more */
132+
if (moves->size != 0)
133+
limited_listchannelmoves(cmd, rinfo);
134+
126135
return rinfo_one_done(cmd, rinfo);
127136
}
128137

138+
/* We do 1000 at a time to avoid overwhelming lightningd */
139+
static struct command_result *limited_listchannelmoves(struct command *cmd,
140+
struct refresh_info *rinfo)
141+
{
142+
struct bkpr *bkpr = bkpr_of(cmd->plugin);
143+
struct out_req *req;
144+
145+
req = jsonrpc_request_start(cmd, "listchannelmoves",
146+
listchannelmoves_done,
147+
plugin_broken_cb,
148+
use_rinfo(rinfo));
149+
json_add_string(req->js, "index", "created");
150+
json_add_u64(req->js, "start", bkpr->channelmoves_index + 1);
151+
json_add_u64(req->js, "limit", 1000);
152+
return send_outreq(req);
153+
}
154+
129155
static struct command_result *listchainmoves_done(struct command *cmd,
130156
const char *method,
131157
const char *buf,
132158
const jsmntok_t *result,
133159
struct refresh_info *rinfo)
134160
{
135-
struct out_req *req;
136161
const jsmntok_t *moves, *t;
137162
size_t i;
138163
struct bkpr *bkpr = bkpr_of(cmd->plugin);
@@ -148,13 +173,7 @@ static struct command_result *listchainmoves_done(struct command *cmd,
148173
"create-or-replace",
149174
datastore_done, NULL, use_rinfo(rinfo));
150175

151-
req = jsonrpc_request_start(cmd, "listchannelmoves",
152-
listchannelmoves_done,
153-
plugin_broken_cb,
154-
use_rinfo(rinfo));
155-
json_add_string(req->js, "index", "created");
156-
json_add_u64(req->js, "start", bkpr->channelmoves_index + 1);
157-
send_outreq(req);
176+
limited_listchannelmoves(cmd, rinfo);
158177
return rinfo_one_done(cmd, rinfo);
159178
}
160179

0 commit comments

Comments
 (0)