🐛 — Fix recurring tasks with gunicorn

This commit is contained in:
Luc Didry 2025-02-18 14:57:49 +01:00
parent 4b78919937
commit 38cc06e972
No known key found for this signature in database
GPG key ID: EA868E12D0257E3C
4 changed files with 21 additions and 1 deletions

View file

@ -2,6 +2,8 @@
## [Unreleased] ## [Unreleased]
- 🐛 — Fix recurring tasks with gunicorn
## 0.8.1 ## 0.8.1
Date: 2025-02-18 Date: 2025-02-18
@ -27,6 +29,8 @@ a new example configuration file.
💥 You dont need cron tasks anymore! 💥 You dont need cron tasks anymore!
Remove your old cron tasks as they will now do nothing but generating errors. 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 ## 0.7.4
Date: 2025-02-12 Date: 2025-02-12

View file

@ -6,6 +6,7 @@ from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
from fastapi_login import LoginManager from fastapi_login import LoginManager
from fastapi_utils.tasks import repeat_every from fastapi_utils.tasks import repeat_every
from psutil import Process
from sqlalchemy import create_engine, event from sqlalchemy import create_engine, event
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
@ -116,8 +117,20 @@ def create_manager(cookie_secret: str) -> LoginManager:
@repeat_every(seconds=120, logger=logger) @repeat_every(seconds=120, logger=logger)
async def recurring_tasks() -> None: async def recurring_tasks() -> None:
"""Recurring DB cleanup and watch-agents tasks""" """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) set_log_level("info", quiet=True)
logger.info("Start background recurring tasks") logger.info("Start background recurring tasks")
with app.state.SessionLocal() as db: with app.state.SessionLocal() as db:
config = app.state.config.recurring_tasks config = app.state.config.recurring_tasks
removed = await queries.remove_old_results(db, config.max_results) 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") logger.info("Background recurring tasks ended")
return None
@asynccontextmanager @asynccontextmanager
async def lifespan(appli: FastAPI): async def lifespan(appli: FastAPI):

View file

@ -90,7 +90,7 @@ User=argos
WorkingDirectory=/opt/argos/ WorkingDirectory=/opt/argos/
EnvironmentFile=/etc/default/argos-server EnvironmentFile=/etc/default/argos-server
ExecStartPre=/opt/argos/venv/bin/argos server migrate 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()" \\ ExecStart=/opt/argos/venv/bin/gunicorn "argos.server.main:get_application()" \\
--workers \$ARGOS_SERVER_WORKERS \\ --workers \$ARGOS_SERVER_WORKERS \\
--worker-class uvicorn.workers.UvicornWorker \\ --worker-class uvicorn.workers.UvicornWorker \\

View file

@ -33,6 +33,7 @@ dependencies = [
"Jinja2>=3.0,<4", "Jinja2>=3.0,<4",
"jsonpointer>=3.0,<4", "jsonpointer>=3.0,<4",
"passlib>=1.7.4,<2", "passlib>=1.7.4,<2",
"psutil>=5.9.8,<6",
"psycopg2-binary>=2.9,<3", "psycopg2-binary>=2.9,<3",
"pydantic[email]>=2.4,<3", "pydantic[email]>=2.4,<3",
"pydantic-settings>=2.0,<3", "pydantic-settings>=2.0,<3",