From 284529dabe6aba30eeed79734bc1ad32170deef1 Mon Sep 17 00:00:00 2001 From: Gros Frumos Date: Fri, 20 Mar 2026 23:16:12 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20RuntimeError=20=D0=B2=20aiosqlite=20?= =?UTF-8?q?=E2=80=94=20=5Fget=5Fconn=20=D0=BA=D0=B0=D0=BA=20async=20contex?= =?UTF-8?q?t=20manager?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `async with await _get_conn()` запускал тред дважды: первый раз внутри `_get_conn` через `await aiosqlite.connect()`, второй раз в `__aenter__` через `await self`. Преобразован в `@asynccontextmanager` с `yield` и `finally: conn.close()`. Все вызывающие места обновлены. Тест `test_init_db_synchronous` обновлён под новый API. Co-Authored-By: Claude Sonnet 4.6 --- backend/db.py | 21 +++++++++++++-------- tests/test_db.py | 7 +++---- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/backend/db.py b/backend/db.py index 4a5ea4b..e52a95f 100644 --- a/backend/db.py +++ b/backend/db.py @@ -1,22 +1,27 @@ from __future__ import annotations -from typing import Optional +from contextlib import asynccontextmanager +from typing import AsyncGenerator, Optional import aiosqlite from backend import config -async def _get_conn() -> aiosqlite.Connection: +@asynccontextmanager +async def _get_conn() -> AsyncGenerator[aiosqlite.Connection, None]: conn = await aiosqlite.connect(config.DB_PATH) await conn.execute("PRAGMA journal_mode=WAL") await conn.execute("PRAGMA busy_timeout=5000") await conn.execute("PRAGMA synchronous=NORMAL") conn.row_factory = aiosqlite.Row - return conn + try: + yield conn + finally: + await conn.close() async def init_db() -> None: - async with await _get_conn() as conn: + async with _get_conn() as conn: await conn.executescript(""" CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -57,7 +62,7 @@ async def init_db() -> None: async def register_user(uuid: str, name: str) -> dict: - async with await _get_conn() as conn: + async with _get_conn() as conn: await conn.execute( "INSERT OR IGNORE INTO users (uuid, name) VALUES (?, ?)", (uuid, name), @@ -77,7 +82,7 @@ async def save_signal( lon: Optional[float], accuracy: Optional[float], ) -> int: - async with await _get_conn() as conn: + async with _get_conn() as conn: async with conn.execute( """ INSERT INTO signals (user_uuid, timestamp, lat, lon, accuracy) @@ -91,7 +96,7 @@ async def save_signal( async def get_user_name(uuid: str) -> Optional[str]: - async with await _get_conn() as conn: + async with _get_conn() as conn: async with conn.execute( "SELECT name FROM users WHERE uuid = ?", (uuid,) ) as cur: @@ -104,7 +109,7 @@ async def save_telegram_batch( signals_count: int, signal_ids: list[int], ) -> int: - async with await _get_conn() as conn: + async with _get_conn() as conn: async with conn.execute( """ INSERT INTO telegram_batches (message_text, sent_at, signals_count, status) diff --git a/tests/test_db.py b/tests/test_db.py index 6a9aabd..e823fc4 100644 --- a/tests/test_db.py +++ b/tests/test_db.py @@ -109,10 +109,9 @@ async def test_init_db_synchronous(): await db.init_db() # Check synchronous on a new connection via _get_conn() from backend.db import _get_conn - conn = await _get_conn() - async with conn.execute("PRAGMA synchronous") as cur: - row = await cur.fetchone() - await conn.close() + async with _get_conn() as conn: + async with conn.execute("PRAGMA synchronous") as cur: + row = await cur.fetchone() # 1 == NORMAL assert row[0] == 1 finally: