fix: exhibit/bulk에서 concurrent DB 세션 충돌 수정

asyncio.gather로 동시에 실행되는 exhibit 항목들이 단일 DB 세션을
공유하면서 "concurrent operations are not permitted" 에러 발생.

각 _fetch_one 태스크가 AsyncSessionLocal()로 독립 세션 사용하도록 수정.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
I Luk Kim 5 months ago
parent 45d832ba5c
commit 1e9432a6e3

@ -10,7 +10,7 @@ from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, Response from fastapi import APIRouter, Depends, HTTPException, Query, Response
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from app.core.database import get_db from app.core.database import get_db, AsyncSessionLocal
from app.schemas.filing import ( from app.schemas.filing import (
BulkExhibitItem, BulkExhibitItem,
BulkExhibitRequest, BulkExhibitRequest,
@ -290,27 +290,29 @@ async def get_exhibit_bulk(
async def _fetch_one(item: dict) -> BulkExhibitItem: async def _fetch_one(item: dict) -> BulkExhibitItem:
accession_number = item.get("accession_number", "") accession_number = item.get("accession_number", "")
exhibit_type = item.get("exhibit_type", "EX-99.1") exhibit_type = item.get("exhibit_type", "EX-99.1")
try: # Each concurrent call gets its own DB session to avoid session contention
result = await asyncio.wait_for( async with AsyncSessionLocal() as session:
sec_filings_service.get_exhibit_content(db, accession_number, exhibit_type), try:
timeout=30, result = await asyncio.wait_for(
) sec_filings_service.get_exhibit_content(session, accession_number, exhibit_type),
return BulkExhibitItem( timeout=30,
accession_number=accession_number, )
exhibit_type=exhibit_type, return BulkExhibitItem(
success=True, accession_number=accession_number,
content=result["content"], exhibit_type=exhibit_type,
content_type=result.get("content_type"), success=True,
filename=result.get("filename"), content=result["content"],
url=result.get("url"), content_type=result.get("content_type"),
) filename=result.get("filename"),
except Exception as e: url=result.get("url"),
return BulkExhibitItem( )
accession_number=accession_number, except Exception as e:
exhibit_type=exhibit_type, return BulkExhibitItem(
success=False, accession_number=accession_number,
error=str(e), exhibit_type=exhibit_type,
) success=False,
error=str(e),
)
raw = await asyncio.gather(*[_fetch_one(item) for item in request.items], return_exceptions=True) raw = await asyncio.gather(*[_fetch_one(item) for item in request.items], return_exceptions=True)
results: List[BulkExhibitItem] = [] results: List[BulkExhibitItem] = []

Loading…
Cancel
Save