Skip to content

feat(bench): make gunicorn keep-alive and worker-tmp-dir configurable#432

Open
mrrobot47 wants to merge 2 commits into
rtCamp:developfrom
mrrobot47:feat/configurable-gunicorn-keepalive-tmpdir
Open

feat(bench): make gunicorn keep-alive and worker-tmp-dir configurable#432
mrrobot47 wants to merge 2 commits into
rtCamp:developfrom
mrrobot47:feat/configurable-gunicorn-keepalive-tmpdir

Conversation

@mrrobot47

Copy link
Copy Markdown
Member

Problem

frappe_manager/site_manager/modules/bench_supervisor.py builds the gunicorn command line for the generated web-server wrapper in _write_gunicorn_wrapper. Two useful gunicorn runtime flags are not supported there:

  • --keep-alive — how long gunicorn keeps an idle client connection open between requests.
  • --worker-tmp-dir — where gunicorn places its per-worker heartbeat files (commonly pointed at a tmpfs such as /dev/shm).

Because the wrapper is regenerated on setup / restart / migrate, an operator who edits the generated script by hand to add either flag loses that customization on the very next FM operation. There is currently no supported way to set these values persistently.

Solution

Expose both flags via common_site_config.json, consistent with the existing gunicorn_workers / gunicorn_max_requests / gunicorn_threads keys:

Key Gunicorn flag Default
gunicorn_keep_alive --keep-alive unset (flag omitted)
gunicorn_worker_tmp_dir --worker-tmp-dir unset (flag omitted)

generate_supervisor_config reads the two keys and adds them to the render context; _write_gunicorn_wrapper conditionally appends the flags only when they are configured.

Backward compatibility

Defaults preserve current behavior exactly. When neither key is set, the generated command is byte-identical to today's output — no --keep-alive, no --worker-tmp-dir.

Default (both keys unset):

-b 0.0.0.0:80 -w 5 --worker-class=gthread --threads 2 --max-requests 1000 --max-requests-jitter 100 -t 120 --graceful-timeout 30 frappe.app:application --preload

With gunicorn_keep_alive=5 and gunicorn_worker_tmp_dir=/dev/shm:

-b 0.0.0.0:80 -w 5 --worker-class=gthread --threads 2 --max-requests 1000 --max-requests-jitter 100 -t 120 --graceful-timeout 30 --keep-alive 5 --worker-tmp-dir /dev/shm frappe.app:application --preload

Emission rules:

  • gunicorn_keep_alive uses an is not None check, so an explicit 0 still emits --keep-alive 0 (a valid gunicorn value); leaving the key unset omits the flag.
  • gunicorn_worker_tmp_dir is emitted only when set to a non-empty path.

Usage

fm shell mybench -c "bench set-config -g gunicorn_keep_alive 5"
fm shell mybench -c "bench set-config -g gunicorn_worker_tmp_dir /dev/shm"
fm restart mybench

Scope notes

Docs: adds an "Optional Gunicorn Flags" subsection to docs/reference/workers.md documenting the two new keys.

The gunicorn --keep-alive and --worker-tmp-dir flags are not supported in the
generated web-server wrapper. Because the wrapper is regenerated on
setup/restart/migrate, operators who add these flags by hand lose the
customization on the next FM operation.

Expose them via common_site_config.json (gunicorn_keep_alive,
gunicorn_worker_tmp_dir), consistent with the existing gunicorn_workers /
gunicorn_max_requests / gunicorn_threads keys. Defaults preserve current
behavior exactly: both flags are omitted from the command unless configured, so
the generated command is byte-identical to today's output when the keys are
unset. gunicorn_keep_alive is emitted whenever it is set (including 0), while
gunicorn_worker_tmp_dir is emitted when it is a non-empty path.
Copilot AI review requested due to automatic review settings July 1, 2026 19:24
@codecov-commenter

codecov-commenter commented Jul 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 12.50000% with 7 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (develop@6c477d8). Learn more about missing BASE report.

Files with missing lines Patch % Lines
...e_manager/site_manager/modules/bench_supervisor.py 12.50% 7 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             develop     #432   +/-   ##
==========================================
  Coverage           ?   41.09%           
==========================================
  Files              ?      126           
  Lines              ?    11846           
  Branches           ?        0           
==========================================
  Hits               ?     4868           
  Misses             ?     6978           
  Partials           ?        0           
Flag Coverage Δ
unittests 41.09% <12.50%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds persistent configuration support for two additional Gunicorn runtime flags (--keep-alive and --worker-tmp-dir) by sourcing new keys from common_site_config.json and emitting them into the generated fm-web-server.sh wrapper when set, with documentation updates to match.

Changes:

  • Read gunicorn_keep_alive / gunicorn_worker_tmp_dir from common_site_config.json and pass them through the supervisor render context.
  • Conditionally append --keep-alive and --worker-tmp-dir to the generated Gunicorn command line.
  • Document the new optional keys in docs/reference/workers.md.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
frappe_manager/site_manager/modules/bench_supervisor.py Adds two new config-derived Gunicorn flags to the generated wrapper command line.
docs/reference/workers.md Documents the new optional Gunicorn flags and how to configure them.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread frappe_manager/site_manager/modules/bench_supervisor.py
Comment thread frappe_manager/site_manager/modules/bench_supervisor.py Outdated
…ments

gunicorn_worker_tmp_dir is a free-form string from common_site_config.json and
was interpolated raw into the GUNICORN_ARGS="..." wrapper, so a value containing
shell-special characters ($, backtick, quote, backslash, ;) could break the
wrapper or expand at runtime. Wrap both optional-flag values with shlex.quote so
they are always emitted as a single safe shell token.

This does not change output for normal values: shlex.quote("5") == "5" and
shlex.quote("/dev/shm") == "/dev/shm", and with both keys unset the generated
command remains byte-identical to before.

Also correct the two inline comments to match the actual emission rules:
gunicorn_keep_alive is omitted only when unset (0 is still emitted via the
is-not-None guard), and gunicorn_worker_tmp_dir is omitted when unset or empty
(truthiness guard).
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.

3 participants