refactor: replace Trio with asyncio/uvloop
This commit is contained in:
+29
-43
@@ -1,3 +1,4 @@
|
||||
import asyncio
|
||||
import hashlib
|
||||
import json
|
||||
from binascii import unhexlify
|
||||
@@ -6,15 +7,15 @@ from typing import Dict, Optional, Union
|
||||
from urllib.parse import ParseResult, parse_qs, urlencode, urlparse, urlunparse
|
||||
|
||||
import httpx
|
||||
import trio
|
||||
from fastapi import Query, security
|
||||
from fastapi import Query, Request
|
||||
from fastapi.exceptions import HTTPException
|
||||
from fastapi.param_functions import Depends
|
||||
from fastapi.params import Body
|
||||
from sse_starlette.sse import EventSourceResponse
|
||||
from pydantic import BaseModel
|
||||
|
||||
from lnbits import bolt11, lnurl
|
||||
from lnbits.core.models import Wallet
|
||||
from lnbits.core.models import Payment, Wallet
|
||||
from lnbits.decorators import (WalletAdminKeyChecker, WalletInvoiceKeyChecker,
|
||||
WalletTypeInfo, get_key_type)
|
||||
from lnbits.helpers import url_for
|
||||
@@ -251,57 +252,42 @@ async def api_payments_pay_lnurl(data: CreateLNURLData):
|
||||
HTTPStatus.CREATED,
|
||||
)
|
||||
|
||||
@core_app.get("/api/v1/payments/sse")
|
||||
async def api_payments_sse(wallet: WalletTypeInfo = Depends(get_key_type)):
|
||||
async def subscribe(request: Request, wallet: Wallet):
|
||||
this_wallet_id = wallet.wallet.id
|
||||
|
||||
send_payment, receive_payment = trio.open_memory_channel(0)
|
||||
payment_queue = asyncio.Queue(0)
|
||||
|
||||
print("adding sse listener", send_payment)
|
||||
api_invoice_listeners.append(send_payment)
|
||||
print("adding sse listener", payment_queue)
|
||||
api_invoice_listeners.append(payment_queue)
|
||||
|
||||
send_event, event_to_send = trio.open_memory_channel(0)
|
||||
send_queue = asyncio.Queue(0)
|
||||
|
||||
async def payment_received() -> None:
|
||||
async for payment in receive_payment:
|
||||
if payment.wallet_id == this_wallet_id:
|
||||
await send_event.send(("payment-received", payment))
|
||||
|
||||
async def repeat_keepalive():
|
||||
await trio.sleep(1)
|
||||
while True:
|
||||
await send_event.send(("keepalive", ""))
|
||||
await trio.sleep(25)
|
||||
payment: Payment = await payment_queue.get()
|
||||
if payment.wallet_id == this_wallet_id:
|
||||
await send_queue.put(("payment-received", payment))
|
||||
|
||||
async with trio.open_nursery() as nursery:
|
||||
nursery.start_soon(payment_received)
|
||||
nursery.start_soon(repeat_keepalive)
|
||||
|
||||
async def send_events():
|
||||
try:
|
||||
async for typ, data in event_to_send:
|
||||
message = [f"event: {typ}".encode("utf-8")]
|
||||
asyncio.create_task(payment_received())
|
||||
|
||||
if data:
|
||||
jdata = json.dumps(dict(data._asdict(), pending=False))
|
||||
message.append(f"data: {jdata}".encode("utf-8"))
|
||||
try:
|
||||
while True:
|
||||
typ, data = await send_queue.get()
|
||||
message = [f"event: {typ}".encode("utf-8")]
|
||||
|
||||
yield b"\n".join(message) + b"\r\n\r\n"
|
||||
except trio.Cancelled:
|
||||
return
|
||||
if data:
|
||||
jdata = json.dumps(dict(data.dict(), pending=False))
|
||||
message.append(f"data: {jdata}".encode("utf-8"))
|
||||
|
||||
yield dict(data=jdata.encode("utf-8"), event=typ.encode("utf-8"))
|
||||
except asyncio.CancelledError:
|
||||
return
|
||||
|
||||
|
||||
@core_app.get("/api/v1/payments/sse")
|
||||
async def api_payments_sse(request: Request, wallet: WalletTypeInfo = Depends(get_key_type)):
|
||||
return EventSourceResponse(subscribe(request, wallet))
|
||||
|
||||
response = await make_response(
|
||||
send_events(),
|
||||
{
|
||||
"Content-Type": "text/event-stream",
|
||||
"Cache-Control": "no-cache",
|
||||
"X-Accel-Buffering": "no",
|
||||
"Connection": "keep-alive",
|
||||
"Transfer-Encoding": "chunked",
|
||||
},
|
||||
)
|
||||
response.timeout = None
|
||||
return response
|
||||
|
||||
@core_app.get("/api/v1/payments/{payment_hash}")
|
||||
async def api_payment(payment_hash, wallet: WalletTypeInfo = Depends(get_key_type)):
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import asyncio
|
||||
|
||||
from http import HTTPStatus
|
||||
from typing import Optional
|
||||
|
||||
@@ -9,7 +11,6 @@ from fastapi.responses import FileResponse, RedirectResponse
|
||||
from fastapi.routing import APIRouter
|
||||
from pydantic.types import UUID4
|
||||
from starlette.responses import HTMLResponse
|
||||
import trio
|
||||
|
||||
from lnbits.core import db
|
||||
from lnbits.helpers import template_renderer, url_for
|
||||
@@ -142,8 +143,7 @@ async def lnurl_full_withdraw_callback(request: Request):
|
||||
except:
|
||||
pass
|
||||
|
||||
async with trio.open_nursery() as n:
|
||||
n.start_soon(pay)
|
||||
asyncio.create_task(pay())
|
||||
|
||||
balance_notify = request.args.get("balanceNotify")
|
||||
if balance_notify:
|
||||
@@ -187,14 +187,14 @@ async def lnurlwallet(request: Request):
|
||||
user = await get_user(account.id, conn=conn)
|
||||
wallet = await create_wallet(user_id=user.id, conn=conn)
|
||||
|
||||
async with trio.open_nursery() as n:
|
||||
n.start_soon(
|
||||
redeem_lnurl_withdraw,
|
||||
asyncio.create_task(
|
||||
redeem_lnurl_withdraw(
|
||||
wallet.id,
|
||||
request.args.get("lightning"),
|
||||
"LNbits initial funding: voucher redeem.",
|
||||
{"tag": "lnurlwallet"},
|
||||
5, # wait 5 seconds before sending the invoice to the service
|
||||
5 # wait 5 seconds before sending the invoice to the service
|
||||
)
|
||||
)
|
||||
|
||||
return RedirectResponse(f"/wallet?usr={user.id}&wal={wallet.id}", status_code=status.HTTP_307_TEMPORARY_REDIRECT)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import trio
|
||||
import asyncio
|
||||
import datetime
|
||||
from http import HTTPStatus
|
||||
|
||||
@@ -26,27 +26,27 @@ async def api_public_payment_longpolling(payment_hash):
|
||||
except:
|
||||
return {"message": "Invalid bolt11 invoice."}, HTTPStatus.BAD_REQUEST
|
||||
|
||||
send_payment, receive_payment = trio.open_memory_channel(0)
|
||||
payment_queue = asyncio.Queue(0)
|
||||
|
||||
print("adding standalone invoice listener", payment_hash, send_payment)
|
||||
api_invoice_listeners.append(send_payment)
|
||||
print("adding standalone invoice listener", payment_hash, payment_queue)
|
||||
api_invoice_listeners.append(payment_queue)
|
||||
|
||||
response = None
|
||||
|
||||
async def payment_info_receiver(cancel_scope):
|
||||
async for payment in receive_payment:
|
||||
async for payment in payment_queue.get():
|
||||
if payment.payment_hash == payment_hash:
|
||||
nonlocal response
|
||||
response = ({"status": "paid"}, HTTPStatus.OK)
|
||||
cancel_scope.cancel()
|
||||
|
||||
async def timeouter(cancel_scope):
|
||||
await trio.sleep(45)
|
||||
await asyncio.sleep(45)
|
||||
cancel_scope.cancel()
|
||||
|
||||
async with trio.open_nursery() as nursery:
|
||||
nursery.start_soon(payment_info_receiver, nursery.cancel_scope)
|
||||
nursery.start_soon(timeouter, nursery.cancel_scope)
|
||||
|
||||
asyncio.create_task(payment_info_receiver())
|
||||
asyncio.create_task(timeouter())
|
||||
|
||||
if response:
|
||||
return response
|
||||
|
||||
Reference in New Issue
Block a user