from __future__ import annotations import time from app.clients.pywechat_client import ClientRegistry, OnlineStatus, registry from app.models.event import EventType, OutboundEvent from app.repositories.event_store import EventStore class HeartbeatService: def __init__(self, registry: ClientRegistry): self.registry = registry self.store: EventStore | None = None def heartbeat(self, account_id: str, payload: dict) -> dict: client = self.registry.get_or_create(account_id, payload.get("account_name")) client.heartbeat() if "risk_level" in payload: client.state.risk_level = payload["risk_level"] if "sent_count_today" in payload: client.state.sent_count_today = payload["sent_count_today"] event = OutboundEvent( event_type=EventType.HEARTBEAT, account_id=account_id, tenant_code=payload.get("tenant_code", "default"), data={ "login_status": client.state.login_status.value, "online_status": client.state.online_status.value, "risk_level": client.state.risk_level, "sent_count_today": client.state.sent_count_today, }, ) if self.store is not None: self.store.save(event) return {"success": True, "account_id": account_id} def check_offline_accounts(self, timeout_seconds: int = 120) -> list[dict]: now = time.time() offline = [] for client in self.registry.list_all(): last = client.state.last_heartbeat_at if client.state.online_status == OnlineStatus.ONLINE and (last is None or now - last > timeout_seconds): client.state.online_status = OnlineStatus.OFFLINE offline.append({"account_id": client.state.account_id, "last_heartbeat_at": last}) return offline heartbeat_service = HeartbeatService(registry) from app.repositories.event_store import event_store # noqa: E402 heartbeat_service.store = event_store