mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-10-21 07:55:18 +08:00
fix(sqlite): enable WAL for concurrent plugin callback commits
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
FROM local/langbot-oss-411:688e7761
|
||||
COPY src/langbot/pkg/persistence/databases/sqlite.py /app/src/langbot/pkg/persistence/databases/sqlite.py
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import sqlalchemy
|
||||
import sqlalchemy.ext.asyncio as sqlalchemy_asyncio
|
||||
|
||||
from .. import database
|
||||
@@ -13,3 +14,8 @@ class SQLiteDatabaseManager(database.BaseDatabaseManager):
|
||||
db_file_path = self.ap.instance_config.data.get('database', {}).get('sqlite', {}).get('path', 'data/langbot.db')
|
||||
engine_url = f'sqlite+aiosqlite:///{db_file_path}'
|
||||
self.engine = sqlalchemy_asyncio.create_async_engine(engine_url)
|
||||
# Reader transactions must not block independent plugin callback commits.
|
||||
# Configure the persistent journal before serving requests, not per write.
|
||||
async with self.engine.connect() as connection:
|
||||
await connection.execute(sqlalchemy.text('PRAGMA journal_mode=WAL'))
|
||||
await connection.commit()
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
import sqlalchemy as sa
|
||||
|
||||
from langbot.pkg.core import app # noqa: F401 - initialize manager registration before database imports
|
||||
from langbot.pkg.persistence.databases.sqlite import SQLiteDatabaseManager
|
||||
|
||||
pytestmark = [pytest.mark.integration, pytest.mark.asyncio]
|
||||
|
||||
|
||||
async def test_writer_commits_while_independent_reader_is_open(tmp_path):
|
||||
application = SimpleNamespace(
|
||||
instance_config=SimpleNamespace(data={'database': {'sqlite': {'path': str(tmp_path / 'concurrency.db')}}})
|
||||
)
|
||||
manager = SQLiteDatabaseManager(application)
|
||||
await manager.initialize()
|
||||
engine = manager.get_engine()
|
||||
try:
|
||||
async with engine.begin() as connection:
|
||||
await connection.execute(sa.text('CREATE TABLE probe (id INTEGER PRIMARY KEY, value TEXT)'))
|
||||
await connection.execute(sa.text("INSERT INTO probe VALUES (1, 'old')"))
|
||||
async with engine.connect() as reader:
|
||||
await reader.execute(sa.text('BEGIN'))
|
||||
assert (await reader.execute(sa.text('SELECT value FROM probe'))).scalar_one() == 'old'
|
||||
async with engine.connect() as writer:
|
||||
await writer.execute(sa.text('PRAGMA busy_timeout=250'))
|
||||
await writer.execute(sa.text("UPDATE probe SET value='new' WHERE id=1"))
|
||||
await writer.commit()
|
||||
await reader.rollback()
|
||||
async with engine.connect() as connection:
|
||||
assert (await connection.execute(sa.text('SELECT value FROM probe'))).scalar_one() == 'new'
|
||||
finally:
|
||||
await engine.dispose()
|
||||
Reference in New Issue
Block a user