From 2aa1c084a56b2893b74b3f9021b0cd56c04a6808 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 5 Jun 2023 12:57:14 +0930 Subject: [PATCH] autoclean: allow dynamic changes to autoclean-cycle. Slightly less trivial: reset timer unless it's currently running callback. Signed-off-by: Rusty Russell --- doc/lightningd-config.5.md | 2 +- plugins/autoclean.c | 28 +++++++++++++++++++++++----- tests/test_plugin.py | 7 +++++-- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/doc/lightningd-config.5.md b/doc/lightningd-config.5.md index 1532ae12a7cf..deaab2cb29d6 100644 --- a/doc/lightningd-config.5.md +++ b/doc/lightningd-config.5.md @@ -442,7 +442,7 @@ accepted, and ignored. ### Cleanup control options: -* **autoclean-cycle**=*SECONDS* [plugin `autoclean`] +* **autoclean-cycle**=*SECONDS* [plugin `autoclean`, *dynamic*] Perform search for things to clean every *SECONDS* seconds (default 3600, or 1 hour, which is usually sufficient). diff --git a/plugins/autoclean.c b/plugins/autoclean.c index a82d34d57a8c..901b8ab51b49 100644 --- a/plugins/autoclean.c +++ b/plugins/autoclean.c @@ -61,6 +61,7 @@ static u64 cycle_seconds = 3600; static struct clean_info timer_cinfo; static u64 total_cleaned[NUM_SUBSYSTEM]; static struct plugin *plugin; +/* This is NULL if it's running now. */ static struct plugin_timer *cleantimer; static void do_clean_timer(void *unused); @@ -439,6 +440,7 @@ static struct command_result *do_clean(struct clean_info *cinfo) static void do_clean_timer(void *unused) { assert(timer_cinfo.cleanup_reqs_remaining == 0); + cleantimer = NULL; do_clean(&timer_cinfo); } @@ -587,6 +589,22 @@ static const char *init(struct plugin *p, return NULL; } +static char *cycle_seconds_option(struct plugin *plugin, const char *arg, + void *unused) +{ + char *problem = u64_option(plugin, arg, &cycle_seconds); + if (problem) + return problem; + + /* If timer is not running right now, reset it to new cycle_seconds */ + if (cleantimer) { + tal_free(cleantimer); + cleantimer = plugin_timer(plugin, time_from_sec(cycle_seconds), + do_clean_timer, NULL); + } + return NULL; +} + static const struct plugin_command commands[] = { { "autocleaninvoice", "payment", @@ -626,11 +644,11 @@ int main(int argc, char *argv[]) " invoices that have expired for at least" " this given seconds are cleaned", u64_option, &timer_cinfo.subsystem_age[EXPIREDINVOICES]), - plugin_option("autoclean-cycle", - "int", - "Perform cleanup every" - " given seconds", - u64_option, &cycle_seconds), + plugin_option_dynamic("autoclean-cycle", + "int", + "Perform cleanup every" + " given seconds", + cycle_seconds_option, NULL), plugin_option_dynamic("autoclean-succeededforwards-age", "int", "How old do successful forwards have to be before deletion (0 = never)", diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 0a77a942fd14..eb95bf64f44a 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -3128,8 +3128,7 @@ def test_commando_badrune(node_factory): def test_autoclean(node_factory): - l1, l2, l3 = node_factory.line_graph(3, opts={'autoclean-cycle': 10, - 'may_reconnect': True}, + l1, l2, l3 = node_factory.line_graph(3, opts={'may_reconnect': True}, wait_for_announce=True) # Under valgrind in CI, it can 50 seconds between creating invoice @@ -3162,6 +3161,8 @@ def test_autoclean(node_factory): assert len(l3.rpc.listinvoices('inv2')['invoices']) == 1 assert l3.rpc.listinvoices('inv1')['invoices'][0]['description'] == 'description1' + l3.rpc.setconfig('autoclean-cycle', 10) + # First it expires. wait_for(lambda: only_one(l3.rpc.listinvoices('inv1')['invoices'])['status'] == 'expired') # Now will get autocleaned @@ -3222,6 +3223,7 @@ def test_autoclean(node_factory): assert only_one(l1.rpc.listpays(inv5['bolt11'])['pays'])['status'] == 'failed' assert only_one(l1.rpc.listpays(inv4['bolt11'])['pays'])['status'] == 'complete' l1.rpc.setconfig('autoclean-failedpays-age', 1) + l1.rpc.setconfig('autoclean-cycle', 5) wait_for(lambda: l1.rpc.listpays(inv5['bolt11'])['pays'] == []) assert l1.rpc.autoclean_status()['autoclean']['failedpays']['cleaned'] == 1 @@ -3237,6 +3239,7 @@ def test_autoclean(node_factory): assert len(l2.rpc.listforwards()['forwards']) == 2 # Clean failed ones. + l2.rpc.setconfig('autoclean-cycle', 5) l2.rpc.setconfig('autoclean-failedforwards-age', 2) wait_for(lambda: l2.rpc.listforwards(status='failed')['forwards'] == [])