refactor: replace exec_dml with CRUD operations in various files and improve session handling
This commit is contained in:
@@ -9,7 +9,7 @@ from typing import Any, cast
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Request, status
|
||||
from sqlalchemy import asc, or_, update
|
||||
from sqlalchemy import asc, or_
|
||||
from sqlalchemy.sql.elements import ColumnElement
|
||||
from sqlmodel import col, select
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
@@ -19,9 +19,9 @@ from app.api.deps import ActorContext, require_admin_or_agent, require_org_admin
|
||||
from app.core.agent_tokens import generate_agent_token, hash_agent_token
|
||||
from app.core.auth import AuthContext, get_auth_context
|
||||
from app.core.time import utcnow
|
||||
from app.db import crud
|
||||
from app.db.pagination import paginate
|
||||
from app.db.session import async_session_maker, get_session
|
||||
from app.db.sqlmodel_exec import exec_dml
|
||||
from app.integrations.openclaw_gateway import GatewayConfig as GatewayClientConfig
|
||||
from app.integrations.openclaw_gateway import OpenClawGatewayError, ensure_session, send_message
|
||||
from app.models.activity_events import ActivityEvent
|
||||
@@ -101,7 +101,7 @@ async def _require_board(
|
||||
session: AsyncSession,
|
||||
board_id: UUID | str | None,
|
||||
*,
|
||||
user: object | None = None,
|
||||
user: User | None = None,
|
||||
write: bool = False,
|
||||
) -> Board:
|
||||
if not board_id:
|
||||
@@ -113,7 +113,7 @@ async def _require_board(
|
||||
if board is None:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Board not found")
|
||||
if user is not None:
|
||||
await require_board_access(session, user=user, board=board, write=write) # type: ignore[arg-type]
|
||||
await require_board_access(session, user=user, board=board, write=write)
|
||||
return board
|
||||
|
||||
|
||||
@@ -972,31 +972,32 @@ async def delete_agent(
|
||||
agent_id=None,
|
||||
)
|
||||
now = datetime.now()
|
||||
await exec_dml(
|
||||
await crud.update_where(
|
||||
session,
|
||||
update(Task)
|
||||
.where(col(Task.assigned_agent_id) == agent.id)
|
||||
.where(col(Task.status) == "in_progress")
|
||||
.values(
|
||||
assigned_agent_id=None,
|
||||
status="inbox",
|
||||
in_progress_at=None,
|
||||
updated_at=now,
|
||||
),
|
||||
Task,
|
||||
col(Task.assigned_agent_id) == agent.id,
|
||||
col(Task.status) == "in_progress",
|
||||
assigned_agent_id=None,
|
||||
status="inbox",
|
||||
in_progress_at=None,
|
||||
updated_at=now,
|
||||
commit=False,
|
||||
)
|
||||
await exec_dml(
|
||||
await crud.update_where(
|
||||
session,
|
||||
update(Task)
|
||||
.where(col(Task.assigned_agent_id) == agent.id)
|
||||
.where(col(Task.status) != "in_progress")
|
||||
.values(
|
||||
assigned_agent_id=None,
|
||||
updated_at=now,
|
||||
),
|
||||
Task,
|
||||
col(Task.assigned_agent_id) == agent.id,
|
||||
col(Task.status) != "in_progress",
|
||||
assigned_agent_id=None,
|
||||
updated_at=now,
|
||||
commit=False,
|
||||
)
|
||||
await exec_dml(
|
||||
await crud.update_where(
|
||||
session,
|
||||
update(ActivityEvent).where(col(ActivityEvent.agent_id) == agent.id).values(agent_id=None),
|
||||
ActivityEvent,
|
||||
col(ActivityEvent.agent_id) == agent.id,
|
||||
agent_id=None,
|
||||
commit=False,
|
||||
)
|
||||
await session.delete(agent)
|
||||
await session.commit()
|
||||
|
||||
@@ -5,7 +5,7 @@ from typing import Any, cast
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy import delete, func, update
|
||||
from sqlalchemy import func
|
||||
from sqlmodel import col, select
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
|
||||
@@ -14,7 +14,6 @@ from app.core.time import utcnow
|
||||
from app.db import crud
|
||||
from app.db.pagination import paginate
|
||||
from app.db.session import get_session
|
||||
from app.db.sqlmodel_exec import exec_dml
|
||||
from app.models.agents import Agent
|
||||
from app.models.board_group_memory import BoardGroupMemory
|
||||
from app.models.board_groups import BoardGroup
|
||||
@@ -276,14 +275,16 @@ async def delete_board_group(
|
||||
await _require_group_access(session, group_id=group_id, member=ctx.member, write=True)
|
||||
|
||||
# Boards reference groups, so clear the FK first to keep deletes simple.
|
||||
await exec_dml(
|
||||
await crud.update_where(
|
||||
session,
|
||||
update(Board).where(col(Board.board_group_id) == group_id).values(board_group_id=None),
|
||||
Board,
|
||||
col(Board.board_group_id) == group_id,
|
||||
board_group_id=None,
|
||||
commit=False,
|
||||
)
|
||||
await exec_dml(
|
||||
session,
|
||||
delete(BoardGroupMemory).where(col(BoardGroupMemory.board_group_id) == group_id),
|
||||
await crud.delete_where(
|
||||
session, BoardGroupMemory, col(BoardGroupMemory.board_group_id) == group_id, commit=False
|
||||
)
|
||||
await exec_dml(session, delete(BoardGroup).where(col(BoardGroup.id) == group_id))
|
||||
await crud.delete_where(session, BoardGroup, col(BoardGroup.id) == group_id, commit=False)
|
||||
await session.commit()
|
||||
return OkResponse()
|
||||
|
||||
@@ -4,7 +4,7 @@ import re
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
from sqlalchemy import delete, func
|
||||
from sqlalchemy import func
|
||||
from sqlmodel import col, select
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
|
||||
@@ -19,7 +19,6 @@ from app.core.time import utcnow
|
||||
from app.db import crud
|
||||
from app.db.pagination import paginate
|
||||
from app.db.session import get_session
|
||||
from app.db.sqlmodel_exec import exec_dml
|
||||
from app.integrations.openclaw_gateway import GatewayConfig as GatewayClientConfig
|
||||
from app.integrations.openclaw_gateway import (
|
||||
OpenClawGatewayError,
|
||||
@@ -307,43 +306,38 @@ async def delete_board(
|
||||
) from exc
|
||||
|
||||
if task_ids:
|
||||
await exec_dml(
|
||||
session, delete(ActivityEvent).where(col(ActivityEvent.task_id).in_(task_ids))
|
||||
await crud.delete_where(
|
||||
session, ActivityEvent, col(ActivityEvent.task_id).in_(task_ids), commit=False
|
||||
)
|
||||
await exec_dml(session, delete(TaskDependency).where(col(TaskDependency.board_id) == board.id))
|
||||
await exec_dml(
|
||||
session, delete(TaskFingerprint).where(col(TaskFingerprint.board_id) == board.id)
|
||||
)
|
||||
await crud.delete_where(session, TaskDependency, col(TaskDependency.board_id) == board.id)
|
||||
await crud.delete_where(session, TaskFingerprint, col(TaskFingerprint.board_id) == board.id)
|
||||
|
||||
# Approvals can reference tasks and agents, so delete before both.
|
||||
await exec_dml(session, delete(Approval).where(col(Approval.board_id) == board.id))
|
||||
await crud.delete_where(session, Approval, col(Approval.board_id) == board.id)
|
||||
|
||||
await exec_dml(session, delete(BoardMemory).where(col(BoardMemory.board_id) == board.id))
|
||||
await exec_dml(
|
||||
session,
|
||||
delete(BoardOnboardingSession).where(col(BoardOnboardingSession.board_id) == board.id),
|
||||
await crud.delete_where(session, BoardMemory, col(BoardMemory.board_id) == board.id)
|
||||
await crud.delete_where(
|
||||
session, BoardOnboardingSession, col(BoardOnboardingSession.board_id) == board.id
|
||||
)
|
||||
await exec_dml(
|
||||
session,
|
||||
delete(OrganizationBoardAccess).where(col(OrganizationBoardAccess.board_id) == board.id),
|
||||
await crud.delete_where(
|
||||
session, OrganizationBoardAccess, col(OrganizationBoardAccess.board_id) == board.id
|
||||
)
|
||||
await exec_dml(
|
||||
await crud.delete_where(
|
||||
session,
|
||||
delete(OrganizationInviteBoardAccess).where(
|
||||
col(OrganizationInviteBoardAccess.board_id) == board.id
|
||||
),
|
||||
OrganizationInviteBoardAccess,
|
||||
col(OrganizationInviteBoardAccess.board_id) == board.id,
|
||||
)
|
||||
|
||||
# Tasks reference agents (assigned_agent_id) and have dependents (fingerprints/dependencies), so
|
||||
# delete tasks before agents.
|
||||
await exec_dml(session, delete(Task).where(col(Task.board_id) == board.id))
|
||||
await crud.delete_where(session, Task, col(Task.board_id) == board.id)
|
||||
|
||||
if agents:
|
||||
agent_ids = [agent.id for agent in agents]
|
||||
await exec_dml(
|
||||
session, delete(ActivityEvent).where(col(ActivityEvent.agent_id).in_(agent_ids))
|
||||
await crud.delete_where(
|
||||
session, ActivityEvent, col(ActivityEvent.agent_id).in_(agent_ids), commit=False
|
||||
)
|
||||
await exec_dml(session, delete(Agent).where(col(Agent.id).in_(agent_ids)))
|
||||
await crud.delete_where(session, Agent, col(Agent.id).in_(agent_ids))
|
||||
await session.delete(board)
|
||||
await session.commit()
|
||||
return OkResponse()
|
||||
|
||||
@@ -21,6 +21,7 @@ from app.integrations.openclaw_gateway_protocol import (
|
||||
)
|
||||
from app.models.boards import Board
|
||||
from app.models.gateways import Gateway
|
||||
from app.models.users import User
|
||||
from app.schemas.common import OkResponse
|
||||
from app.schemas.gateway_api import (
|
||||
GatewayCommandsResponse,
|
||||
@@ -43,7 +44,7 @@ async def _resolve_gateway(
|
||||
gateway_token: str | None,
|
||||
gateway_main_session_key: str | None,
|
||||
*,
|
||||
user: object | None = None,
|
||||
user: User | None = None,
|
||||
) -> tuple[Board | None, GatewayClientConfig, str | None]:
|
||||
if gateway_url:
|
||||
return (
|
||||
@@ -59,8 +60,8 @@ async def _resolve_gateway(
|
||||
board = await Board.objects.by_id(board_id).first(session)
|
||||
if board is None:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Board not found")
|
||||
if isinstance(user, object) and user is not None:
|
||||
await require_board_access(session, user=user, board=board, write=False) # type: ignore[arg-type]
|
||||
if user is not None:
|
||||
await require_board_access(session, user=user, board=board, write=False)
|
||||
if not board.gateway_id:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
@@ -85,7 +86,7 @@ async def _resolve_gateway(
|
||||
|
||||
|
||||
async def _require_gateway(
|
||||
session: AsyncSession, board_id: str | None, *, user: object | None = None
|
||||
session: AsyncSession, board_id: str | None, *, user: User | None = None
|
||||
) -> tuple[Board, GatewayClientConfig, str | None]:
|
||||
board, config, main_session = await _resolve_gateway(
|
||||
session,
|
||||
|
||||
@@ -5,7 +5,7 @@ from typing import Any, Sequence
|
||||
from uuid import UUID
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy import delete, func, update
|
||||
from sqlalchemy import func
|
||||
from sqlmodel import col, select
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
|
||||
@@ -15,7 +15,6 @@ from app.core.time import utcnow
|
||||
from app.db import crud
|
||||
from app.db.pagination import paginate
|
||||
from app.db.session import get_session
|
||||
from app.db.sqlmodel_exec import exec_dml
|
||||
from app.models.activity_events import ActivityEvent
|
||||
from app.models.agents import Agent
|
||||
from app.models.approvals import Approval
|
||||
@@ -214,67 +213,85 @@ async def delete_my_org(
|
||||
)
|
||||
group_ids = select(BoardGroup.id).where(col(BoardGroup.organization_id) == org_id)
|
||||
|
||||
await exec_dml(session, delete(ActivityEvent).where(col(ActivityEvent.task_id).in_(task_ids)))
|
||||
await exec_dml(session, delete(ActivityEvent).where(col(ActivityEvent.agent_id).in_(agent_ids)))
|
||||
await exec_dml(
|
||||
session, delete(TaskDependency).where(col(TaskDependency.board_id).in_(board_ids))
|
||||
await crud.delete_where(
|
||||
session, ActivityEvent, col(ActivityEvent.task_id).in_(task_ids), commit=False
|
||||
)
|
||||
await exec_dml(
|
||||
await crud.delete_where(
|
||||
session, ActivityEvent, col(ActivityEvent.agent_id).in_(agent_ids), commit=False
|
||||
)
|
||||
await crud.delete_where(
|
||||
session, TaskDependency, col(TaskDependency.board_id).in_(board_ids), commit=False
|
||||
)
|
||||
await crud.delete_where(
|
||||
session, TaskFingerprint, col(TaskFingerprint.board_id).in_(board_ids), commit=False
|
||||
)
|
||||
await crud.delete_where(session, Approval, col(Approval.board_id).in_(board_ids), commit=False)
|
||||
await crud.delete_where(
|
||||
session, BoardMemory, col(BoardMemory.board_id).in_(board_ids), commit=False
|
||||
)
|
||||
await crud.delete_where(
|
||||
session,
|
||||
delete(TaskFingerprint).where(col(TaskFingerprint.board_id).in_(board_ids)),
|
||||
BoardOnboardingSession,
|
||||
col(BoardOnboardingSession.board_id).in_(board_ids),
|
||||
commit=False,
|
||||
)
|
||||
await exec_dml(session, delete(Approval).where(col(Approval.board_id).in_(board_ids)))
|
||||
await exec_dml(session, delete(BoardMemory).where(col(BoardMemory.board_id).in_(board_ids)))
|
||||
await exec_dml(
|
||||
await crud.delete_where(
|
||||
session,
|
||||
delete(BoardOnboardingSession).where(col(BoardOnboardingSession.board_id).in_(board_ids)),
|
||||
OrganizationBoardAccess,
|
||||
col(OrganizationBoardAccess.board_id).in_(board_ids),
|
||||
commit=False,
|
||||
)
|
||||
await exec_dml(
|
||||
await crud.delete_where(
|
||||
session,
|
||||
delete(OrganizationBoardAccess).where(col(OrganizationBoardAccess.board_id).in_(board_ids)),
|
||||
OrganizationInviteBoardAccess,
|
||||
col(OrganizationInviteBoardAccess.board_id).in_(board_ids),
|
||||
commit=False,
|
||||
)
|
||||
await exec_dml(
|
||||
await crud.delete_where(
|
||||
session,
|
||||
delete(OrganizationInviteBoardAccess).where(
|
||||
col(OrganizationInviteBoardAccess.board_id).in_(board_ids)
|
||||
),
|
||||
OrganizationBoardAccess,
|
||||
col(OrganizationBoardAccess.organization_member_id).in_(member_ids),
|
||||
commit=False,
|
||||
)
|
||||
await exec_dml(
|
||||
await crud.delete_where(
|
||||
session,
|
||||
delete(OrganizationBoardAccess).where(
|
||||
col(OrganizationBoardAccess.organization_member_id).in_(member_ids)
|
||||
),
|
||||
OrganizationInviteBoardAccess,
|
||||
col(OrganizationInviteBoardAccess.organization_invite_id).in_(invite_ids),
|
||||
commit=False,
|
||||
)
|
||||
await exec_dml(
|
||||
await crud.delete_where(session, Task, col(Task.board_id).in_(board_ids), commit=False)
|
||||
await crud.delete_where(session, Agent, col(Agent.board_id).in_(board_ids), commit=False)
|
||||
await crud.delete_where(session, Board, col(Board.organization_id) == org_id, commit=False)
|
||||
await crud.delete_where(
|
||||
session,
|
||||
delete(OrganizationInviteBoardAccess).where(
|
||||
col(OrganizationInviteBoardAccess.organization_invite_id).in_(invite_ids)
|
||||
),
|
||||
BoardGroupMemory,
|
||||
col(BoardGroupMemory.board_group_id).in_(group_ids),
|
||||
commit=False,
|
||||
)
|
||||
await exec_dml(session, delete(Task).where(col(Task.board_id).in_(board_ids)))
|
||||
await exec_dml(session, delete(Agent).where(col(Agent.board_id).in_(board_ids)))
|
||||
await exec_dml(session, delete(Board).where(col(Board.organization_id) == org_id))
|
||||
await exec_dml(
|
||||
await crud.delete_where(
|
||||
session, BoardGroup, col(BoardGroup.organization_id) == org_id, commit=False
|
||||
)
|
||||
await crud.delete_where(session, Gateway, col(Gateway.organization_id) == org_id, commit=False)
|
||||
await crud.delete_where(
|
||||
session,
|
||||
delete(BoardGroupMemory).where(col(BoardGroupMemory.board_group_id).in_(group_ids)),
|
||||
OrganizationInvite,
|
||||
col(OrganizationInvite.organization_id) == org_id,
|
||||
commit=False,
|
||||
)
|
||||
await exec_dml(session, delete(BoardGroup).where(col(BoardGroup.organization_id) == org_id))
|
||||
await exec_dml(session, delete(Gateway).where(col(Gateway.organization_id) == org_id))
|
||||
await exec_dml(
|
||||
await crud.delete_where(
|
||||
session,
|
||||
delete(OrganizationInvite).where(col(OrganizationInvite.organization_id) == org_id),
|
||||
OrganizationMember,
|
||||
col(OrganizationMember.organization_id) == org_id,
|
||||
commit=False,
|
||||
)
|
||||
await exec_dml(
|
||||
await crud.update_where(
|
||||
session,
|
||||
delete(OrganizationMember).where(col(OrganizationMember.organization_id) == org_id),
|
||||
User,
|
||||
col(User.active_organization_id) == org_id,
|
||||
active_organization_id=None,
|
||||
commit=False,
|
||||
)
|
||||
await exec_dml(
|
||||
session,
|
||||
update(User)
|
||||
.where(col(User.active_organization_id) == org_id)
|
||||
.values(active_organization_id=None),
|
||||
)
|
||||
await exec_dml(session, delete(Organization).where(col(Organization.id) == org_id))
|
||||
await crud.delete_where(session, Organization, col(Organization.id) == org_id, commit=False)
|
||||
await session.commit()
|
||||
return OkResponse()
|
||||
|
||||
@@ -425,11 +442,11 @@ async def remove_org_member(
|
||||
detail="Organization must have at least one owner",
|
||||
)
|
||||
|
||||
await exec_dml(
|
||||
await crud.delete_where(
|
||||
session,
|
||||
delete(OrganizationBoardAccess).where(
|
||||
col(OrganizationBoardAccess.organization_member_id) == member.id
|
||||
),
|
||||
OrganizationBoardAccess,
|
||||
col(OrganizationBoardAccess.organization_member_id) == member.id,
|
||||
commit=False,
|
||||
)
|
||||
|
||||
user = await User.objects.by_id(member.user_id).first(session)
|
||||
@@ -532,11 +549,11 @@ async def revoke_org_invite(
|
||||
organization_id=ctx.organization.id,
|
||||
invite_id=invite_id,
|
||||
)
|
||||
await exec_dml(
|
||||
await crud.delete_where(
|
||||
session,
|
||||
delete(OrganizationInviteBoardAccess).where(
|
||||
col(OrganizationInviteBoardAccess.organization_invite_id) == invite.id
|
||||
),
|
||||
OrganizationInviteBoardAccess,
|
||||
col(OrganizationInviteBoardAccess.organization_invite_id) == invite.id,
|
||||
commit=False,
|
||||
)
|
||||
await crud.delete(session, invite)
|
||||
return OrganizationInviteRead.model_validate(invite, from_attributes=True)
|
||||
|
||||
@@ -9,7 +9,7 @@ from typing import cast
|
||||
from uuid import UUID
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Request, status
|
||||
from sqlalchemy import asc, delete, desc, or_
|
||||
from sqlalchemy import asc, desc, or_
|
||||
from sqlmodel import col, select
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
from sqlmodel.sql.expression import Select
|
||||
@@ -25,9 +25,9 @@ from app.api.deps import (
|
||||
)
|
||||
from app.core.auth import AuthContext
|
||||
from app.core.time import utcnow
|
||||
from app.db import crud
|
||||
from app.db.pagination import paginate
|
||||
from app.db.session import async_session_maker, get_session
|
||||
from app.db.sqlmodel_exec import exec_dml
|
||||
from app.integrations.openclaw_gateway import GatewayConfig as GatewayClientConfig
|
||||
from app.integrations.openclaw_gateway import OpenClawGatewayError, ensure_session, send_message
|
||||
from app.models.activity_events import ActivityEvent
|
||||
@@ -997,17 +997,21 @@ async def delete_task(
|
||||
if auth.user is None:
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
|
||||
await require_board_access(session, user=auth.user, board=board, write=True)
|
||||
await exec_dml(session, delete(ActivityEvent).where(col(ActivityEvent.task_id) == task.id))
|
||||
await exec_dml(session, delete(TaskFingerprint).where(col(TaskFingerprint.task_id) == task.id))
|
||||
await exec_dml(session, delete(Approval).where(col(Approval.task_id) == task.id))
|
||||
await exec_dml(
|
||||
await crud.delete_where(
|
||||
session, ActivityEvent, col(ActivityEvent.task_id) == task.id, commit=False
|
||||
)
|
||||
await crud.delete_where(
|
||||
session, TaskFingerprint, col(TaskFingerprint.task_id) == task.id, commit=False
|
||||
)
|
||||
await crud.delete_where(session, Approval, col(Approval.task_id) == task.id, commit=False)
|
||||
await crud.delete_where(
|
||||
session,
|
||||
delete(TaskDependency).where(
|
||||
or_(
|
||||
col(TaskDependency.task_id) == task.id,
|
||||
col(TaskDependency.depends_on_task_id) == task.id,
|
||||
)
|
||||
TaskDependency,
|
||||
or_(
|
||||
col(TaskDependency.task_id) == task.id,
|
||||
col(TaskDependency.depends_on_task_id) == task.id,
|
||||
),
|
||||
commit=False,
|
||||
)
|
||||
await session.delete(task)
|
||||
await session.commit()
|
||||
|
||||
Reference in New Issue
Block a user