feat: extension lifecycle hooks (__init__.py)
- restaurant_start spawns three permanent tasks:
1. invoice listener (LNBits payment settlement)
2. NostrClient bootstrap (after 10s grace for nostrclient ext)
3. Nostr sync loop (after 15s)
- restaurant_stop cancels tasks and closes the WS.
- Module-level nostr_client = None when nostrclient unavailable;
publishing helpers no-op gracefully in that case.
This commit is contained in:
parent
5c19cf6691
commit
3b046276f6
1 changed files with 89 additions and 0 deletions
89
__init__.py
Normal file
89
__init__.py
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
from fastapi import APIRouter
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
from .crud import db
|
||||||
|
from .tasks import wait_for_paid_invoices
|
||||||
|
from .views import restaurant_generic_router
|
||||||
|
from .views_api import restaurant_api_router
|
||||||
|
|
||||||
|
restaurant_ext: APIRouter = APIRouter(prefix="/restaurant", tags=["Restaurant"])
|
||||||
|
restaurant_ext.include_router(restaurant_generic_router)
|
||||||
|
restaurant_ext.include_router(restaurant_api_router)
|
||||||
|
|
||||||
|
restaurant_static_files = [
|
||||||
|
{
|
||||||
|
"path": "/restaurant/static",
|
||||||
|
"name": "restaurant_static",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
scheduled_tasks: list[asyncio.Task] = []
|
||||||
|
|
||||||
|
# Module-level NostrClient — None when nostrclient extension is unavailable.
|
||||||
|
# Populated by the lifecycle task below.
|
||||||
|
nostr_client = None
|
||||||
|
|
||||||
|
|
||||||
|
def restaurant_stop():
|
||||||
|
for task in scheduled_tasks:
|
||||||
|
try:
|
||||||
|
task.cancel()
|
||||||
|
except Exception as ex:
|
||||||
|
logger.warning(ex)
|
||||||
|
|
||||||
|
global nostr_client
|
||||||
|
if nostr_client:
|
||||||
|
asyncio.get_event_loop().create_task(nostr_client.stop())
|
||||||
|
|
||||||
|
|
||||||
|
def restaurant_start():
|
||||||
|
from lnbits.tasks import create_permanent_unique_task
|
||||||
|
|
||||||
|
# Invoice listener — settles orders on payment, kicks off print jobs.
|
||||||
|
task1 = create_permanent_unique_task("ext_restaurant", wait_for_paid_invoices)
|
||||||
|
scheduled_tasks.append(task1)
|
||||||
|
|
||||||
|
async def _start_nostr_client():
|
||||||
|
global nostr_client
|
||||||
|
await asyncio.sleep(10) # Wait for nostrclient to be ready
|
||||||
|
try:
|
||||||
|
from .nostr.nostr_client import NostrClient
|
||||||
|
|
||||||
|
nostr_client = NostrClient()
|
||||||
|
logger.info("[RESTAURANT] Starting NostrClient for menu + order sync")
|
||||||
|
await nostr_client.run_forever()
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"[RESTAURANT] NostrClient failed to start: {e}")
|
||||||
|
logger.info("[RESTAURANT] Restaurant will work without Nostr layer")
|
||||||
|
|
||||||
|
task2 = create_permanent_unique_task("ext_restaurant_nostr", _start_nostr_client)
|
||||||
|
scheduled_tasks.append(task2)
|
||||||
|
|
||||||
|
async def _sync_nostr_events():
|
||||||
|
global nostr_client
|
||||||
|
await asyncio.sleep(15)
|
||||||
|
if not nostr_client:
|
||||||
|
logger.info("[RESTAURANT] No NostrClient, skipping Nostr sync")
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
from .nostr_sync import wait_for_nostr_events
|
||||||
|
|
||||||
|
await wait_for_nostr_events(nostr_client)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[RESTAURANT] Nostr sync task failed: {e}")
|
||||||
|
|
||||||
|
task3 = create_permanent_unique_task(
|
||||||
|
"ext_restaurant_nostr_sync", _sync_nostr_events
|
||||||
|
)
|
||||||
|
scheduled_tasks.append(task3)
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"db",
|
||||||
|
"restaurant_ext",
|
||||||
|
"restaurant_start",
|
||||||
|
"restaurant_static_files",
|
||||||
|
"restaurant_stop",
|
||||||
|
]
|
||||||
Loading…
Add table
Add a link
Reference in a new issue