Skip to content

Add --max-tasks-jitter to spread out worker restarts - #73

Merged
tokibito merged 1 commit into
mainfrom
feat/max-tasks-jitter
Oct 12, 2026
Merged

tokibito merged 1 commit into
mainfrom
feat/max-tasks-jitter

Conversation

@tokibito

Copy link
Copy Markdown
Owner

Part of #64: the jitter on the task count only. The lifetime and memory conditions stay open in the issue.

Under --workers N --continuous --max-tasks K the workers start together and reach K at about the same time, so they restart together and the host briefly has no worker. --max-tasks-jitter J makes each worker add a random number from 0 to J, drawn once at start, to --max-tasks, as gunicorn's max_requests_jitter does.

What changes

  • New option --max-tasks-jitter J on run_database_tasks, default 0. With 0, --max-tasks behaves exactly as before.
  • The draw happens in the worker, not in the --workers supervisor, so every worker and every restart gets its own value. A worker run by a process manager takes the option the same way.
  • The draw uses random.SystemRandom, so a project that seeds the random module at import does not make every worker draw the same value.
  • The limit drawn is printed at startup (Max tasks: 1037 (1000 + jitter 37 of up to 100)) and carried as a new max_tasks field on the Worker started log record. Reached max tasks limit reports the drawn limit.
  • Help text translated in all four catalogues; README (options table, Running several workers) and CHANGELOG updated.

Decisions to check

  • Name and type: --max-tasks-jitter, an integer count, as proposed in the issue.
  • Without --max-tasks the option is ignored, as gunicorn ignores max_requests_jitter without max_requests, rather than refused. A negative value is refused with a CommandError.
  • max_tasks is added to Worker started so the drawn value is visible in a fleet's logs; it is 0 when there is no limit. No existing field or message changes.

Compatibility

Default 0 keeps the current behaviour; the only change to existing output is the added log field. Existing projects need no changes.

Testing

venv (Django 6.0) and .venv (Django 6.1, -W error::DeprecationWarning) pass, as does the suite against PostgreSQL 16. A smoke run of --workers 3 --continuous --max-tasks 3 --max-tasks-jitter 4 on PostgreSQL showed restarted workers drawing different limits.

Under --workers N --continuous --max-tasks K the workers start together
and reach K at about the same time, so they restart together and the
host briefly has no worker. Each worker now adds a random number from 0
to J, drawn once at start, to --max-tasks, as gunicorn's
max_requests_jitter does. The draw is made in the worker, not the
supervisor, so every worker and every restart gets its own, and it comes
from SystemRandom so a project that seeds the random module does not make
the draws alike. The limit drawn is printed at startup and carried as
max_tasks on the Worker started record.

The default of 0 leaves --max-tasks as it was, and the option is ignored
without --max-tasks.

Part of #64.
@tokibito
tokibito merged commit 9d16e98 into main Oct 12, 2026
10 checks passed
@tokibito
tokibito deleted the feat/max-tasks-jitter branch October 12, 2026 16:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant