Cashier creates an ETTN receipt in Checkbox bound to the TTN with payment control; Checkbox fiscalizes it itself when the parcel is paid for. - cash_registers (Fernet-encrypted license key / PIN) and receipts tables - Checkbox HTTP client + stub (ETTN does not work on test registers) - two-phase create via ARQ job, timeout reconciliation, cron status polling - /receipts and /cash-registers API, audit records - dashboard: per-order and bulk create, prepayment, cancel; cash registers page Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
54 lines
1.6 KiB
Python
54 lines
1.6 KiB
Python
"""Постановка задач ARQ worker'у из API.
|
||
|
||
Пул Redis создаётся лениво при первой задаче, а не в lifespan: недоступный
|
||
Redis не должен ронять старт API. Если задачу поставить не удалось, чек
|
||
остаётся `pending`, и cron `poll_receipts` подхватит его в течение минуты.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from typing import Any, Protocol
|
||
|
||
from arq import ArqRedis, create_pool
|
||
from arq.connections import RedisSettings
|
||
|
||
from app.core.config import settings
|
||
from app.core.logging import get_logger
|
||
|
||
log = get_logger(__name__)
|
||
|
||
|
||
class TaskQueue(Protocol):
|
||
async def enqueue(self, function: str, *args: Any) -> None: ...
|
||
|
||
|
||
class ArqTaskQueue:
|
||
def __init__(self) -> None:
|
||
self._pool: ArqRedis | None = None
|
||
|
||
async def enqueue(self, function: str, *args: Any) -> None:
|
||
try:
|
||
if self._pool is None:
|
||
self._pool = await create_pool(
|
||
RedisSettings.from_dsn(settings.redis_url), retry=0
|
||
)
|
||
await self._pool.enqueue_job(function, *args)
|
||
except Exception as exc: # noqa: BLE001 — см. докстринг модуля
|
||
log.warning("enqueue_failed", function=function, error=repr(exc))
|
||
|
||
async def close(self) -> None:
|
||
if self._pool is not None:
|
||
await self._pool.aclose()
|
||
self._pool = None
|
||
|
||
|
||
_queue = ArqTaskQueue()
|
||
|
||
|
||
def get_task_queue() -> TaskQueue:
|
||
return _queue
|
||
|
||
|
||
async def close_task_queue() -> None:
|
||
await _queue.close()
|