From 5c7cc75c1f011c589d0b37d3bcd7f7c9694e6b5c Mon Sep 17 00:00:00 2001 From: Victor Skvortsov Date: Thu, 16 Jan 2025 16:17:54 +0500 Subject: [PATCH] Use AsyncAdaptedQueuePool for sqlite Due to aiosqlite's default, NullPool was used for sqlite. This is a suboptimal setting when spawning many sessions as we do. (See https://github.com/bluesky/tiled/issues/663) Also increase busy_timeout to 30s. It allows getting rid of "database is locked" when stopping many runs (e.g. 20 at a time). --- src/dstack/_internal/server/db.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/dstack/_internal/server/db.py b/src/dstack/_internal/server/db.py index 81b6b7057..742b07ad7 100644 --- a/src/dstack/_internal/server/db.py +++ b/src/dstack/_internal/server/db.py @@ -2,7 +2,7 @@ from typing import Optional from alembic import command, config -from sqlalchemy import event +from sqlalchemy import AsyncAdaptedQueuePool, event from sqlalchemy.engine.interfaces import DBAPIConnection from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, create_async_engine from sqlalchemy.orm import sessionmaker @@ -19,7 +19,11 @@ def __init__(self, url: str, engine: Optional[AsyncEngine] = None): if engine is not None: self.engine = engine else: - self.engine = create_async_engine(self.url, echo=settings.SQL_ECHO_ENABLED) + self.engine = create_async_engine( + self.url, + echo=settings.SQL_ECHO_ENABLED, + poolclass=AsyncAdaptedQueuePool, + ) self.session_maker = sessionmaker( bind=self.engine, expire_on_commit=False, @@ -34,7 +38,7 @@ def set_sqlite_pragma(dbapi_connection: DBAPIConnection, _: ConnectionPoolEntry) cursor.execute("PRAGMA journal_mode=WAL;") cursor.execute("PRAGMA foreign_keys=ON;") cursor.execute("PRAGMA synchronous=NORMAL;") - cursor.execute("PRAGMA busy_timeout=10000;") + cursor.execute("PRAGMA busy_timeout=30000;") cursor.close() @property