- /unlimited and /limited handlers passed the data dict where the dirty
client expected the action (method) name, surfacing as a 500 from
getattr(self, action) on the dirty worker. Pass 'process' as the
action so the call routes to DirtyApp.process(data).
- TestUnlimitedApps now bumps worker count via TTIN and polls both apps
for readiness before each test. The preceding TTOU-spam test pins the
worker count at the LimitedTask floor (2) and the arbiter takes a
moment to rebind apps to the surviving workers; the previous tests
raced that rebind and saw 'No workers available'.
Add support for SIGTTIN and SIGTTOU signals to the dirty arbiter,
allowing dynamic scaling of dirty workers at runtime without restarting
gunicorn.
Changes:
- Add TTIN/TTOU to DirtyArbiter.SIGNALS
- Add num_workers instance variable for dynamic count
- Add _get_minimum_workers() to enforce app worker constraints
- Add signal handlers for TTIN (increase) and TTOU (decrease)
- Update manage_workers() to use dynamic count
- Add documentation for dynamic scaling
- Add unit tests for signal handling
- Add Docker integration tests
The minimum worker constraint ensures TTOU cannot reduce workers below
what apps require (e.g., if an app has workers=3, minimum is 3).
Closes#3489