Проект разделен на два репозитория
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import signal
|
||||
import socket
|
||||
import uuid
|
||||
|
||||
from app.config import load_settings
|
||||
from app.crm import CrmClient
|
||||
from app.domain import full_jitter_delay
|
||||
from app.engine import RetryableWorkflow, WorkflowEngine
|
||||
from app.repository import Repository
|
||||
|
||||
|
||||
async def worker_main() -> None:
|
||||
settings = load_settings()
|
||||
if not settings.enabled:
|
||||
return
|
||||
assert settings.database_url and settings.crm_rest_webhook_url and settings.portal_host
|
||||
repository = Repository(settings.database_url.get_secret_value(), settings.db_pool_size)
|
||||
crm = CrmClient(
|
||||
settings.crm_rest_webhook_url.get_secret_value(),
|
||||
settings.portal_host,
|
||||
settings.http_timeout_sec,
|
||||
)
|
||||
engine = WorkflowEngine(repository, crm, settings)
|
||||
stop = asyncio.Event()
|
||||
loop = asyncio.get_running_loop()
|
||||
for event in (signal.SIGINT, signal.SIGTERM):
|
||||
try:
|
||||
loop.add_signal_handler(event, stop.set)
|
||||
except NotImplementedError:
|
||||
pass
|
||||
worker_id = f"{socket.gethostname()}:{uuid.uuid4()}"
|
||||
try:
|
||||
while not stop.is_set():
|
||||
tasks = await repository.claim_tasks(
|
||||
worker_id, settings.claim_size, settings.lease_seconds
|
||||
)
|
||||
webhooks = await repository.claim_webhooks(
|
||||
worker_id, settings.claim_size, settings.lease_seconds
|
||||
)
|
||||
rebind_ids = await repository.pending_rebind_ids(settings.claim_size)
|
||||
if not tasks and not webhooks and not rebind_ids:
|
||||
try:
|
||||
await asyncio.wait_for(stop.wait(), timeout=1)
|
||||
except TimeoutError:
|
||||
continue
|
||||
for task in tasks:
|
||||
if stop.is_set():
|
||||
break
|
||||
await engine.process(task)
|
||||
for item in webhooks:
|
||||
if stop.is_set():
|
||||
break
|
||||
try:
|
||||
await engine.process_webhook(item)
|
||||
except RetryableWorkflow as exc:
|
||||
delay = exc.retry_after or full_jitter_delay(
|
||||
item.attempt_count + 1,
|
||||
settings.retry_base_seconds,
|
||||
settings.retry_max_seconds,
|
||||
)
|
||||
await repository.retry_webhook(item, exc.code, delay)
|
||||
for request_id in rebind_ids:
|
||||
if stop.is_set():
|
||||
break
|
||||
try:
|
||||
await engine.process_rebind(request_id)
|
||||
except RetryableWorkflow:
|
||||
continue
|
||||
finally:
|
||||
await crm.close()
|
||||
await repository.close()
|
||||
|
||||
|
||||
def run() -> None:
|
||||
asyncio.run(worker_main())
|
||||
Reference in New Issue
Block a user