Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f52e0e891 | ||
|
|
04ba5457fa |
@@ -1,5 +1,6 @@
|
||||
import asyncio
|
||||
import json
|
||||
import shutil
|
||||
from datetime import datetime, timezone
|
||||
from collections import deque
|
||||
from typing import Optional, Callable, Awaitable, Dict, Any
|
||||
@@ -8,6 +9,22 @@ from app.config import settings
|
||||
from app.internal.logger import logger
|
||||
from app.internal import credentials, key_pickup
|
||||
|
||||
|
||||
def disk_report(path: str) -> Dict[str, Optional[int]]:
|
||||
"""Free/total bytes of the filesystem holding `path` (node-26#41).
|
||||
|
||||
/recordings is a bind mount of the host checkout, so this is the host disk
|
||||
the recorder writes to and Docker's images/build cache live on. A full disk
|
||||
stopped node-002 recording for 17 days while it still showed Online. Nulls
|
||||
on error, so C2 overwrites a stale reading instead of keeping it.
|
||||
"""
|
||||
try:
|
||||
usage = shutil.disk_usage(path)
|
||||
except OSError:
|
||||
return {"disk_free_bytes": None, "disk_total_bytes": None}
|
||||
return {"disk_free_bytes": usage.free, "disk_total_bytes": usage.total}
|
||||
|
||||
|
||||
CommandCallback = Callable[[Dict[str, Any]], Awaitable[None]]
|
||||
ConfigCallback = Callable[[Dict[str, Any]], Awaitable[None]]
|
||||
ApiKeyCallback = Callable[[Dict[str, Any]], Awaitable[None]]
|
||||
@@ -372,6 +389,7 @@ class MQTTManager:
|
||||
count = devices.get("count") or None
|
||||
if count is not None:
|
||||
payload["sdr_count"] = count
|
||||
payload.update(disk_report(settings.recordings_path))
|
||||
self._publish(self._t_checkin, payload, qos=1)
|
||||
|
||||
def _publish(self, topic: str, payload: dict, qos: int = 0, retain: bool = False):
|
||||
|
||||
@@ -140,3 +140,16 @@ def test_build_client_does_not_touch_offline_buffer(monkeypatch):
|
||||
|
||||
assert list(mqtt_manager._offline_buffer) == [("nodes/test/metadata", {"call_id": "sentinel"})]
|
||||
mqtt_manager._offline_buffer.clear()
|
||||
|
||||
|
||||
def test_disk_report_reads_free_and_total(tmp_path):
|
||||
from app.internal.mqtt_manager import disk_report
|
||||
rep = disk_report(str(tmp_path))
|
||||
assert rep["disk_total_bytes"] > 0
|
||||
assert 0 <= rep["disk_free_bytes"] <= rep["disk_total_bytes"]
|
||||
|
||||
|
||||
def test_disk_report_nulls_when_path_unreadable(tmp_path):
|
||||
# node-26#41: nulls (not omitted keys) so C2 never keeps a stale reading.
|
||||
from app.internal.mqtt_manager import disk_report
|
||||
assert disk_report(str(tmp_path / "missing")) == {"disk_free_bytes": None, "disk_total_bytes": None}
|
||||
|
||||
Reference in New Issue
Block a user