from __future__ import annotations from typing import List, Optional, TYPE_CHECKING from sqlalchemy.orm import Session, joinedload from packages.adapters.sqlalchemy_impl.models import WorkspaceMemberModel from packages.domain.entities import WorkspaceMember from packages.ports.workspace_member_repository import WorkspaceMemberRepository if TYPE_CHECKING: from packages.adapters.sqlalchemy_impl.models import UserModel class SQLAlchemyWorkspaceMemberRepository(WorkspaceMemberRepository): def __init__(self, session: Session): self.session = session def save(self, member: WorkspaceMember) -> None: model = self.session.get(WorkspaceMemberModel, member.id) if model is None: model = ( self.session.query(WorkspaceMemberModel) .filter( WorkspaceMemberModel.workspace_id == member.workspace_id, WorkspaceMemberModel.user_id == member.user_id, ) .first() ) if model is None: model = WorkspaceMemberModel(id=member.id) self.session.add(model) model.workspace_id = member.workspace_id model.user_id = member.user_id model.role = str(member.role) model.invited_by = member.invited_by model.joined_at = member.joined_at self.session.commit() self.session.refresh(model) def find_by_id(self, member_id: str) -> WorkspaceMember | None: return self._to_entity(self.session.get(WorkspaceMemberModel, member_id)) def find_by_workspace_and_user(self, workspace_id: str, user_id: str) -> WorkspaceMember | None: model = ( self.session.query(WorkspaceMemberModel) .filter(WorkspaceMemberModel.workspace_id == workspace_id, WorkspaceMemberModel.user_id == user_id) .first() ) return self._to_entity(model) def find_by_user(self, user_id: str) -> list[WorkspaceMember]: models = ( self.session.query(WorkspaceMemberModel) .filter(WorkspaceMemberModel.user_id == user_id) .order_by(WorkspaceMemberModel.joined_at.desc()) .all() ) return [self._to_entity(model) for model in models if model is not None] def find_by_workspace(self, workspace_id: str) -> list[WorkspaceMember]: """查找 workspace 的所有成员,使用 JOIN 预加载用户数据避免 N+1 查询问题。 P2-3 Fix: 使用 joinedload 预加载关联的用户数据, 这样在访问 member.user 时不会触发额外的数据库查询。 """ models = ( self.session.query(WorkspaceMemberModel) .filter(WorkspaceMemberModel.workspace_id == workspace_id) .options(joinedload(WorkspaceMemberModel.user)) # P2-3: JOIN 预加载用户数据 .order_by(WorkspaceMemberModel.joined_at.asc()) .all() ) return [self._to_entity(model) for model in models if model is not None] def count_by_workspace(self, workspace_id: str) -> int: return ( self.session.query(WorkspaceMemberModel).filter(WorkspaceMemberModel.workspace_id == workspace_id).count() ) def delete(self, member_id: str) -> bool: model = self.session.get(WorkspaceMemberModel, member_id) if model is None: return False self.session.delete(model) self.session.commit() return True @staticmethod def _to_entity(model: WorkspaceMemberModel | None) -> WorkspaceMember | None: if model is None: return None return WorkspaceMember( id=model.id, workspace_id=model.workspace_id, user_id=model.user_id, role=model.role, invited_by=model.invited_by, joined_at=model.joined_at, )