@ -196,10 +196,33 @@ async def _run_build_snapshots(
_asyncio . set_event_loop ( loop )
async def _build ( ) :
# Create a fresh engine + session factory bound to THIS event loop.
# asyncpg connections are loop-bound; reusing the API's AsyncSessionLocal
# in a different loop raises "Future attached to a different loop".
from sqlalchemy . ext . asyncio import (
AsyncSession ,
async_sessionmaker ,
create_async_engine ,
)
from sqlalchemy . orm import sessionmaker as _sessionmaker
from app . core . config import settings
_engine = create_async_engine (
settings . DATABASE_URL ,
echo = False ,
pool_size = 2 ,
max_overflow = 0 ,
pool_timeout = 30 ,
pool_pre_ping = True ,
connect_args = { " server_settings " : { " jit " : " off " } } ,
)
_SessionLocal = _sessionmaker (
_engine , class_ = AsyncSession , expire_on_commit = False
)
svc = UniverseService ( )
try :
result = await svc . build_snapshots (
AsyncSessionLocal ,
_ SessionLocal,
tickers = tickers ,
start_date = start_date ,
end_date = end_date ,
@ -208,6 +231,8 @@ async def _run_build_snapshots(
logger . info ( f " Universe background build complete: { result } " )
except Exception as e :
logger . error ( f " Universe background build failed: { e } " )
finally :
await _engine . dispose ( )
try :
loop . run_until_complete ( _build ( ) )