From 2d42ba16e36b118f0dcb765b0d08bf75983ad7e5 Mon Sep 17 00:00:00 2001 From: phernandez Date: Sun, 14 Jun 2026 17:25:12 -0500 Subject: [PATCH] fix(core): preserve sqlite rollback semantics on windows Signed-off-by: phernandez --- src/basic_memory/db.py | 3 +- tests/db/test_memory_db_session_isolation.py | 30 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/basic_memory/db.py b/src/basic_memory/db.py index 81500511..a8835255 100644 --- a/src/basic_memory/db.py +++ b/src/basic_memory/db.py @@ -206,14 +206,13 @@ def _create_sqlite_engine(db_url: str, db_type: DatabaseType) -> AsyncEngine: Configured async engine for SQLite """ # Configure connection args with Windows-specific settings - connect_args: dict[str, bool | float | None] = {"check_same_thread": False} + connect_args: dict[str, bool | float] = {"check_same_thread": False} # Add Windows-specific parameters to improve reliability if os.name == "nt": # Windows connect_args.update( { "timeout": 30.0, # Increase timeout to 30 seconds for Windows - "isolation_level": None, # Use autocommit mode } ) diff --git a/tests/db/test_memory_db_session_isolation.py b/tests/db/test_memory_db_session_isolation.py index 1e25b4d9..54afe099 100644 --- a/tests/db/test_memory_db_session_isolation.py +++ b/tests/db/test_memory_db_session_isolation.py @@ -21,6 +21,7 @@ import pytest from sqlalchemy import text from basic_memory import db +from basic_memory.config import BasicMemoryConfig, DatabaseBackend, ProjectEntry from basic_memory.models import Base @@ -91,3 +92,32 @@ async def test_concurrent_session_rollback_does_not_destroy_uncommitted_writes() "writer's committed INSERT was rolled back by a concurrent session — " "the in-memory engine is sharing one transaction scope across sessions" ) + + +@pytest.mark.asyncio +async def test_windows_memory_engine_respects_explicit_rollback(monkeypatch): + """The Windows SQLite branch must not force driver-level autocommit.""" + db_path = Path("unused.db") + app_config = BasicMemoryConfig( + env="test", + projects={"test-project": ProjectEntry(path=".")}, + default_project="test-project", + database_backend=DatabaseBackend.SQLITE, + ) + monkeypatch.setattr(db.os, "name", "nt") + + async with db.engine_session_factory( + db_path=db_path, db_type=db.DatabaseType.MEMORY, config=app_config + ) as (engine, session_maker): + async with engine.begin() as conn: + await conn.execute(text("CREATE TABLE rollback_probe (name TEXT NOT NULL)")) + + async with session_maker() as session: + transaction = await session.begin() + await session.execute(text("INSERT INTO rollback_probe (name) VALUES ('discarded')")) + await transaction.rollback() + + async with session_maker() as session: + count = (await session.execute(text("SELECT count(*) FROM rollback_probe"))).scalar() + + assert count == 0