configurable handle_missed_events

This commit is contained in:
Riccardo Balbo 2025-02-22 13:41:44 +00:00
commit 1f26e11e8b
4 changed files with 36 additions and 8 deletions

View file

@ -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

View file

@ -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"},
)

20
nwcp.py
View file

@ -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":
@ -126,6 +127,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: "
+ str(self.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

View file

@ -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)