feat: back off pending payment polling
This commit is contained in:
parent
f4b96107fa
commit
e9d3c48aec
2 changed files with 16 additions and 8 deletions
11
tasks.py
11
tasks.py
|
|
@ -34,7 +34,9 @@ from .paranoia import (
|
||||||
)
|
)
|
||||||
from .permission import nwc_permissions
|
from .permission import nwc_permissions
|
||||||
|
|
||||||
PAYMENT_STATUS_POLL_INTERVAL_SECONDS = 1.0
|
PAYMENT_STATUS_POLL_INITIAL_INTERVAL_SECONDS = 1.0
|
||||||
|
PAYMENT_STATUS_POLL_MAX_INTERVAL_SECONDS = 60.0
|
||||||
|
PAYMENT_STATUS_POLL_BACKOFF_MULTIPLIER = 2.0
|
||||||
|
|
||||||
|
|
||||||
async def _check(nwc: NWCKey | None, method: str) -> dict | None:
|
async def _check(nwc: NWCKey | None, method: str) -> dict | None:
|
||||||
|
|
@ -112,6 +114,7 @@ async def _process_invoice(
|
||||||
True # currently required by nip 47 specs, might change in future
|
True # currently required by nip 47 specs, might change in future
|
||||||
)
|
)
|
||||||
payment_status: PaymentStatus | None = None
|
payment_status: PaymentStatus | None = None
|
||||||
|
poll_interval = PAYMENT_STATUS_POLL_INITIAL_INTERVAL_SECONDS
|
||||||
while wait_for_preimage:
|
while wait_for_preimage:
|
||||||
payment_status = await check_transaction_status(wallet_id, payment_hash)
|
payment_status = await check_transaction_status(wallet_id, payment_hash)
|
||||||
if payment_status.success:
|
if payment_status.success:
|
||||||
|
|
@ -124,7 +127,11 @@ async def _process_invoice(
|
||||||
},
|
},
|
||||||
"in_budget": in_budget,
|
"in_budget": in_budget,
|
||||||
}
|
}
|
||||||
await asyncio.sleep(PAYMENT_STATUS_POLL_INTERVAL_SECONDS)
|
await asyncio.sleep(poll_interval)
|
||||||
|
poll_interval = min(
|
||||||
|
poll_interval * PAYMENT_STATUS_POLL_BACKOFF_MULTIPLIER,
|
||||||
|
PAYMENT_STATUS_POLL_MAX_INTERVAL_SECONDS,
|
||||||
|
)
|
||||||
if not payment_status:
|
if not payment_status:
|
||||||
raise Exception("Payment status not found")
|
raise Exception("Payment status not found")
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -32,29 +32,30 @@ async def test_process_invoice_returns_payment_failed_on_failed_status(monkeypat
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_process_invoice_polls_pending_payment_at_sustainable_interval(
|
async def test_process_invoice_backs_off_pending_payment_polling_to_configured_max(
|
||||||
monkeypatch,
|
monkeypatch,
|
||||||
):
|
):
|
||||||
async def fake_tracked_spend_nwc(*args, **kwargs):
|
async def fake_tracked_spend_nwc(*args, **kwargs):
|
||||||
return True, "a" * 64
|
return True, "a" * 64
|
||||||
|
|
||||||
|
pending = SimpleNamespace(success=False, failed=False)
|
||||||
statuses = iter(
|
statuses = iter(
|
||||||
[
|
[pending] * 8
|
||||||
SimpleNamespace(success=False, failed=False),
|
+ [
|
||||||
SimpleNamespace(
|
SimpleNamespace(
|
||||||
success=True,
|
success=True,
|
||||||
failed=False,
|
failed=False,
|
||||||
preimage="b" * 64,
|
preimage="b" * 64,
|
||||||
fee_msat=10,
|
fee_msat=10,
|
||||||
paid=True,
|
paid=True,
|
||||||
),
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
async def fake_check_transaction_status(wallet_id: str, payment_hash: str):
|
async def fake_check_transaction_status(wallet_id: str, payment_hash: str):
|
||||||
return next(statuses)
|
return next(statuses)
|
||||||
|
|
||||||
sleep_calls = []
|
sleep_calls: list[float] = []
|
||||||
|
|
||||||
async def fake_sleep(delay: float):
|
async def fake_sleep(delay: float):
|
||||||
sleep_calls.append(delay)
|
sleep_calls.append(delay)
|
||||||
|
|
@ -73,7 +74,7 @@ async def test_process_invoice_polls_pending_payment_at_sustainable_interval(
|
||||||
description="test",
|
description="test",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert sleep_calls == [tasks.PAYMENT_STATUS_POLL_INTERVAL_SECONDS]
|
assert sleep_calls == [1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 60.0, 60.0]
|
||||||
assert result["preimage"] == "b" * 64
|
assert result["preimage"] == "b" * 64
|
||||||
assert result["fee_msats"] == 10
|
assert result["fee_msats"] == 10
|
||||||
assert result["paid"] is True
|
assert result["paid"] is True
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue