초기 커밋
This commit is contained in:
64
app/tasks/device_tasks.py
Normal file
64
app/tasks/device_tasks.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import structlog
|
||||
|
||||
from app.tasks.celery_app import celery_app
|
||||
|
||||
logger = structlog.get_logger("tasks.device")
|
||||
|
||||
|
||||
@celery_app.task(name="app.tasks.device_tasks.check_device_health")
|
||||
def check_device_health() -> dict:
|
||||
"""Check all devices for heartbeat timeout and mark offline."""
|
||||
import asyncio
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from sqlalchemy import select, update
|
||||
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from app.core.config import settings
|
||||
from app.core.constants import DeviceStatus
|
||||
from app.models.mariadb.device import Device
|
||||
|
||||
async def _check() -> int:
|
||||
engine = create_async_engine(settings.MARIADB_DSN)
|
||||
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
|
||||
threshold = datetime.utcnow() - timedelta(minutes=10)
|
||||
|
||||
async with async_session() as session:
|
||||
stmt = (
|
||||
update(Device)
|
||||
.where(
|
||||
Device.status == DeviceStatus.ONLINE,
|
||||
Device.last_seen_at < threshold,
|
||||
Device.is_deleted == False, # noqa: E712
|
||||
)
|
||||
.values(status=DeviceStatus.OFFLINE)
|
||||
)
|
||||
result = await session.execute(stmt)
|
||||
await session.commit()
|
||||
count = result.rowcount # type: ignore[assignment]
|
||||
|
||||
await engine.dispose()
|
||||
return count
|
||||
|
||||
count = asyncio.get_event_loop().run_until_complete(_check())
|
||||
logger.info("device_health_check", offline_count=count)
|
||||
return {"marked_offline": count}
|
||||
|
||||
|
||||
@celery_app.task(name="app.tasks.device_tasks.batch_firmware_update")
|
||||
def batch_firmware_update(device_uids: list[str], firmware_url: str) -> dict:
|
||||
"""Trigger OTA firmware update for a batch of devices."""
|
||||
import asyncio
|
||||
from app.communication.mqtt.publisher import publish_ota
|
||||
|
||||
async def _update() -> int:
|
||||
for uid in device_uids:
|
||||
await publish_ota(uid, {"url": firmware_url, "action": "update"})
|
||||
return len(device_uids)
|
||||
|
||||
count = asyncio.get_event_loop().run_until_complete(_update())
|
||||
logger.info("batch_firmware_update", count=count)
|
||||
return {"updated": count}
|
||||
Reference in New Issue
Block a user