diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py index 9d0fee15..79dd8070 100644 --- a/gunicorn/arbiter.py +++ b/gunicorn/arbiter.py @@ -51,6 +51,7 @@ class Arbiter(object): def __init__(self, app): os.environ["SERVER_SOFTWARE"] = SERVER_SOFTWARE + self._num_workers = None self.setup(app) self.pidfile = None @@ -79,6 +80,14 @@ class Arbiter(object): 0: sys.executable } + def _get_num_workers(self): + return self._num_workers + def _set_num_workers(self, value): + old_value = self._num_workers + self._num_workers = value + self.cfg.nworkers_changed(self, value, old_value) + num_workers = property(_get_num_workers, _set_num_workers) + def setup(self, app): self.app = app self.cfg = app.cfg diff --git a/gunicorn/config.py b/gunicorn/config.py index c02f4459..e3e25f06 100644 --- a/gunicorn/config.py +++ b/gunicorn/config.py @@ -1056,6 +1056,24 @@ class WorkerExit(Setting): the just-exited Worker. """ +class NumWorkersChanged(Setting): + name = "nworkers_changed" + section = "Server Hooks" + validator = validate_callable(3) + type = "callable" + def nworkers_changed(server, new_value, old_value): + pass + default = staticmethod(nworkers_changed) + desc = """\ + Called just after num_workers has been changed. + + The callable needs to accept an instance variable of the Arbiter and + two integers of number of workers after and before change. + + If the number of workers is set for the first time, old_value would be + None. + """ + class ProxyProtocol(Setting): name = "proxy_protocol" section = "Server Mechanics" diff --git a/tests/test_003-config.py b/tests/test_003-config.py index b2431a12..030312e3 100644 --- a/tests/test_003-config.py +++ b/tests/test_003-config.py @@ -214,3 +214,12 @@ def test_post_request(): c.set("post_request", post_request_2) t.eq(2, c.post_request(1, 2, 3, 4)) + + +def test_nworkers_changed(): + c = config.Config() + def nworkers_changed_3(server, new_value, old_value): + return 3 + + c.set("nworkers_changed", nworkers_changed_3) + t.eq(3, c.nworkers_changed(1, 2, 3))