stop doing the check_invoices thing on each call. do it once on lnbits starup and then rely on the invoices listener.

This commit is contained in:
fiatjaf 2021-03-21 17:57:33 -03:00
parent f27c2ebc21
commit 7e4a42e7ff
8 changed files with 61 additions and 70 deletions

View file

@ -11,7 +11,14 @@ from .commands import db_migrate, handle_assets
from .core import core_app from .core import core_app
from .helpers import get_valid_extensions, get_js_vendored, get_css_vendored, url_for_vendored from .helpers import get_valid_extensions, get_js_vendored, get_css_vendored, url_for_vendored
from .proxy_fix import ASGIProxyFix from .proxy_fix import ASGIProxyFix
from .tasks import run_deferred_async, invoice_listener, internal_invoice_listener, webhook_handler, grab_app_for_later from .tasks import (
run_deferred_async,
check_pending_payments,
invoice_listener,
internal_invoice_listener,
webhook_handler,
grab_app_for_later,
)
from .settings import WALLET from .settings import WALLET
secure_headers = SecureHeaders(hsts=False, xfo=False) secure_headers = SecureHeaders(hsts=False, xfo=False)
@ -123,8 +130,9 @@ def register_async_tasks(app):
@app.before_serving @app.before_serving
async def listeners(): async def listeners():
run_deferred_async(app.nursery) run_deferred_async(app.nursery)
app.nursery.start_soon(invoice_listener) app.nursery.start_soon(check_pending_payments)
app.nursery.start_soon(internal_invoice_listener) app.nursery.start_soon(invoice_listener, app.nursery)
app.nursery.start_soon(internal_invoice_listener, app.nursery)
@app.after_serving @app.after_serving
async def stop_listeners(): async def stop_listeners():

View file

@ -1,7 +1,7 @@
import json import json
import datetime import datetime
from uuid import uuid4 from uuid import uuid4
from typing import List, Optional, Dict from typing import List, Optional, Dict, Any
from lnbits import bolt11 from lnbits import bolt11
from lnbits.settings import DEFAULT_WALLET_NAME from lnbits.settings import DEFAULT_WALLET_NAME
@ -158,9 +158,9 @@ async def get_wallet_payment(wallet_id: str, payment_hash: str) -> Optional[Paym
return Payment.from_row(row) if row else None return Payment.from_row(row) if row else None
async def get_wallet_payments( async def get_payments(
wallet_id: str,
*, *,
wallet_id: Optional[str] = None,
complete: bool = False, complete: bool = False,
pending: bool = False, pending: bool = False,
outgoing: bool = False, outgoing: bool = False,
@ -171,41 +171,48 @@ async def get_wallet_payments(
Filters payments to be returned by complete | pending | outgoing | incoming. Filters payments to be returned by complete | pending | outgoing | incoming.
""" """
clause = "" args: Any = ()
if complete and pending:
clause += ""
elif complete:
clause += "AND ((amount > 0 AND pending = 0) OR amount < 0)"
elif pending:
clause += "AND pending = 1"
else:
raise TypeError("at least one of [complete, pending] must be True.")
clause += " " clause = []
if wallet_id:
clause.append("wallet = ?")
args = (wallet_id,)
if complete and pending:
pass
elif complete:
clause.append("((amount > 0 AND pending = 0) OR amount < 0)")
elif pending:
clause.append("pending = 1")
else:
pass
if outgoing and incoming: if outgoing and incoming:
clause += "" pass
elif outgoing: elif outgoing:
clause += "AND amount < 0" clause.append("amount < 0")
elif incoming: elif incoming:
clause += "AND amount > 0" clause.append("amount > 0")
else: else:
raise TypeError("at least one of [outgoing, incoming] must be True.") pass
clause += " "
if exclude_uncheckable: # checkable means it has a checking_id that isn't internal if exclude_uncheckable: # checkable means it has a checking_id that isn't internal
clause += "AND checking_id NOT LIKE 'temp_%' " clause.append("checking_id NOT LIKE 'temp_%'")
clause += "AND checking_id NOT LIKE 'internal_%' " clause.append("checking_id NOT LIKE 'internal_%'")
where = ""
if clause:
where = f"WHERE {' AND '.join(clause)}"
rows = await db.fetchall( rows = await db.fetchall(
f""" f"""
SELECT * SELECT *
FROM apipayments FROM apipayments
WHERE wallet = ? {clause} {where}
ORDER BY time DESC ORDER BY time DESC
""", """,
(wallet_id,), args,
) )
return [Payment.from_row(row) for row in rows] return [Payment.from_row(row) for row in rows]

View file

@ -60,10 +60,10 @@ class Wallet(NamedTuple):
incoming: bool = True, incoming: bool = True,
exclude_uncheckable: bool = False exclude_uncheckable: bool = False
) -> List["Payment"]: ) -> List["Payment"]:
from .crud import get_wallet_payments from .crud import get_payments
return await get_wallet_payments( return await get_payments(
self.id, wallet_id=self.id,
complete=complete, complete=complete,
pending=pending, pending=pending,
outgoing=outgoing, outgoing=outgoing,

View file

@ -604,19 +604,6 @@ new Vue({
]) ])
}) })
}, },
checkPendingPayments: function () {
var dismissMsg = this.$q.notify({
timeout: 0,
message: 'Checking pending transactions...'
})
LNbits.api
.checkPending(this.g.wallet)
.then(() => LNbits.api.fetchPayments)
.then(() => {
dismissMsg()
})
},
exportCSV: function () { exportCSV: function () {
LNbits.utils.exportCSV(this.paymentsTable.columns, this.payments) LNbits.utils.exportCSV(this.paymentsTable.columns, this.payments)
} }
@ -629,7 +616,6 @@ new Vue({
created: function () { created: function () {
this.fetchBalance() this.fetchBalance()
this.fetchPayments() this.fetchPayments()
this.checkPendingPayments()
}, },
mounted: function () { mounted: function () {
// show disclaimer // show disclaimer

View file

@ -13,7 +13,6 @@ from lnbits.decorators import api_check_wallet_key, api_validate_post_request
from .. import core_app, db from .. import core_app, db
from ..services import create_invoice, pay_invoice, perform_lnurlauth from ..services import create_invoice, pay_invoice, perform_lnurlauth
from ..crud import delete_expired_invoices
from ..tasks import sse_listeners from ..tasks import sse_listeners
@ -32,17 +31,6 @@ async def api_wallet():
) )
@core_app.route("/api/v1/checkpending", methods=["POST"])
@api_check_wallet_key("invoice")
async def api_checkpending():
g.nursery.start_soon(delete_expired_invoices)
for payment in await g.wallet.get_payments(complete=False, pending=True, exclude_uncheckable=True):
await payment.check_pending()
return "", HTTPStatus.NO_CONTENT
@core_app.route("/api/v1/payments", methods=["GET"]) @core_app.route("/api/v1/payments", methods=["GET"])
@api_check_wallet_key("invoice") @api_check_wallet_key("invoice")
async def api_payments(): async def api_payments():

View file

@ -4,7 +4,7 @@ from lnbits.core.models import Payment
from lnbits.core.crud import ( from lnbits.core.crud import (
create_account, create_account,
get_user, get_user,
get_wallet_payments, get_payments,
create_wallet, create_wallet,
delete_wallet, delete_wallet,
) )
@ -91,7 +91,7 @@ async def get_usermanager_wallets(user_id: str) -> List[Wallets]:
async def get_usermanager_wallet_transactions(wallet_id: str) -> List[Payment]: async def get_usermanager_wallet_transactions(wallet_id: str) -> List[Payment]:
return await get_wallet_payments(wallet_id=wallet_id, complete=True, pending=False, outgoing=True, incoming=True) return await get_payments(wallet_id=wallet_id, complete=True, pending=False, outgoing=True, incoming=True)
async def delete_usermanager_wallet(wallet_id: str, user_id: str) -> None: async def delete_usermanager_wallet(wallet_id: str, user_id: str) -> None:

View file

@ -52,9 +52,6 @@ window.LNbits = {
getWallet: function (wallet) { getWallet: function (wallet) {
return this.request('get', '/api/v1/wallet', wallet.inkey) return this.request('get', '/api/v1/wallet', wallet.inkey)
}, },
checkPending: function (wallet) {
return this.request('post', '/api/v1/checkpending', wallet.inkey)
},
getPayments: function (wallet) { getPayments: function (wallet) {
return this.request('get', '/api/v1/payments', wallet.inkey) return this.request('get', '/api/v1/payments', wallet.inkey)
}, },

View file

@ -4,7 +4,7 @@ from typing import Optional, List, Callable
from quart_trio import QuartTrio from quart_trio import QuartTrio
from lnbits.settings import WALLET from lnbits.settings import WALLET
from lnbits.core.crud import get_standalone_payment from lnbits.core.crud import get_payments, get_standalone_payment, delete_expired_invoices
main_app: Optional[QuartTrio] = None main_app: Optional[QuartTrio] = None
@ -54,18 +54,23 @@ async def webhook_handler():
internal_invoice_paid, internal_invoice_received = trio.open_memory_channel(0) internal_invoice_paid, internal_invoice_received = trio.open_memory_channel(0)
async def internal_invoice_listener(): async def internal_invoice_listener(nursery):
async with trio.open_nursery() as nursery:
async for checking_id in internal_invoice_received: async for checking_id in internal_invoice_received:
nursery.start_soon(invoice_callback_dispatcher, checking_id) nursery.start_soon(invoice_callback_dispatcher, checking_id)
async def invoice_listener(): async def invoice_listener(nursery):
async with trio.open_nursery() as nursery:
async for checking_id in WALLET.paid_invoices_stream(): async for checking_id in WALLET.paid_invoices_stream():
nursery.start_soon(invoice_callback_dispatcher, checking_id) nursery.start_soon(invoice_callback_dispatcher, checking_id)
async def check_pending_payments():
await delete_expired_invoices()
for payment in await get_payments(complete=False, pending=True, exclude_uncheckable=True):
print(" - checking pending", payment.checking_id)
await payment.check_pending()
async def invoice_callback_dispatcher(checking_id: str): async def invoice_callback_dispatcher(checking_id: str):
payment = await get_standalone_payment(checking_id) payment = await get_standalone_payment(checking_id)
if payment and payment.is_in: if payment and payment.is_in: