From 3774f68393f6db54c3759ddbd3b6f45bf83dcefe Mon Sep 17 00:00:00 2001 From: "Xavier L." Date: Mon, 8 Sep 2025 12:23:37 -0400 Subject: [PATCH] feat: Add option to switch sqlite to WAL (#6050) Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com> --- Taskfile.yml | 2 ++ .../installation/backend-config.md | 19 +++++++++--------- mealie/core/settings/settings.py | 2 ++ mealie/db/db_setup.py | 20 +++++++++++++++++++ 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 5352a3ca3..e926fe9f0 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -88,6 +88,8 @@ tasks: - rm -r ./dev/data/recipes/ - rm -r ./dev/data/users/ - rm -f ./dev/data/mealie*.db + - rm -f ./dev/data/mealie*.db-shm + - rm -f ./dev/data/mealie*.db-wal - rm -f ./dev/data/mealie.log - rm -f ./dev/data/.secret diff --git a/docs/docs/documentation/getting-started/installation/backend-config.md b/docs/docs/documentation/getting-started/installation/backend-config.md index 0857e7f63..0bf06e304 100644 --- a/docs/docs/documentation/getting-started/installation/backend-config.md +++ b/docs/docs/documentation/getting-started/installation/backend-config.md @@ -32,15 +32,16 @@ ### Database - | Variables | Default | Description | - | ------------------------------------------------------- | :------: | ----------------------------------------------------------------------- | - | DB_ENGINE | sqlite | Optional: 'sqlite', 'postgres' | - | POSTGRES_USER[†][secrets] | mealie | Postgres database user | - | POSTGRES_PASSWORD[†][secrets] | mealie | Postgres database password | - | POSTGRES_SERVER[†][secrets] | postgres | Postgres database server address | - | POSTGRES_PORT[†][secrets] | 5432 | Postgres database port | - | POSTGRES_DB[†][secrets] | mealie | Postgres database name | - | POSTGRES_URL_OVERRIDE[†][secrets] | None | Optional Postgres URL override to use instead of POSTGRES\_\* variables | + | Variables | Default | Description | + |---------------------------------------------------------|:--------:|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| + | DB_ENGINE | sqlite | Optional: 'sqlite', 'postgres' | + | SQLITE_MIGRATE_JOURNAL_WAL | False | If set to true, switches SQLite's journal mode to WAL, which allows for multiple concurrent accesses. This can be useful when you have a decent amount of concurrency or when using certain remote storage systems such as Ceph. | + | POSTGRES_USER[†][secrets] | mealie | Postgres database user | + | POSTGRES_PASSWORD[†][secrets] | mealie | Postgres database password | + | POSTGRES_SERVER[†][secrets] | postgres | Postgres database server address | + | POSTGRES_PORT[†][secrets] | 5432 | Postgres database port | + | POSTGRES_DB[†][secrets] | mealie | Postgres database name | + | POSTGRES_URL_OVERRIDE[†][secrets] | None | Optional Postgres URL override to use instead of POSTGRES\_\* variables | ### Email diff --git a/mealie/core/settings/settings.py b/mealie/core/settings/settings.py index 1f30fdf14..10bfb6aeb 100644 --- a/mealie/core/settings/settings.py +++ b/mealie/core/settings/settings.py @@ -196,6 +196,8 @@ class AppSettings(AppLoggingSettings): DB_ENGINE: str = "sqlite" # Options: 'sqlite', 'postgres' DB_PROVIDER: AbstractDBProvider | None = None + SQLITE_MIGRATE_JOURNAL_WAL: bool = False + @property def DB_URL(self) -> str | None: return self.DB_PROVIDER.db_url if self.DB_PROVIDER else None diff --git a/mealie/db/db_setup.py b/mealie/db/db_setup.py index 672260e2a..ea0d9a334 100644 --- a/mealie/db/db_setup.py +++ b/mealie/db/db_setup.py @@ -2,6 +2,8 @@ from collections.abc import Generator from contextlib import contextmanager import sqlalchemy as sa +from sqlalchemy.engine import Engine +from sqlalchemy.event import listens_for from sqlalchemy.orm import sessionmaker from sqlalchemy.orm.session import Session @@ -10,6 +12,24 @@ from mealie.core.config import get_app_settings settings = get_app_settings() +@listens_for(Engine, "connect") +def set_sqlite_pragma_journal_wal(dbapi_connection, connection_record): + """ + Automatically enables SQLite's WAL journal mode if the setting is activated. + + This is a persistent setting, so turning it off down the line doesn't revert back to the original journal mode. + + Write-Ahead-Log enables sqlite to be used concurrently by multiple readers and writers (writes still happen + sequentially). + """ + global settings + if settings.DB_ENGINE != "sqlite" or not settings.SQLITE_MIGRATE_JOURNAL_WAL: + return + cursor = dbapi_connection.cursor() + cursor.execute("PRAGMA journal_mode=WAL") + cursor.close() + + def sql_global_init(db_url: str): connect_args = {} if "sqlite" in db_url: