Skip to content
This repository has been archived by the owner on Apr 14, 2024. It is now read-only.

Commit

Permalink
Fix lazy joined relationships
Browse files Browse the repository at this point in the history
  • Loading branch information
OlegYurchik committed Mar 26, 2024
1 parent 00fabd1 commit 1fc45cc
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 19 deletions.
14 changes: 2 additions & 12 deletions sapphire/database/models/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,14 @@ class Project(Base):
history: Mapped[list["ProjectHistory"]] = relationship(
back_populates="project",
order_by="desc(ProjectHistory.created_at)",
lazy=False,
)
last_history: Mapped["ProjectHistory"] = relationship(
back_populates="project",
order_by="desc(ProjectHistory.created_at)",
lazy=False,
)
positions: Mapped[list["Position"]] = relationship(back_populates="project", join_depth=2,
lazy=False)
reviews: Mapped[list["Review"]] = relationship(back_populates="project", lazy=False)
positions: Mapped[list["Position"]] = relationship(back_populates="project")
reviews: Mapped[list["Review"]] = relationship(back_populates="project")
owner: Mapped[User] = relationship(foreign_keys=[owner_id], lazy=False)

__table_args__ = (
Expand All @@ -62,14 +60,6 @@ class Project(Base):
def status(self) -> ProjectStatusEnum:
return self.last_history.status

@property
def joined_participants(self) -> list["Participant"]:
return [
participant
for position in self.positions
for participant in position.joined_participants
]


class ProjectHistory(Base):
__tablename__ = "projects_history"
Expand Down
10 changes: 10 additions & 0 deletions sapphire/projects/api/rest/participants/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,13 @@ async def create_participant(
if participant_user is None:
logger.error("Participant user not exist")
raise HTTPInternalServerError()
project_joined_participants = await database_service.get_project_joined_participants(
session=session,
project=position.project,
)
await broker_service.send_participant_requested(
project=position.project,
project_joined_participants=project_joined_participants,
participant=participant,
participant_email=participant_user.email,
owner_email=position.project.owner.email,
Expand Down Expand Up @@ -138,6 +143,10 @@ async def update_participant(
project=project,
)
raise HTTPInternalServerError()
project_joined_participants = await database_service.get_project_joined_participants(
session=session,
project=project,
)

notification_send_map = {
ParticipantStatusEnum.JOINED: {
Expand All @@ -159,6 +168,7 @@ async def update_participant(
if participant_notification_send:
await participant_notification_send(
project=project,
project_joined_participants=project_joined_participants,
participant=participant,
participant_email=participant_user.email,
owner_email=project.owner.email,
Expand Down
19 changes: 13 additions & 6 deletions sapphire/projects/broker/service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import asyncio
import uuid
from typing import Iterable

from pydantic import BaseModel, EmailStr

Expand All @@ -20,6 +21,7 @@ class Service(BaseBrokerProducerService):
async def send_participant_requested(
self,
project: Project,
project_joined_participants: Iterable[Participant],
participant: Participant,
participant_email: str,
owner_email: str,
Expand All @@ -44,19 +46,20 @@ async def send_participant_requested(
async def send_participant_joined(
self,
project: Project,
project_joined_participants: Iterable[Participant],
participant: Participant,
participant_email: str,
owner_email: str,
) -> None:
"""RECIPIENTS: PARTICIPANTS"""
await self._send_email(
recipients=[p.user.email for p in project.joined_participants],
recipients=[p.user.email for p in project_joined_participants],
email_type=EmailType.PARTICIPANT_JOINED,
)

await self._send_notification_to_recipients(
notification_type=ParticipantNotificationType.JOINED,
recipients=[p.user_id for p in project.joined_participants],
recipients=[p.user_id for p in project_joined_participants],
notification_data=await self._create_participant_notification_data(
project=project,
participant=participant,
Expand All @@ -68,6 +71,7 @@ async def send_participant_joined(
async def send_participant_declined(
self,
project: Project,
project_joined_participants: Iterable[Participant],
participant: Participant,
participant_email: str,
owner_email: str,
Expand All @@ -91,6 +95,7 @@ async def send_participant_declined(
async def send_owner_declined(
self,
project: Project,
project_joined_participants: Iterable[Participant],
participant: Participant,
participant_email: str,
owner_email: str,
Expand All @@ -114,19 +119,20 @@ async def send_owner_declined(
async def send_participant_left(
self,
project: Project,
project_joined_participants: Iterable[Participant],
participant: Participant,
participant_email: str,
owner_email: str,
) -> None:
"""RECIPIENTS: PROJECT OWNER AND PARTICIPANTS"""
await self._send_email(
recipients=[owner_email] + [p.user.email for p in project.joined_participants],
recipients=[owner_email] + [p.user.email for p in project_joined_participants],
email_type=EmailType.PARTICIPANT_LEFT,
)

await self._send_notification_to_recipients(
notification_type=ParticipantNotificationType.PARTICIPANT_LEFT,
recipients=[project.owner_id] + [p.user_id for p in project.joined_participants],
recipients=[project.owner_id] + [p.user_id for p in project_joined_participants],
notification_data=await self._create_participant_notification_data(
project=project,
participant=participant,
Expand All @@ -138,19 +144,20 @@ async def send_participant_left(
async def send_owner_excluded(
self,
project: Project,
project_joined_participants: Iterable[Participant],
participant: Participant,
participant_email: str,
owner_email: str,
) -> None:
"""RECIPIENTS: PROJECT OWNER AND PARTICIPANTS"""
await self._send_email(
recipients=[owner_email] + [p.user.email for p in project.joined_participants],
recipients=[owner_email] + [p.user.email for p in project_joined_participants],
email_type=EmailType.OWNER_EXCLUDED,
)

await self._send_notification_to_recipients(
notification_type=ParticipantNotificationType.OWNER_EXCLUDED,
recipients=[project.owner_id] + [p.user_id for p in project.joined_participants],
recipients=[project.owner_id] + [p.user_id for p in project_joined_participants],
notification_data=await self._create_participant_notification_data(
project=project,
participant=participant,
Expand Down
17 changes: 16 additions & 1 deletion sapphire/projects/database/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ async def _change_project_status(
status=status,
)
session.add(new_history_entry)
project.history.insert(0, new_history_entry)
await nested_session.commit()

await session.refresh(project)
Expand Down Expand Up @@ -297,6 +296,7 @@ async def get_position(
filters.append(Position.id == position_id)

statement = select(Position).where(*filters)

result = await session.execute(statement)

return result.unique().scalar_one_or_none()
Expand Down Expand Up @@ -681,6 +681,21 @@ async def get_project_history(

return list(result.unique().scalars().all())

async def get_project_joined_participants(
self,
session: AsyncSession,
project: Project,
) -> list[Participant]:
statement = select(Participant).where(
Participant.status == ParticipantStatusEnum.JOINED,
Participant.position_id == Position.id,
Position.project_id == project.id,
)

result = await session.execute(statement)

return list(result.unique().scalars().all())

async def get_user_statistic(self, session: AsyncSession, user_id: uuid.UUID) -> UserStatistic:
stmt = select(
func.count(Project.id), # pylint: disable=not-callable
Expand Down

0 comments on commit 1fc45cc

Please sign in to comment.