Added use_werkzeug_server
option to backend.http
.
There are situations where you may not want to run the HTTP server in a full blown WSGI-over-Tornado container - unit/integration tests and embedded single-core devices are among those cases. In those scenarios, we should allow the user to be able to run the backend using the built-in Werkzeug server provided by Flask.
This commit is contained in:
parent
013274bcbc
commit
666ea9ea6b
3 changed files with 48 additions and 22 deletions
|
@ -199,6 +199,7 @@ class HttpBackend(Backend):
|
|||
resource_dirs: Optional[Mapping[str, str]] = None,
|
||||
secret_key_file: Optional[str] = None,
|
||||
num_workers: Optional[int] = None,
|
||||
use_werkzeug_server: bool = False,
|
||||
**kwargs,
|
||||
):
|
||||
"""
|
||||
|
@ -211,6 +212,16 @@ class HttpBackend(Backend):
|
|||
:param secret_key_file: Path to the file containing the secret key that will be used by Flask
|
||||
(default: ``~/.local/share/platypush/flask.secret.key``).
|
||||
:param num_workers: Number of worker processes to use (default: ``(cpu_count * 2) + 1``).
|
||||
:param use_werkzeug_server: Whether the backend should be served by a
|
||||
Werkzeug server (default: ``False``). Note that using the built-in
|
||||
Werkzeug server instead of Tornado is very inefficient, and it
|
||||
doesn't support websocket-based features either so the UI will
|
||||
probably be severely limited. You should only use this option if:
|
||||
|
||||
- You are running tests.
|
||||
- You have issues with running a full Tornado server - for
|
||||
example, you are running the application on a small embedded
|
||||
device that doesn't support Tornado.
|
||||
"""
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
@ -235,6 +246,7 @@ class HttpBackend(Backend):
|
|||
)
|
||||
self.local_base_url = f'http://localhost:{self.port}'
|
||||
self.num_workers = num_workers or (cpu_count() * 2) + 1
|
||||
self.use_werkzeug_server = use_werkzeug_server
|
||||
|
||||
def send_message(self, *_, **__):
|
||||
self.logger.warning('Use cURL or any HTTP client to query the HTTP backend')
|
||||
|
@ -339,14 +351,25 @@ class HttpBackend(Backend):
|
|||
self.num_workers,
|
||||
)
|
||||
|
||||
sockets = bind_sockets(self.port, address=self.bind_address, reuse_port=True)
|
||||
if self.use_werkzeug_server:
|
||||
application.config['redis_queue'] = self.bus.redis_queue
|
||||
application.run(
|
||||
host=self.bind_address,
|
||||
port=self.port,
|
||||
use_reloader=False,
|
||||
debug=True,
|
||||
)
|
||||
else:
|
||||
sockets = bind_sockets(
|
||||
self.port, address=self.bind_address, reuse_port=True
|
||||
)
|
||||
|
||||
try:
|
||||
fork_processes(self.num_workers)
|
||||
future = self._post_fork_main(sockets)
|
||||
asyncio.run(future)
|
||||
except (asyncio.CancelledError, KeyboardInterrupt):
|
||||
return
|
||||
try:
|
||||
fork_processes(self.num_workers)
|
||||
future = self._post_fork_main(sockets)
|
||||
asyncio.run(future)
|
||||
except (asyncio.CancelledError, KeyboardInterrupt):
|
||||
return
|
||||
|
||||
def _start_web_server(self):
|
||||
self._server_proc = Process(target=self._web_server_proc)
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import logging
|
||||
import os
|
||||
import pytest
|
||||
import time
|
||||
from threading import Thread
|
||||
|
||||
import pytest
|
||||
|
||||
from platypush import Daemon, Config
|
||||
|
||||
from .utils import config_file, set_base_url
|
||||
|
@ -17,8 +18,6 @@ def clear_loggers():
|
|||
This is to prevent pytest spitting out logging errors on teardown if the logging objects have been deinitialized
|
||||
(see https://github.com/pytest-dev/pytest/issues/5502#issuecomment-647157873).
|
||||
"""
|
||||
import logging
|
||||
# noinspection PyUnresolvedReferences
|
||||
loggers = [logging.getLogger()] + list(logging.Logger.manager.loggerDict.values())
|
||||
for logger in loggers:
|
||||
handlers = getattr(logger, 'handlers', [])
|
||||
|
@ -31,31 +30,34 @@ def app():
|
|||
logging.info('Starting Platypush test service')
|
||||
|
||||
Config.init(config_file)
|
||||
app = Daemon(config_file=config_file, redis_queue='platypush-tests/bus')
|
||||
Thread(target=lambda: app.run()).start()
|
||||
logging.info('Sleeping {} seconds while waiting for the daemon to start up'.format(app_start_timeout))
|
||||
_app = Daemon(config_file=config_file, redis_queue='platypush-tests/bus')
|
||||
Thread(target=_app.run).start()
|
||||
logging.info(
|
||||
'Sleeping %d seconds while waiting for the daemon to start up',
|
||||
app_start_timeout,
|
||||
)
|
||||
time.sleep(app_start_timeout)
|
||||
yield app
|
||||
yield _app
|
||||
|
||||
logging.info('Stopping Platypush test service')
|
||||
app.stop_app()
|
||||
_app.stop_app()
|
||||
clear_loggers()
|
||||
db_file = (Config.get('main.db') or {}).get('engine', '')[len('sqlite:///'):]
|
||||
db = (Config.get('main.db') or {}).get('engine', '')[len('sqlite:///') :]
|
||||
|
||||
if db_file and os.path.isfile(db_file):
|
||||
logging.info('Removing temporary db file {}'.format(db_file))
|
||||
os.unlink(db_file)
|
||||
if db and os.path.isfile(db):
|
||||
logging.info('Removing temporary db file %s', db)
|
||||
os.unlink(db)
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def db_file():
|
||||
yield Config.get('main.db')['engine'][len('sqlite:///'):]
|
||||
yield Config.get('main.db')['engine'][len('sqlite:///') :]
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def base_url():
|
||||
backends = Config.get_backends()
|
||||
assert 'http' in backends, 'Missing HTTP server configuration'
|
||||
url = 'http://localhost:{port}'.format(port=backends['http']['port'])
|
||||
url = f'http://localhost:{backends["http"]["port"]}'
|
||||
set_base_url(url)
|
||||
yield url
|
||||
|
|
|
@ -6,7 +6,8 @@ main.db:
|
|||
|
||||
backend.http:
|
||||
port: 8123
|
||||
disable_websocket: True
|
||||
num_workers: 1
|
||||
use_werkzeug_server: True
|
||||
|
||||
backend.redis:
|
||||
disabled: False
|
||||
|
|
Loading…
Reference in a new issue