真人/虚拟人像库BUG修复 | app build
This commit is contained in:
@@ -1,10 +1,32 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.models.private_portrait import PrivatePortraitProject
|
||||
from app.services.private_portrait.project_service import list_projects, project_to_out, refresh_project_counters
|
||||
|
||||
|
||||
async def _reload_projects_by_ids(db: AsyncSession, project_ids: list[str]) -> list[PrivatePortraitProject]:
|
||||
"""Reload projects after counter refresh to avoid async expired-attribute lazy load.
|
||||
|
||||
refresh_project_counters() uses bulk UPDATE. In SQLAlchemy async ORM, previously
|
||||
loaded ORM instances may become expired after a bulk update. Accessing expired
|
||||
scalar attributes outside greenlet context triggers MissingGreenlet. Reloading
|
||||
with populate_existing=True refreshes the identity-map objects during the awaited
|
||||
execute call, and keeps the original pagination order.
|
||||
"""
|
||||
if not project_ids:
|
||||
return []
|
||||
result = await db.execute(
|
||||
select(PrivatePortraitProject)
|
||||
.where(PrivatePortraitProject.id.in_(project_ids))
|
||||
.execution_options(populate_existing=True)
|
||||
)
|
||||
project_map = {project.id: project for project in result.scalars().all()}
|
||||
return [project_map[project_id] for project_id in project_ids if project_id in project_map]
|
||||
|
||||
|
||||
async def admin_list_projects(
|
||||
db: AsyncSession,
|
||||
*,
|
||||
@@ -15,6 +37,18 @@ async def admin_list_projects(
|
||||
page: int = 1,
|
||||
page_size: int = 20,
|
||||
):
|
||||
items, total = await list_projects(db, user_id=user_id, page=page, page_size=page_size, keyword=keyword, status=status, library_type=library_type)
|
||||
await refresh_project_counters(db, [item.id for item in items])
|
||||
items, total = await list_projects(
|
||||
db,
|
||||
user_id=user_id,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
keyword=keyword,
|
||||
status=status,
|
||||
library_type=library_type,
|
||||
)
|
||||
project_ids = [item.id for item in items]
|
||||
await refresh_project_counters(db, project_ids)
|
||||
|
||||
# Bulk UPDATE may expire loaded ORM instances. Re-query before DTO conversion.
|
||||
items = await _reload_projects_by_ids(db, project_ids)
|
||||
return [project_to_out(item, include_user=True) for item in items], total
|
||||
|
||||
@@ -251,6 +251,7 @@ async def refresh_project_counters(db: AsyncSession, project_ids: list[str]) ->
|
||||
active_image_asset_count=active_image_total,
|
||||
active_video_asset_count=active_video_total,
|
||||
)
|
||||
.execution_options(synchronize_session=False)
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user