""" PostgreSQL Workspace Repository 实现 """ from typing import Optional import psycopg2 from psycopg2.extras import RealDictCursor from packages.domain.entities import Workspace from packages.ports.workspace_repository import WorkspaceRepository class PostgresWorkspaceRepository(WorkspaceRepository): """Workspace 仓储 PostgreSQL 实现""" def __init__(self, connection_string: str): self.connection_string = connection_string def _get_connection(self): """获取数据库连接(使用连接池)""" from packages.adapters.postgres.connection_pool import PooledConnection return PooledConnection() def save(self, workspace: Workspace) -> None: """保存工作空间""" conn = self._get_connection() try: with conn.cursor() as cur: cur.execute( """ INSERT INTO workspaces ( id, name, owner_user_id, subscription_plan, subscription_status, subscription_expires_at, max_projects, max_storage_gb, used_storage_gb, created_at ) VALUES ( %(id)s, %(name)s, %(owner_user_id)s, %(subscription_plan)s, %(subscription_status)s, %(subscription_expires_at)s, %(max_projects)s, %(max_storage_gb)s, %(used_storage_gb)s, %(created_at)s ) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, subscription_plan = EXCLUDED.subscription_plan, subscription_status = EXCLUDED.subscription_status, subscription_expires_at = EXCLUDED.subscription_expires_at, max_projects = EXCLUDED.max_projects, max_storage_gb = EXCLUDED.max_storage_gb, used_storage_gb = EXCLUDED.used_storage_gb """, { "id": workspace.id, "name": workspace.name, "owner_user_id": workspace.owner_user_id, "subscription_plan": workspace.subscription_plan, "subscription_status": workspace.subscription_status, "subscription_expires_at": workspace.subscription_expires_at, "max_projects": workspace.max_projects, "max_storage_gb": workspace.max_storage_gb, "used_storage_gb": workspace.used_storage_gb, "created_at": workspace.created_at, }, ) conn.commit() finally: conn.close() def find_by_id(self, workspace_id: str) -> Optional[Workspace]: """根据 ID 查找工作空间""" conn = self._get_connection() try: with conn.cursor() as cur: cur.execute("SELECT * FROM workspaces WHERE id = %s", (workspace_id,)) row = cur.fetchone() if row: return self._row_to_workspace(row) return None finally: conn.close() def delete(self, workspace_id: str) -> bool: """删除工作空间""" conn = self._get_connection() try: with conn.cursor() as cur: cur.execute("DELETE FROM workspaces WHERE id = %s", (workspace_id,)) deleted = cur.rowcount > 0 conn.commit() return deleted finally: conn.close() def _row_to_workspace(self, row: dict) -> Workspace: """将数据库行转换为 Workspace 对象""" return Workspace( id=row["id"], name=row["name"], owner_user_id=row["owner_user_id"], subscription_plan=row["subscription_plan"], subscription_status=row["subscription_status"], subscription_expires_at=row["subscription_expires_at"], max_projects=row["max_projects"], max_storage_gb=row["max_storage_gb"], used_storage_gb=float(row["used_storage_gb"]), created_at=row["created_at"], )