Compare commits

...

6 Commits

Author SHA1 Message Date
Ariel Rin
762a28948f Merge branch 'servicesworker' into 'v5.x'
Singlethread Services Worker

See merge request allianceauth/allianceauth!1698
2025-04-07 04:17:56 +00:00
Joel Falknau
49a271a99f
update pre-commit 2025-04-07 14:04:06 +10:00
Joel Falknau
af87da876b
Celery 5.5 + shutdown timeouts 2025-04-07 14:01:33 +10:00
Joel Falknau
57b3841293
internal network port only 2025-04-07 13:57:57 +10:00
Joel Falknau
7ec4325973
add to group and memmon 2025-03-06 12:27:52 +10:00
Joel Falknau
f1145c09c0
Create singlethreaded services worker 2025-03-06 10:19:51 +10:00
6 changed files with 46 additions and 9 deletions

View File

@ -25,13 +25,13 @@ exclude: |
repos: repos:
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.0 rev: v0.11.4
hooks: hooks:
# Run the linter, and only the linter # Run the linter, and only the linter
- id: ruff - id: ruff
- repo: https://github.com/adamchainz/django-upgrade - repo: https://github.com/adamchainz/django-upgrade
rev: 1.23.1 rev: 1.24.0
hooks: hooks:
- id: django-upgrade - id: django-upgrade
args: [--target-version=5.1] args: [--target-version=5.1]
@ -73,7 +73,7 @@ repos:
- id: check-executables-have-shebangs - id: check-executables-have-shebangs
- id: end-of-file-fixer - id: end-of-file-fixer
- repo: https://github.com/editorconfig-checker/editorconfig-checker.python - repo: https://github.com/editorconfig-checker/editorconfig-checker.python
rev: 3.2.0 rev: 3.2.1
hooks: hooks:
- id: editorconfig-checker - id: editorconfig-checker
- repo: https://github.com/igorshubovych/markdownlint-cli - repo: https://github.com/igorshubovych/markdownlint-cli
@ -97,6 +97,6 @@ repos:
hooks: hooks:
- id: tox-ini-fmt - id: tox-ini-fmt
- repo: https://github.com/abravalheri/validate-pyproject - repo: https://github.com/abravalheri/validate-pyproject
rev: v0.24 rev: v0.24.1
hooks: hooks:
- id: validate-pyproject - id: validate-pyproject

View File

@ -31,6 +31,13 @@ app.conf.ONCE = {
'settings': {} 'settings': {}
} }
app.conf.task_routes = {
# Some AA Services are sensitive to threaded tasks
# Utilize a single threaded worker to process these tasks
# Discord: Multithreads can cause duplicate role creation.
"discord.*": {"queue": "services"},
}
# Load task modules from all registered Django app configs. # Load task modules from all registered Django app configs.
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

View File

@ -24,6 +24,21 @@ stopwaitsecs = 600
killasgroup=true killasgroup=true
priority=998 priority=998
[program:worker_services]
command={{ celery }} -A {{ project_name }} worker --pool=threads --concurrency=1 -Q services -n %(program_name)s_%(process_num)02d
directory={{ project_directory }}
user=allianceserver
numprocs=1
process_name=%(program_name)s_%(process_num)02d
stdout_logfile={{ project_directory }}/log/worker_services.log
stderr_logfile={{ project_directory }}/log/worker_services.log
autostart=true
autorestart=true
startsecs=10
stopwaitsecs = 600
killasgroup=true
priority=998
{% if gunicorn %} {% if gunicorn %}
[program:gunicorn] [program:gunicorn]
user = allianceserver user = allianceserver
@ -38,12 +53,12 @@ stopsignal=INT
{% endif %} {% endif %}
[eventlistener:memmon] [eventlistener:memmon]
command={{ memmon }} -p worker_00=256MB -p gunicorn=256MB command={{ memmon }} -p worker_00=256MB -p worker_services_00=256MB -p gunicorn=256MB
directory={{ project_directory }} directory={{ project_directory }}
events=TICK_60 events=TICK_60
stdout_logfile={{ project_directory }}/log/memmon.log stdout_logfile={{ project_directory }}/log/memmon.log
stderr_logfile={{ project_directory }}/log/memmon.log stderr_logfile={{ project_directory }}/log/memmon.log
[group:{{ project_name }}] [group:{{ project_name }}]
programs=beat,worker{% if gunicorn %},gunicorn{% endif %} programs=beat,worker,worker_services{% if gunicorn %},gunicorn{% endif %}
priority=999 priority=999

View File

@ -14,6 +14,10 @@ app = Celery('myauth')
# Celery startup if it is unavailable. # Celery startup if it is unavailable.
app.conf.broker_connection_retry_on_startup = True app.conf.broker_connection_retry_on_startup = True
# Set a hard task execution time of 5 minutes before celery will cold restart
app.conf.worker_soft_shutdown_timeout = 300
app.conf.worker_enable_soft_shutdown_on_idle = True
# Using a string here means the worker don't have to serialize # Using a string here means the worker don't have to serialize
# the configuration object to child processes. # the configuration object to child processes.
app.config_from_object('django.conf:settings') app.config_from_object('django.conf:settings')
@ -31,6 +35,13 @@ app.conf.ONCE = {
'settings': {} 'settings': {}
} }
app.conf.task_routes = {
# Some AA Services are sensitive to threaded tasks
# Utilize a single threaded worker to process these tasks
# Discord: Multithreads can cause duplicate role creation.
"discord.*": {"queue": "services"},
}
# Load task modules from all registered Django app configs. # Load task modules from all registered Django app configs.
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

View File

@ -89,8 +89,8 @@ services:
container_name: allianceauth_gunicorn container_name: allianceauth_gunicorn
<<: [*allianceauth-base] <<: [*allianceauth-base]
entrypoint: ["gunicorn", "myauth.wsgi", "--bind=0.0.0.0:8000", "--workers=3", "--timeout=120", "--max-requests=500", "--max-requests-jitter=50"] entrypoint: ["gunicorn", "myauth.wsgi", "--bind=0.0.0.0:8000", "--workers=3", "--timeout=120", "--max-requests=500", "--max-requests-jitter=50"]
ports: expose:
- 8000:8000 - 8000
allianceauth_beat: allianceauth_beat:
container_name: allianceauth_worker_beat container_name: allianceauth_worker_beat
@ -103,6 +103,10 @@ services:
deploy: deploy:
replicas: 2 replicas: 2
allianceauth_worker_services:
<<: [*allianceauth-base, *allianceauth-health-checks]
entrypoint: ["celery", "-A", "myauth", "worker", "--pool=threads", "--concurrency=1", "-Q" , "services" , "-n", "worker_services_%n"]
grafana: grafana:
image: grafana/grafana-oss:latest image: grafana/grafana-oss:latest
restart: always restart: always

View File

@ -40,7 +40,7 @@ dynamic = [
dependencies = [ dependencies = [
"bcrypt", "bcrypt",
"beautifulsoup4", "beautifulsoup4",
"celery>=5.4,<6", "celery>=5.5,<6",
"celery-once>=3.0.1", "celery-once>=3.0.1",
"django>=5.1,<5.2", "django>=5.1,<5.2",
"django-bootstrap-form", "django-bootstrap-form",