Files
yunke/yunke-server/app/analytics/health.py
T
2026-09-04 15:37:13 +08:00

49 lines
1.4 KiB
Python

"""E0-lite 数据健康——「数据截至」角标 + 实体新鲜度。
完整 E0(调度日志解析/成功率账本)二批;v1 用表新鲜度判定:
msg_daily_stats 当日有行 = 4h 消息链路活着。
"""
from __future__ import annotations
import datetime as dt
import sqlalchemy as sa
from sqlalchemy.ext.asyncio import AsyncSession
from app.db.models import (
ChatGroup,
Customer,
Media,
Message,
MomentsPost,
MsgDailyStats,
PhoneCall,
)
async def data_as_of(session: AsyncSession) -> int | None:
"""数据截至(ms-epoch)= MAX(msg_daily_stats.last_ts)。"""
val = (
await session.execute(sa.select(sa.func.max(MsgDailyStats.last_ts)))
).scalar_one_or_none()
return int(val) if val is not None else None
async def entity_freshness(session: AsyncSession) -> list[dict]:
"""各实体最后更新时间(UPDATED_AT 列 MAX;message 用 fetched_at)。"""
async def _max(col) -> dt.datetime | None:
return (await session.execute(sa.select(sa.func.max(col)))).scalar_one_or_none()
out = []
for name, col in (
("customer", Customer.updated_at),
("chat_group", ChatGroup.updated_at),
("phone_call", PhoneCall.updated_at),
("media", Media.updated_at),
("moments_post", MomentsPost.updated_at),
("message", Message.fetched_at),
):
out.append({"table": name, "last_seen": await _max(col)})
return out