| """Cluster heartbeat ring buffer — time-series snapshots of worker node health. |
| |
| Latest live metrics are stored on `worker_nodes` (see node.py); this table |
| keeps a rolling history for charts and alerts. Old rows can be pruned. |
| """ |
|
|
| from datetime import datetime, timezone |
| from sqlalchemy import String, Integer, BigInteger, SmallInteger, DateTime, ForeignKey, Index |
| from sqlalchemy.orm import Mapped, mapped_column |
| from mac.database import Base |
|
|
|
|
| def _utcnow(): |
| return datetime.now(timezone.utc) |
|
|
|
|
| class ClusterHeartbeat(Base): |
| """Time-series sample of one worker node's resource usage.""" |
| __tablename__ = "cluster_heartbeats" |
|
|
| id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True) |
| node_id: Mapped[str] = mapped_column( |
| String(36), ForeignKey("worker_nodes.id", ondelete="CASCADE"), nullable=False |
| ) |
| gpu_util: Mapped[int | None] = mapped_column(SmallInteger, nullable=True) |
| cpu_util: Mapped[int | None] = mapped_column(SmallInteger, nullable=True) |
| ram_used_mb: Mapped[int | None] = mapped_column(Integer, nullable=True) |
| vram_used_mb: Mapped[int | None] = mapped_column(Integer, nullable=True) |
| active_model: Mapped[str | None] = mapped_column(String(128), nullable=True) |
| queue_depth: Mapped[int | None] = mapped_column(SmallInteger, nullable=True) |
| recorded_at: Mapped[datetime] = mapped_column( |
| DateTime(timezone=True), default=_utcnow, nullable=False |
| ) |
|
|
| __table_args__ = ( |
| Index("idx_hb_node_time", "node_id", "recorded_at"), |
| ) |
|
|