This commit is contained in:
dni
2026-07-13 09:09:42 +02:00
parent 5514e35e18
commit 062246b577
+44 -37
View File
@@ -219,46 +219,55 @@ class TaskManager:
self, txid: str, queue: asyncio.Queue[OnchainTxEvent] self, txid: str, queue: asyncio.Queue[OnchainTxEvent]
) -> None: ) -> None:
"""Register a per-connection queue for a watched transaction.""" """Register a per-connection queue for a watched transaction."""
self._ws_tx_queues.setdefault(txid, []).append(queue) self._get_tx_tracker(txid).register_queue(queue)
if len(self._ws_tx_queues[txid]) == 1:
self.create_task(
self._transaction_tracker_dispatch(txid), name=f"ws_tx_{txid}"
)
def unregister_ws_tx_queue( def unregister_ws_tx_queue(
self, txid: str, queue: asyncio.Queue[OnchainTxEvent] self, txid: str, queue: asyncio.Queue[OnchainTxEvent]
) -> None: ) -> None:
"""Deregister a per-connection queue; cancel tracker when last one leaves.""" """Deregister a per-connection queue; cancel tracker when last one leaves."""
queues = self._ws_tx_queues.get(txid, []) tracker = self._tx_trackers.get(txid)
if queue in queues: if not tracker:
queues.remove(queue) return
if not queues: tracker.unregister_queue(queue)
self._ws_tx_queues.pop(txid, None) if not tracker.has_queues():
self._tx_trackers.pop(txid, None)
task = self.get_task(f"ws_tx_{txid}") task = self.get_task(f"ws_tx_{txid}")
if task: if task:
self.cancel_task(task) self.cancel_task(task)
def _get_tx_tracker(self, txid: str) -> "TransactionTracker":
tracker = self._tx_trackers.get(txid)
if tracker is None:
tracker = TransactionTracker(settings.lnbits_blockexplorer_electrum_url)
self._tx_trackers[txid] = tracker
if not self.get_task(f"ws_tx_{txid}"):
self.create_task(
self._transaction_tracker_dispatch(txid, tracker),
name=f"ws_tx_{txid}",
)
return tracker
def register_ws_block_queue(self, queue: asyncio.Queue[BlockInfo]) -> None: def register_ws_block_queue(self, queue: asyncio.Queue[BlockInfo]) -> None:
"""Register a per-connection queue for new block events.""" """Register a per-connection queue for new block events."""
self._ws_block_queues.append(queue) if self._block_tracker is None:
if len(self._ws_block_queues) == 1: self._block_tracker = BlockTracker(
if self._block_tracker is None: settings.lnbits_blockexplorer_electrum_url
self._block_tracker = BlockTracker( )
settings.lnbits_blockexplorer_electrum_url tracker = self._block_tracker
) was_empty = not tracker.has_queues()
tracker.register_queue(queue)
if was_empty:
self.create_task( self.create_task(
self._block_tracker.run( tracker.run(lambda: tracker.has_queues() and settings.lnbits_running),
self._dispatch_block_event,
lambda: bool(self._ws_block_queues) and settings.lnbits_running,
),
name="block_tracker", name="block_tracker",
) )
def unregister_ws_block_queue(self, queue: asyncio.Queue[BlockInfo]) -> None: def unregister_ws_block_queue(self, queue: asyncio.Queue[BlockInfo]) -> None:
"""Deregister a per-connection queue; cancel tracker when last one leaves.""" """Deregister a per-connection queue; cancel tracker when last one leaves."""
if queue in self._ws_block_queues: if not self._block_tracker:
self._ws_block_queues.remove(queue) return
if not self._ws_block_queues: self._block_tracker.unregister_queue(queue)
if not self._block_tracker.has_queues():
task = self.get_task("block_tracker") task = self.get_task("block_tracker")
if task: if task:
self.cancel_task(task) self.cancel_task(task)
@@ -353,16 +362,6 @@ class TaskManager:
if task.onchain_queue: if task.onchain_queue:
task.onchain_queue.put_nowait(event) task.onchain_queue.put_nowait(event)
async def _dispatch_onchain_tx_event(self, event: OnchainTxEvent) -> None:
"""Dispatches a tx event to all WS queues watching that txid."""
for q in list(self._ws_tx_queues.get(event.txid, [])):
q.put_nowait(event)
async def _dispatch_block_event(self, event: BlockInfo) -> None:
"""Dispatches a new block event to all WS queues."""
for q in list(self._ws_block_queues):
q.put_nowait(event)
async def _invoice_listener_consumer(self) -> None: async def _invoice_listener_consumer(self) -> None:
payment = await self.invoice_queue.get() payment = await self.invoice_queue.get()
logger.info(f"got a payment notification {payment.checking_id}") logger.info(f"got a payment notification {payment.checking_id}")
@@ -382,13 +381,21 @@ class TaskManager:
lambda: settings.lnbits_running, lambda: settings.lnbits_running,
) )
async def _transaction_tracker_dispatch(self, txid: str) -> None: async def _transaction_tracker_dispatch(
await TransactionTracker(settings.lnbits_blockexplorer_electrum_url).track( self, txid: str, tracker: "TransactionTracker"
) -> None:
"""Runs a shared tracker whose events are fanned out to its own
registered queues; no separate callback dispatch is needed."""
await tracker.track(
txid, txid,
self._dispatch_onchain_tx_event, self._noop_tx_callback,
lambda: txid in self._ws_tx_queues and settings.lnbits_running, lambda: tracker.has_queues() and settings.lnbits_running,
) )
@staticmethod
async def _noop_tx_callback(_: OnchainTxEvent) -> None:
return None
T = TypeVar("T", bound=BaseModel) T = TypeVar("T", bound=BaseModel)