Files
microdao-daarion/services/node-registry/app/schemas.py
Apple 3de3c8cb36 feat: Add presence heartbeat for Matrix online status
- matrix-gateway: POST /internal/matrix/presence/online endpoint
- usePresenceHeartbeat hook with activity tracking
- Auto away after 5 min inactivity
- Offline on page close/visibility change
- Integrated in MatrixChatRoom component
2025-11-27 00:19:40 -08:00

102 lines
3.3 KiB
Python

"""
Pydantic schemas for request/response validation
"""
from datetime import datetime
from typing import Optional, Dict, Any, List
from pydantic import BaseModel, Field, validator
class NodeBase(BaseModel):
"""Base node schema"""
node_id: str = Field(..., description="Unique node identifier")
node_name: str = Field(..., description="Human-readable node name")
node_role: str = Field(..., description="Node role: production, development, backup")
node_type: str = Field(..., description="Node type: router, gateway, worker")
ip_address: Optional[str] = Field(None, description="Public IP address")
local_ip: Optional[str] = Field(None, description="Local network IP")
hostname: Optional[str] = Field(None, description="Hostname")
metadata: Optional[Dict[str, Any]] = Field(default_factory=dict, description="Additional metadata")
class NodeRegister(BaseModel):
"""Schema for node registration"""
node_name: Optional[str] = Field(None, description="Node name (auto-generated if not provided)")
node_role: str = Field(default="worker", description="Node role")
node_type: str = Field(default="worker", description="Node type")
hostname: Optional[str] = None
ip_address: Optional[str] = None
local_ip: Optional[str] = None
capabilities: Optional[Dict[str, Any]] = Field(default_factory=dict, description="Node capabilities")
@validator('node_role')
def validate_role(cls, v):
allowed_roles = ['production', 'development', 'backup', 'worker']
if v not in allowed_roles:
raise ValueError(f'Role must be one of: {allowed_roles}')
return v
@validator('node_type')
def validate_type(cls, v):
allowed_types = ['router', 'gateway', 'worker', 'orchestrator']
if v not in allowed_types:
raise ValueError(f'Type must be one of: {allowed_types}')
return v
class NodeResponse(BaseModel):
"""Schema for node response"""
id: str
node_id: str
node_name: str
node_role: str
node_type: str
ip_address: Optional[str]
local_ip: Optional[str]
hostname: Optional[str]
status: str
last_heartbeat: Optional[datetime]
registered_at: datetime
updated_at: datetime
metadata: Dict[str, Any]
class Config:
orm_mode = True
class NodeListResponse(BaseModel):
"""Schema for list of nodes"""
nodes: List[NodeResponse]
total: int
class HeartbeatRequest(BaseModel):
"""Schema for heartbeat request"""
node_id: str = Field(..., description="Node identifier")
status: Optional[str] = Field("online", description="Node status")
metrics: Optional[Dict[str, Any]] = Field(default_factory=dict, description="System metrics")
class HeartbeatResponse(BaseModel):
"""Schema for heartbeat response"""
success: bool
node_id: str
timestamp: datetime
message: str
class NodeDiscoveryQuery(BaseModel):
"""Schema for node discovery query"""
role: Optional[str] = None
type: Optional[str] = None
status: Optional[str] = "online"
capability: Optional[str] = None
labels: Optional[List[str]] = None
class NodeDiscoveryResponse(BaseModel):
"""Schema for node discovery response"""
nodes: List[NodeResponse]
query: NodeDiscoveryQuery
total: int