From a97308505b91b5c6284eaa2c0738580720845d3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 28 Aug 2026 13:38:50 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Simplify=20database=20read?= =?UTF-8?q?iness=20checks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test-backend.yml | 2 +- backend/README.md | 2 +- backend/app/backend_pre_start.py | 39 ------------------- backend/app/core/db.py | 2 +- backend/app/tests_pre_start.py | 39 ------------------- backend/pyproject.toml | 1 - backend/scripts/prestart.sh | 3 -- backend/scripts/tests-start.sh | 2 - .../tests/scripts/test_backend_pre_start.py | 33 ---------------- backend/tests/scripts/test_test_pre_start.py | 33 ---------------- uv.lock | 11 ------ 11 files changed, 3 insertions(+), 164 deletions(-) delete mode 100644 backend/app/backend_pre_start.py delete mode 100644 backend/app/tests_pre_start.py delete mode 100644 backend/tests/scripts/test_backend_pre_start.py delete mode 100644 backend/tests/scripts/test_test_pre_start.py diff --git a/.github/workflows/test-backend.yml b/.github/workflows/test-backend.yml index 477a6b44ad..300386a790 100644 --- a/.github/workflows/test-backend.yml +++ b/.github/workflows/test-backend.yml @@ -26,7 +26,7 @@ jobs: with: version: "latest-known" - run: docker compose down -v --remove-orphans - - run: docker compose up -d db mailpit + - run: docker compose up -d --wait db mailpit - name: Migrate DB run: uv run bash scripts/prestart.sh working-directory: backend diff --git a/backend/README.md b/backend/README.md index 92175a0b2b..96276b7a68 100644 --- a/backend/README.md +++ b/backend/README.md @@ -78,7 +78,7 @@ If your stack is already up and you just want to run the tests, you can use: docker compose exec backend bash scripts/tests-start.sh ``` -The `/app/backend/scripts/tests-start.sh` script calls `pytest` after making sure that the rest of the stack is running. If you need to pass extra arguments to `pytest`, you can pass them to that command and they will be forwarded. +The `/app/backend/scripts/tests-start.sh` script calls `pytest`. If you need to pass extra arguments to `pytest`, you can pass them to that command and they will be forwarded. For example, to stop on first error: diff --git a/backend/app/backend_pre_start.py b/backend/app/backend_pre_start.py deleted file mode 100644 index c2f8e29ae1..0000000000 --- a/backend/app/backend_pre_start.py +++ /dev/null @@ -1,39 +0,0 @@ -import logging - -from sqlalchemy import Engine -from sqlmodel import Session, select -from tenacity import after_log, before_log, retry, stop_after_attempt, wait_fixed - -from app.core.db import engine - -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) - -max_tries = 60 * 5 # 5 minutes -wait_seconds = 1 - - -@retry( - stop=stop_after_attempt(max_tries), - wait=wait_fixed(wait_seconds), - before=before_log(logger, logging.INFO), - after=after_log(logger, logging.WARN), -) -def init(db_engine: Engine) -> None: - try: - with Session(db_engine) as session: - # Try to create session to check if DB is awake - session.exec(select(1)) - except Exception as e: - logger.error(e) - raise e - - -def main() -> None: - logger.info("Initializing service") - init(engine) - logger.info("Service finished initializing") - - -if __name__ == "__main__": - main() diff --git a/backend/app/core/db.py b/backend/app/core/db.py index f19ac0d3bf..d11b0ebd59 100644 --- a/backend/app/core/db.py +++ b/backend/app/core/db.py @@ -4,7 +4,7 @@ from app.core.config import settings from app.models import User, UserCreate -engine = create_engine(str(settings.DATABASE_URL)) +engine = create_engine(str(settings.DATABASE_URL), pool_pre_ping=True) # make sure all SQLModel models are imported (app.models) before initializing DB diff --git a/backend/app/tests_pre_start.py b/backend/app/tests_pre_start.py deleted file mode 100644 index 0ce6045635..0000000000 --- a/backend/app/tests_pre_start.py +++ /dev/null @@ -1,39 +0,0 @@ -import logging - -from sqlalchemy import Engine -from sqlmodel import Session, select -from tenacity import after_log, before_log, retry, stop_after_attempt, wait_fixed - -from app.core.db import engine - -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) - -max_tries = 60 * 5 # 5 minutes -wait_seconds = 1 - - -@retry( - stop=stop_after_attempt(max_tries), - wait=wait_fixed(wait_seconds), - before=before_log(logger, logging.INFO), - after=after_log(logger, logging.WARN), -) -def init(db_engine: Engine) -> None: - try: - # Try to create session to check if DB is awake - with Session(db_engine) as session: - session.exec(select(1)) - except Exception as e: - logger.error(e) - raise e - - -def main() -> None: - logger.info("Initializing service") - init(engine) - logger.info("Service finished initializing") - - -if __name__ == "__main__": - main() diff --git a/backend/pyproject.toml b/backend/pyproject.toml index c473adac5d..982944a48d 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -7,7 +7,6 @@ dependencies = [ "fastapi[standard]>=0.141.1,<1.0.0", "python-multipart<1.0.0,>=0.0.27", "email-validator<3.0.0.0,>=2.1.0.post1", - "tenacity<10.0.0,>=8.2.3", "pydantic>2.0", "emails>=1.1.2,<2.0", "jinja2<4.0.0,>=3.1.4", diff --git a/backend/scripts/prestart.sh b/backend/scripts/prestart.sh index 1b395d513f..e67852ba07 100644 --- a/backend/scripts/prestart.sh +++ b/backend/scripts/prestart.sh @@ -3,9 +3,6 @@ set -e set -x -# Let the DB start -python app/backend_pre_start.py - # Run migrations alembic upgrade head diff --git a/backend/scripts/tests-start.sh b/backend/scripts/tests-start.sh index 89dcb0da23..62874d4dc5 100644 --- a/backend/scripts/tests-start.sh +++ b/backend/scripts/tests-start.sh @@ -2,6 +2,4 @@ set -e set -x -python app/tests_pre_start.py - bash scripts/test.sh "$@" diff --git a/backend/tests/scripts/test_backend_pre_start.py b/backend/tests/scripts/test_backend_pre_start.py deleted file mode 100644 index e8f35c644a..0000000000 --- a/backend/tests/scripts/test_backend_pre_start.py +++ /dev/null @@ -1,33 +0,0 @@ -from unittest.mock import MagicMock, patch - -from sqlmodel import select - -from app.backend_pre_start import init, logger - - -def test_init_successful_connection() -> None: - engine_mock = MagicMock() - - session_mock = MagicMock() - session_mock.__enter__.return_value = session_mock - - select1 = select(1) - - with ( - patch("app.backend_pre_start.Session", return_value=session_mock), - patch("app.backend_pre_start.select", return_value=select1), - patch.object(logger, "info"), - patch.object(logger, "error"), - patch.object(logger, "warn"), - ): - try: - init(engine_mock) - connection_successful = True - except Exception: - connection_successful = False - - assert connection_successful, ( - "The database connection should be successful and not raise an exception." - ) - - session_mock.exec.assert_called_once_with(select1) diff --git a/backend/tests/scripts/test_test_pre_start.py b/backend/tests/scripts/test_test_pre_start.py deleted file mode 100644 index 180bdd5232..0000000000 --- a/backend/tests/scripts/test_test_pre_start.py +++ /dev/null @@ -1,33 +0,0 @@ -from unittest.mock import MagicMock, patch - -from sqlmodel import select - -from app.tests_pre_start import init, logger - - -def test_init_successful_connection() -> None: - engine_mock = MagicMock() - - session_mock = MagicMock() - session_mock.__enter__.return_value = session_mock - - select1 = select(1) - - with ( - patch("app.tests_pre_start.Session", return_value=session_mock), - patch("app.tests_pre_start.select", return_value=select1), - patch.object(logger, "info"), - patch.object(logger, "error"), - patch.object(logger, "warn"), - ): - try: - init(engine_mock) - connection_successful = True - except Exception: - connection_successful = False - - assert connection_successful, ( - "The database connection should be successful and not raise an exception." - ) - - session_mock.exec.assert_called_once_with(select1) diff --git a/uv.lock b/uv.lock index 1a2b12f6e8..b09bf1ed10 100644 --- a/uv.lock +++ b/uv.lock @@ -82,7 +82,6 @@ dependencies = [ { name = "python-multipart" }, { name = "sentry-sdk", extra = ["fastapi"] }, { name = "sqlmodel" }, - { name = "tenacity" }, ] [package.dev-dependencies] @@ -110,7 +109,6 @@ requires-dist = [ { name = "python-multipart", specifier = ">=0.0.27,<1.0.0" }, { name = "sentry-sdk", extras = ["fastapi"], specifier = ">=2.66.1,<3.0.0" }, { name = "sqlmodel", specifier = ">=0.0.39,<1.0.0" }, - { name = "tenacity", specifier = ">=8.2.3,<10.0.0" }, ] [package.metadata.requires-dev] @@ -1284,15 +1282,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/bb/2799cc2ede3ed41131f8975621e7213dfc7ef4acbbaadfa440f32500c370/starlette-1.3.1-py3-none-any.whl", hash = "sha256:c7372aae11c3c3f26a42df7bd626cec2f47d03483d261d369516a615a53714c6", size = 73632, upload-time = "2026-06-12T09:23:10.017Z" }, ] -[[package]] -name = "tenacity" -version = "9.1.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/47/c6/ee486fd809e357697ee8a44d3d69222b344920433d3b6666ccd9b374630c/tenacity-9.1.4.tar.gz", hash = "sha256:adb31d4c263f2bd041081ab33b498309a57c77f9acf2db65aadf0898179cf93a", size = 49413, upload-time = "2026-02-07T10:45:33.841Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d7/c1/eb8f9debc45d3b7918a32ab756658a0904732f75e555402972246b0b8e71/tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55", size = 28926, upload-time = "2026-02-07T10:45:32.24Z" }, -] - [[package]] name = "ty" version = "0.0.54"