feat: add Mine Map v1
This commit is contained in:
1 parent
548051899e
commit
60a831950c
16 files changed
+2027
-163
No files matched your search
@@ -0,0 +1,87 @@
|
||||
"""Mine Map read-model composition independent of HTTP."""
|
||||
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
from uuid import UUID
|
||||
|
||||
from app.locations.models import (
|
||||
MapActiveRepair,
|
||||
MapPosition,
|
||||
MapRoom,
|
||||
MapSite,
|
||||
MapVirtualMiner,
|
||||
MineMapData,
|
||||
MineMapMeta,
|
||||
MineMapResponse,
|
||||
)
|
||||
from app.locations.repository import LocationMapRepository
|
||||
|
||||
|
||||
MINER_FIELDS = {
|
||||
"miner_id", "asset_id", "current_mac", "expected_mac", "current_ip", "miner_status",
|
||||
"status",
|
||||
"hostname", "miner_sn", "power_sn", "model", "miner_type",
|
||||
"firmware_version", "lifecycle_status", "last_seen_at", "asset_state",
|
||||
"observed_at", "hashrate_ths", "power_w", "chip_temp_max_c",
|
||||
"chip_temp_avg_c", "hash_stable", "pool_rejected_percent",
|
||||
}
|
||||
|
||||
|
||||
class LocationMapService:
|
||||
def __init__(self, repository: LocationMapRepository):
|
||||
self.repository = repository
|
||||
|
||||
@staticmethod
|
||||
def _repair(row: dict[str, Any]) -> MapActiveRepair | None:
|
||||
repair_id = row.pop("active_repair_id", None)
|
||||
status = row.pop("active_repair_status", None)
|
||||
reason = row.pop("active_repair_reason", None)
|
||||
if repair_id is None:
|
||||
return None
|
||||
return MapActiveRepair(id=repair_id, status=status, reason=reason)
|
||||
|
||||
@classmethod
|
||||
def _redact(cls, row: dict[str, Any]) -> dict[str, Any]:
|
||||
redacted = dict(row)
|
||||
for field in MINER_FIELDS:
|
||||
redacted[field] = None
|
||||
redacted["active_repair_id"] = None
|
||||
redacted["active_repair_status"] = None
|
||||
redacted["active_repair_reason"] = None
|
||||
return redacted
|
||||
|
||||
def get_map(
|
||||
self,
|
||||
*,
|
||||
site_id: UUID | None = None,
|
||||
room_id: UUID | None = None,
|
||||
include_miner_details: bool,
|
||||
) -> MineMapResponse:
|
||||
rows = self.repository.read_map(site_id=site_id, room_id=room_id)
|
||||
positions = []
|
||||
for source in rows["positions"]:
|
||||
row = dict(source) if include_miner_details else self._redact(source)
|
||||
row["active_repair"] = self._repair(row)
|
||||
positions.append(MapPosition.model_validate(row))
|
||||
virtual_miners = []
|
||||
if include_miner_details:
|
||||
for source in rows["virtual_miners"]:
|
||||
row = dict(source)
|
||||
row["active_repair"] = self._repair(row)
|
||||
virtual_miners.append(MapVirtualMiner.model_validate(row))
|
||||
return MineMapResponse(
|
||||
data=MineMapData(
|
||||
sites=[MapSite.model_validate(row) for row in rows["sites"]],
|
||||
rooms=[MapRoom.model_validate(row) for row in rows["rooms"]],
|
||||
positions=positions,
|
||||
virtual_miners=virtual_miners,
|
||||
),
|
||||
meta=MineMapMeta(
|
||||
generated_at=datetime.now(timezone.utc),
|
||||
site_id=site_id,
|
||||
room_id=room_id,
|
||||
position_count=len(positions),
|
||||
virtual_miner_count=len(virtual_miners),
|
||||
miner_details_included=include_miner_details,
|
||||
),
|
||||
)
|
||||
Reference in new issue
Block a user