mirror of
https://github.com/frappe/gunicorn.git
synced 2026-07-02 18:51:31 +08:00
- /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'.
76 lines
2.3 KiB
Python
76 lines
2.3 KiB
Python
#
|
|
# This file is part of gunicorn released under the MIT license.
|
|
# See the NOTICE for more information.
|
|
|
|
"""Test app with multiple dirty tasks for TTIN/TTOU testing."""
|
|
|
|
import json
|
|
import time
|
|
|
|
from gunicorn.dirty import DirtyApp, get_dirty_client
|
|
|
|
|
|
# Unlimited workers - runs on all dirty workers
|
|
class UnlimitedTask(DirtyApp):
|
|
"""Task that runs on all dirty workers."""
|
|
|
|
def setup(self):
|
|
pass
|
|
|
|
def process(self, data):
|
|
return {"task": "unlimited", "data": data}
|
|
|
|
|
|
# Limited to 2 workers
|
|
class LimitedTask(DirtyApp):
|
|
"""Task limited to 2 workers."""
|
|
|
|
workers = 2
|
|
|
|
def setup(self):
|
|
pass
|
|
|
|
def process(self, data):
|
|
delay = data.get("delay", 0)
|
|
if delay:
|
|
time.sleep(delay)
|
|
return {"task": "limited", "data": data}
|
|
|
|
|
|
def app(environ, start_response):
|
|
"""Simple WSGI app for testing."""
|
|
path = environ.get('PATH_INFO', '/')
|
|
|
|
if path == '/health':
|
|
start_response('200 OK', [('Content-Type', 'text/plain')])
|
|
return [b'OK']
|
|
|
|
# client.execute(app_path, action, *args, **kwargs) — action is the
|
|
# method name on the DirtyApp. The original fixture passed the data
|
|
# dict where ``action`` belongs, which surfaced as a 500 from
|
|
# ``getattr(self, action)`` on the dirty worker.
|
|
if path == '/unlimited':
|
|
try:
|
|
client = get_dirty_client()
|
|
result = client.execute('app:UnlimitedTask', 'process', {'test': 'data'})
|
|
start_response('200 OK', [('Content-Type', 'application/json')])
|
|
return [json.dumps(result).encode()]
|
|
except Exception as e:
|
|
start_response('500 Internal Server Error',
|
|
[('Content-Type', 'text/plain')])
|
|
return [str(e).encode()]
|
|
|
|
if path == '/limited':
|
|
try:
|
|
client = get_dirty_client()
|
|
result = client.execute('app:LimitedTask', 'process', {'test': 'data'})
|
|
start_response('200 OK', [('Content-Type', 'application/json')])
|
|
return [json.dumps(result).encode()]
|
|
except Exception as e:
|
|
start_response('500 Internal Server Error',
|
|
[('Content-Type', 'text/plain')])
|
|
return [str(e).encode()]
|
|
|
|
start_response('404 Not Found', [('Content-Type', 'text/plain')])
|
|
return [b'Not Found']
|