938d26927f
- Agent per-server API Key认证 (agent.py) - JWT updated_at校验与会话超时 (auth_jwt.py) - 服务器凭据Fernet加密存储+密码脱敏 (servers.py) - WebSSH服务器级授权检查 (webssh.py) - Config同步去重+回滚机制 (sync_engine_v2.py) - DB层分页offset/limit (server_repo.py) - session.py logger修复 + @property死代码清理 - 心跳刷入rollback误用修复 (heartbeat_flush.py) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
99 lines
3.4 KiB
Python
99 lines
3.4 KiB
Python
"""Nexus — Server Repository (Async SQLAlchemy implementation)
|
|
Concrete implementation of ServerRepository protocol.
|
|
"""
|
|
|
|
from datetime import datetime, timezone
|
|
from typing import Optional, List, Tuple
|
|
from sqlalchemy import select, update, delete, func
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from server.domain.models import Server
|
|
|
|
|
|
class ServerRepositoryImpl:
|
|
"""Async SQLAlchemy implementation of Server data access"""
|
|
|
|
def __init__(self, session: AsyncSession):
|
|
self.session = session
|
|
|
|
async def get_by_id(self, id: int) -> Optional[Server]:
|
|
result = await self.session.execute(select(Server).where(Server.id == id))
|
|
return result.scalar_one_or_none()
|
|
|
|
async def get_all(self) -> List[Server]:
|
|
result = await self.session.execute(select(Server).order_by(Server.id))
|
|
return list(result.scalars().all())
|
|
|
|
async def get_paginated(
|
|
self,
|
|
category: Optional[str] = None,
|
|
offset: int = 0,
|
|
limit: int = 50,
|
|
) -> Tuple[List[Server], int]:
|
|
"""Get paginated server list with total count.
|
|
|
|
Returns (servers, total_count) — DB-level pagination for 2000+ servers.
|
|
"""
|
|
# Base query
|
|
base_query = select(Server)
|
|
if category:
|
|
base_query = base_query.where(Server.category == category)
|
|
|
|
# Count query
|
|
count_query = select(func.count(Server.id))
|
|
if category:
|
|
count_query = count_query.where(Server.category == category)
|
|
count_result = await self.session.execute(count_query)
|
|
total = count_result.scalar_one() or 0
|
|
|
|
# Paginated data query
|
|
data_query = base_query.order_by(Server.id).offset(offset).limit(limit)
|
|
result = await self.session.execute(data_query)
|
|
servers = list(result.scalars().all())
|
|
|
|
return servers, total
|
|
|
|
async def get_by_category(self, category: str) -> List[Server]:
|
|
result = await self.session.execute(
|
|
select(Server).where(Server.category == category).order_by(Server.id)
|
|
)
|
|
return list(result.scalars().all())
|
|
|
|
async def get_online(self) -> List[Server]:
|
|
result = await self.session.execute(
|
|
select(Server).where(Server.is_online == True).order_by(Server.id)
|
|
)
|
|
return list(result.scalars().all())
|
|
|
|
async def create(self, server: Server) -> Server:
|
|
self.session.add(server)
|
|
await self.session.commit()
|
|
await self.session.refresh(server)
|
|
return server
|
|
|
|
async def update(self, server: Server) -> Server:
|
|
await self.session.commit()
|
|
await self.session.refresh(server)
|
|
return server
|
|
|
|
async def delete(self, id: int) -> bool:
|
|
server = await self.get_by_id(id)
|
|
if server:
|
|
await self.session.delete(server)
|
|
await self.session.commit()
|
|
return True
|
|
return False
|
|
|
|
async def update_heartbeat(self, id: int, is_online: bool, system_info: str, agent_version: str) -> None:
|
|
"""Update server online status from Agent heartbeat"""
|
|
await self.session.execute(
|
|
update(Server)
|
|
.where(Server.id == id)
|
|
.values(
|
|
is_online=is_online,
|
|
last_heartbeat=datetime.now(timezone.utc),
|
|
system_info=system_info,
|
|
agent_version=agent_version,
|
|
)
|
|
)
|
|
await self.session.commit() |