From 1f26e11e8b98cef3e06fae71cd4c7aa3601f09e7 Mon Sep 17 00:00:00 2001 From: Riccardo Balbo Date: Sat, 22 Feb 2025 13:41:44 +0000 Subject: [PATCH] configurable handle_missed_events --- README.md | 7 +++++++ migrations.py | 14 ++++++++++++++ nwcp.py | 20 +++++++++++++------- tasks.py | 3 ++- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 605ec9d..c1f3ec7 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,13 @@ Configure the extension from the "Settings" page in the top right menu when logg | relay | URL of the nostr relay for dispatching and receiving NWC events. Use public relays or a custom one. Specify `nostrclient` to connect to the [nostrclient extension](https://github.com/lnbits/nostrclient). | nostrclient | | provider_key | Nostr secret key of the NWC Service Provider. | Random key generated on install | | relay_alias | Relay URL to display in pairing URLs. Set if different from `relay`. | Empty (uses the `relay` value) | +| handle_missed_events | Number of seconds to look back for processing events missed while offline. Setting it to 0 disables this functionality. | 0 | + + +> [!WARNING] +> +> Do not change handle_missed_events from its default value of 0 unless you fully understand its implications. While a non-zero value may improve service quality under unstable conditions (e.g., poor connectivity or unreliable power), it can also lead to unexpected behavior. For example, in shared or community lnbits instances, where users are unaware of this functionality, they might assume a payment has failed and attempt to pay a new invoice with a different wallet, only for the instance to come back online and process the original payment request, potentially leading to duplicate payments. For this reason, unless you are trying to tackle this specific issue, it is recommended to leave this setting at 0. + ### Using Nostrclient diff --git a/migrations.py b/migrations.py index 98dd934..6046c3c 100644 --- a/migrations.py +++ b/migrations.py @@ -105,3 +105,17 @@ async def m005_key_last_used(db): ALTER TABLE nwcprovider.keys ADD COLUMN last_used INTEGER; """ ) + + +async def m006_default_config3(db): + """ + Default config + """ + + await db.execute( + """ + INSERT OR REPLACE INTO nwcprovider.config + (key, value) VALUES ('handle_missed_events', :value); + """, + {"value": "0"}, + ) diff --git a/nwcp.py b/nwcp.py index 5aafbe8..8af7716 100644 --- a/nwcp.py +++ b/nwcp.py @@ -47,10 +47,11 @@ class MainSubscription: if event_id not in self.responses: self.responses.append(event_id) - def gc(self, expire: int = 3 * 60 * 60): + def gc(self, expire: Optional[int] = None): """ - Garbage collection, remove all the events that have a response older than expire seconds. + Garbage collection, remove all the events that have a response older than expire seconds (defaults to 1 hour if 0 or None) """ + expire = expire or 1 * 60 * 60 now = int(time.time()) deleted_ids = [] for [event_id, event] in self.events.items(): @@ -70,7 +71,7 @@ class MainSubscription: class NWCServiceProvider: - def __init__(self, private_key: Optional[str] = None, relay: Optional[str] = None): + def __init__(self, private_key: Optional[str] = None, relay: Optional[str] = None, handle_missed_events: int = 3 * 60 * 60): if not relay: # Connect to nostrclient relay = "nostrclient" if relay == "nostrclient": @@ -125,6 +126,11 @@ class NWCServiceProvider: # if True the instance is shutting down self.shutdown = False + + # process missed events that are not older than + # handle_missed_events seconds (0 to disable) + # (handles reboots) + self.handle_missed_events = handle_missed_events logger.info( "NWC Service is ready. relay: " @@ -136,7 +142,7 @@ class NWCServiceProvider: async def _gc_loop(self): while not self._is_shutting_down(): if self.sub: - self.sub.gc() + self.sub.gc(self.handle_missed_events) await asyncio.sleep(60) @@ -263,15 +269,15 @@ class NWCServiceProvider: req_filter = { "kinds": [23194], "#p": [self.public_key_hex], - # Since the last 3 hours (handles reboots) - "since": int(time.time()) - 3 * 60 * 60, + # Since the last handle_missed_events seconds (handles reboots) + "since": int(time.time()) - self.handle_missed_events } self.sub.requests_sub_id = self._get_new_subid() # Create responses subscription (needed to track previosly responded requests) res_filter = { "kinds": [23195], "authors": [self.public_key_hex], - "since": int(time.time()) - 3 * 60 * 60, + "since": int(time.time()) - self.handle_missed_events, } self.sub.responses_sub_id = self._get_new_subid() # Subscribe diff --git a/tasks.py b/tasks.py index 43175f2..5091656 100644 --- a/tasks.py +++ b/tasks.py @@ -503,7 +503,8 @@ async def _on_get_info( async def handle_nwc(): priv_key = await get_config_nwc("provider_key") relay = await get_config_nwc("relay") - nwcsp = NWCServiceProvider(priv_key, relay) + handle_missed_events = int(await get_config_nwc("handle_missed_events") or 0) + nwcsp = NWCServiceProvider(priv_key, relay, handle_missed_events) nwcsp.add_request_listener("pay_invoice", _on_pay_invoice) nwcsp.add_request_listener("multi_pay_invoice", _on_multi_pay_invoice) nwcsp.add_request_listener("make_invoice", _on_make_invoice)