autoclean: allow cleaning of paid invoices too.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2022-09-19 10:19:52 +09:30
committed by Christian Decker
parent 7da51892e8
commit 660c9af1d9
2 changed files with 36 additions and 9 deletions

View File

@@ -8,10 +8,12 @@
#include <plugins/libplugin.h> #include <plugins/libplugin.h>
enum subsystem { enum subsystem {
PAIDINVOICES,
EXPIREDINVOICES, EXPIREDINVOICES,
#define NUM_SUBSYSTEM (EXPIREDINVOICES + 1) #define NUM_SUBSYSTEM (EXPIREDINVOICES + 1)
}; };
static const char *subsystem_str[] = { static const char *subsystem_str[] = {
"paidinvoices",
"expiredinvoices", "expiredinvoices",
}; };
@@ -94,9 +96,9 @@ static struct command_result *clean_finished_one(struct command *cmd)
static struct command_result *del_done(struct command *cmd, static struct command_result *del_done(struct command *cmd,
const char *buf, const char *buf,
const jsmntok_t *result, const jsmntok_t *result,
ptrint_t *unused) ptrint_t *subsystemp)
{ {
num_cleaned[EXPIREDINVOICES]++; num_cleaned[ptr2int(subsystemp)]++;
return clean_finished_one(cmd); return clean_finished_one(cmd);
} }
@@ -124,11 +126,20 @@ static struct command_result *listinvoices_done(struct command *cmd,
json_for_each_arr(i, t, inv) { json_for_each_arr(i, t, inv) {
const jsmntok_t *status = json_get_member(buf, t, "status"); const jsmntok_t *status = json_get_member(buf, t, "status");
const jsmntok_t *time; const jsmntok_t *time;
enum subsystem subsys;
u64 invtime; u64 invtime;
if (json_tok_streq(buf, status, "expired")) if (json_tok_streq(buf, status, "expired")) {
subsys = EXPIREDINVOICES;
time = json_get_member(buf, t, "expires_at"); time = json_get_member(buf, t, "expires_at");
else } else if (json_tok_streq(buf, status, "paid")) {
subsys = PAIDINVOICES;
time = json_get_member(buf, t, "paid_at");
} else
continue;
/* Continue if we don't care. */
if (subsystem_age[subsys] == 0)
continue; continue;
if (!json_to_u64(buf, time, &invtime)) { if (!json_to_u64(buf, time, &invtime)) {
@@ -137,17 +148,17 @@ static struct command_result *listinvoices_done(struct command *cmd,
json_tok_full(buf, time)); json_tok_full(buf, time));
} }
if (invtime <= now - subsystem_age[EXPIREDINVOICES]) { if (invtime <= now - subsystem_age[subsys]) {
struct out_req *req; struct out_req *req;
const jsmntok_t *label = json_get_member(buf, t, "label"); const jsmntok_t *label = json_get_member(buf, t, "label");
req = jsonrpc_request_start(plugin, NULL, "delinvoice", req = jsonrpc_request_start(plugin, NULL, "delinvoice",
del_done, del_failed, del_done, del_failed,
int2ptr(EXPIREDINVOICES)); int2ptr(subsys));
json_add_tok(req->js, "label", label, buf); json_add_tok(req->js, "label", label, buf);
json_add_tok(req->js, "status", status, buf); json_add_tok(req->js, "status", status, buf);
send_outreq(plugin, req); send_outreq(plugin, req);
plugin_log(plugin, LOG_DBG, "Expiring %.*s", plugin_log(plugin, LOG_DBG, "Cleaning up %.*s",
json_tok_full_len(label), json_tok_full(buf, label)); json_tok_full_len(label), json_tok_full(buf, label));
cleanup_reqs_remaining++; cleanup_reqs_remaining++;
} }
@@ -163,7 +174,8 @@ static void do_clean(void *unused)
struct out_req *req = NULL; struct out_req *req = NULL;
assert(cleanup_reqs_remaining == 0); assert(cleanup_reqs_remaining == 0);
if (subsystem_age[EXPIREDINVOICES] != 0) { if (subsystem_age[EXPIREDINVOICES] != 0
|| subsystem_age[PAIDINVOICES] != 0) {
req = jsonrpc_request_start(plugin, NULL, "listinvoices", req = jsonrpc_request_start(plugin, NULL, "listinvoices",
listinvoices_done, cmd_failed, listinvoices_done, cmd_failed,
(char *)"listinvoices"); (char *)"listinvoices");

View File

@@ -2935,12 +2935,14 @@ def test_commando_badrune(node_factory):
def test_autoclean(node_factory): def test_autoclean(node_factory):
l1 = node_factory.get_node(options={'autoclean-cycle': 10}) l0, l1 = node_factory.line_graph(2, opts={'autoclean-cycle': 10,
'may_reconnect': True})
assert l1.rpc.autoclean_status('expiredinvoices')['autoclean']['expiredinvoices']['enabled'] is False assert l1.rpc.autoclean_status('expiredinvoices')['autoclean']['expiredinvoices']['enabled'] is False
l1.rpc.invoice(amount_msat=12300, label='inv1', description='description1', expiry=5) l1.rpc.invoice(amount_msat=12300, label='inv1', description='description1', expiry=5)
l1.rpc.invoice(amount_msat=12300, label='inv2', description='description2', expiry=20) l1.rpc.invoice(amount_msat=12300, label='inv2', description='description2', expiry=20)
l1.rpc.invoice(amount_msat=12300, label='inv3', description='description3', expiry=20) l1.rpc.invoice(amount_msat=12300, label='inv3', description='description3', expiry=20)
inv4 = l1.rpc.invoice(amount_msat=12300, label='inv4', description='description4', expiry=2000)
l1.rpc.autoclean(subsystem='expiredinvoices', age=2) l1.rpc.autoclean(subsystem='expiredinvoices', age=2)
assert l1.rpc.autoclean_status()['autoclean']['expiredinvoices']['enabled'] is True assert l1.rpc.autoclean_status()['autoclean']['expiredinvoices']['enabled'] is True
assert l1.rpc.autoclean_status()['autoclean']['expiredinvoices']['age'] == 2 assert l1.rpc.autoclean_status()['autoclean']['expiredinvoices']['age'] == 2
@@ -2983,8 +2985,21 @@ def test_autoclean(node_factory):
# Now enable: they will get autocleaned # Now enable: they will get autocleaned
l1.rpc.autoclean(subsystem='expiredinvoices', age=2) l1.rpc.autoclean(subsystem='expiredinvoices', age=2)
wait_for(lambda: len(l1.rpc.listinvoices()['invoices']) == 1)
assert l1.rpc.autoclean_status()['autoclean']['expiredinvoices']['cleaned'] == 3
# Reconnect, l0 pays invoice, we test paid expiry.
l1.rpc.connect(l0.info['id'], 'localhost', l0.port)
l0.rpc.pay(inv4['bolt11'])
assert l1.rpc.autoclean_status()['autoclean']['paidinvoices']['enabled'] is False
assert l1.rpc.autoclean_status()['autoclean']['paidinvoices']['cleaned'] == 0
l1.rpc.autoclean(subsystem='paidinvoices', age=1)
assert l1.rpc.autoclean_status()['autoclean']['paidinvoices']['enabled'] is True
wait_for(lambda: l1.rpc.listinvoices()['invoices'] == []) wait_for(lambda: l1.rpc.listinvoices()['invoices'] == [])
assert l1.rpc.autoclean_status()['autoclean']['expiredinvoices']['cleaned'] == 3 assert l1.rpc.autoclean_status()['autoclean']['expiredinvoices']['cleaned'] == 3
assert l1.rpc.autoclean_status()['autoclean']['paidinvoices']['cleaned'] == 1
def test_block_added_notifications(node_factory, bitcoind): def test_block_added_notifications(node_factory, bitcoind):