diff --git a/CHANGELOG.md b/CHANGELOG.md index 3edd674..29ead76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## [Unreleased] +- πŸ› β€” Fix recurring tasks with gunicorn + ## 0.8.1 Date: 2025-02-18 @@ -27,6 +29,8 @@ a new example configuration file. πŸ’₯ You don’t need cron tasks anymore! Remove your old cron tasks as they will now do nothing but generating errors. +NB: You may want to add `--enqueue` to `reload-config` command in your systemd file. + ## 0.7.4 Date: 2025-02-12 diff --git a/argos/server/main.py b/argos/server/main.py index c4623d2..85a6a0b 100644 --- a/argos/server/main.py +++ b/argos/server/main.py @@ -6,6 +6,7 @@ from fastapi import FastAPI from fastapi.staticfiles import StaticFiles from fastapi_login import LoginManager from fastapi_utils.tasks import repeat_every +from psutil import Process from sqlalchemy import create_engine, event from sqlalchemy.orm import sessionmaker @@ -116,8 +117,20 @@ def create_manager(cookie_secret: str) -> LoginManager: @repeat_every(seconds=120, logger=logger) async def recurring_tasks() -> None: """Recurring DB cleanup and watch-agents tasks""" + # If we are using gunicorn + if not hasattr(app.state, "SessionLocal"): + parent_process = Process(os.getppid()) + children = parent_process.children(recursive=True) + # Start the task only once, not for every worker + if children[0].pid == os.getpid(): + # and we need to setup database engine + setup_database(app) + else: + return None + set_log_level("info", quiet=True) logger.info("Start background recurring tasks") + with app.state.SessionLocal() as db: config = app.state.config.recurring_tasks removed = await queries.remove_old_results(db, config.max_results) @@ -135,6 +148,8 @@ async def recurring_tasks() -> None: logger.info("Background recurring tasks ended") + return None + @asynccontextmanager async def lifespan(appli: FastAPI): diff --git a/docs/installation/tl-dr.md b/docs/installation/tl-dr.md index d1ff6da..c822c59 100644 --- a/docs/installation/tl-dr.md +++ b/docs/installation/tl-dr.md @@ -90,7 +90,7 @@ User=argos WorkingDirectory=/opt/argos/ EnvironmentFile=/etc/default/argos-server ExecStartPre=/opt/argos/venv/bin/argos server migrate -ExecStartPre=/opt/argos/venv/bin/argos server reload-config +ExecStartPre=/opt/argos/venv/bin/argos server reload-config --enqueue ExecStart=/opt/argos/venv/bin/gunicorn "argos.server.main:get_application()" \\ --workers \$ARGOS_SERVER_WORKERS \\ --worker-class uvicorn.workers.UvicornWorker \\ diff --git a/pyproject.toml b/pyproject.toml index ee56641..3a85b45 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,7 @@ dependencies = [ "Jinja2>=3.0,<4", "jsonpointer>=3.0,<4", "passlib>=1.7.4,<2", + "psutil>=5.9.8,<6", "psycopg2-binary>=2.9,<3", "pydantic[email]>=2.4,<3", "pydantic-settings>=2.0,<3",