diff --git a/projects/tentacles/BUILD b/projects/tentacles/BUILD index 4febfd8..336cd7d 100644 --- a/projects/tentacles/BUILD +++ b/projects/tentacles/BUILD @@ -6,12 +6,12 @@ py_project( main_deps = [ "//projects/anosql", "//projects/anosql-migrations", + "//projects/cherry-shim", py_requirement("attrs"), py_requirement("click"), py_requirement("flask"), py_requirement("jinja2"), py_requirement("octorest"), - py_requirement("cherrypy"), ], lib_data = [ "//projects/tentacles/src/python/tentacles/static/css", diff --git a/projects/tentacles/src/python/tentacles/__main__.py b/projects/tentacles/src/python/tentacles/__main__.py index 370915a..506aa0a 100644 --- a/projects/tentacles/src/python/tentacles/__main__.py +++ b/projects/tentacles/src/python/tentacles/__main__.py @@ -3,13 +3,13 @@ """The core app entrypoint.""" from datetime import datetime -import logging from pathlib import Path import tomllib -import cherrypy import click from flask import Flask, request + +from cherry_shim import shim from tentacles.blueprints import ( api, file_ui, @@ -19,7 +19,7 @@ from tentacles.blueprints import ( ) from tentacles.globals import _ctx, Ctx, ctx from tentacles.store import Store -from tentacles.workers import Worker +from tentacles.workers import create_workers @click.group() @@ -27,7 +27,7 @@ def cli(): pass -def db_factory(app): +def store_factory(app): store = Store(app.config.get("db", {}).get("uri")) store.connect() return store @@ -35,7 +35,7 @@ def db_factory(app): def custom_ctx(app, wsgi_app): def helper(environ, start_response): - store = db_factory(app) + store = store_factory(app) token = _ctx.set(Ctx(store)) try: return wsgi_app(environ, start_response) @@ -76,11 +76,21 @@ def user_session(): ctx.is_admin = user.group_id == 0 -def make_app(): +@cli.command() +@click.option("--hostname", "hostname", type=str, default="0.0.0.0") +@click.option("--port", "port", type=int, default=8080) +@click.option("--config", type=Path) +def serve(hostname: str, port: int, config: Path): app = Flask(__name__) + if config: + with open(config, "rb") as fp: + app.config.update(tomllib.load(fp)) + + print(app.config) # Before first request create_j2_request_global(app) + shutdown_event = create_workers(app, store_factory) # Before request app.before_request(user_session) @@ -94,51 +104,13 @@ def make_app(): # Shove our middleware in there app.wsgi_app = custom_ctx(app, app.wsgi_app) + cherry = shim(app) - return app - - -@cli.command() -@click.option("--hostname", "hostname", type=str, default="0.0.0.0") -@click.option("--port", "port", type=int, default=8080) -@click.option("--config", type=Path) -def serve(hostname: str, port: int, config: Path): - logging.basicConfig( - format="%(asctime)s %(relativeCreated)6d %(threadName)s - %(name)s - %(levelname)s - %(message)s", - level=logging.INFO, - ) - - logging.getLogger("tentacles").setLevel(logging.DEBUG) - - app = make_app() - - if config: - with open(config, "rb") as fp: - app.config.update(tomllib.load(fp)) - print(app.config) - - cherrypy.server.unsubscribe() - server = cherrypy._cpserver.Server() - cherrypy.config.update( - { - "environment": "production", - "engine.autoreload.on": False, - } - ) - cherrypy.tree.graft(app, "/") - - server.socket_host = hostname - server.socket_port = port - server.thread_pool = 16 - server.shutdown_timeout = 1 - server.subscribe() - - # Spawn the worker thread - Worker(cherrypy.engine, app, db_factory, frequency=5).start() - - # Run the server - cherrypy.engine.start() - cherrypy.engine.block() + # And run the blame thing + try: + cherry.run(host=hostname, port=port) + finally: + shutdown_event.set() if __name__ == "__main__": diff --git a/projects/tentacles/src/python/tentacles/workers.py b/projects/tentacles/src/python/tentacles/workers.py index 6dafcdd..410efca 100644 --- a/projects/tentacles/src/python/tentacles/workers.py +++ b/projects/tentacles/src/python/tentacles/workers.py @@ -11,13 +11,13 @@ from contextlib import closing from datetime import datetime, timedelta import logging from pathlib import Path -from threading import Event +from threading import Event, Thread from time import sleep +from typing import Callable from urllib import parse as urlparse -from cherrypy.process.plugins import Monitor from fastmail import FastMailSMTP -from flask import Flask as App +from flask import Flask as App, render_template from octorest import OctoRest as _OR from requests import Response from requests.exceptions import ( @@ -271,18 +271,18 @@ def send_emails(app, store: Store): store.send_email(message.id) -class Worker(Monitor): - def __init__(self, bus, app, db_factory, **kwargs): - self._app = app - self._db_factory = db_factory - super().__init__(bus, self.callback, **kwargs) +@corn_job(timedelta(seconds=5)) +def run_worker(app: App, db_factory): + with app.app_context(), closing(db_factory(app)) as store: + poll_printers(app, store) + assign_jobs(app, store) + push_jobs(app, store) + revoke_jobs(app, store) + pull_jobs(app, store) + send_emails(app, store) - def callback(self): - log.debug("Tick") - with self._app.app_context(), closing(self._db_factory(self._app)) as store: - poll_printers(self._app, store) - assign_jobs(self._app, store) - push_jobs(self._app, store) - revoke_jobs(self._app, store) - pull_jobs(self._app, store) - send_emails(self._app, store) + +def create_workers(app, db_factory: Callable[[App], Store]) -> Event: + Thread(target=run_worker, args=[app, db_factory]).start() + + return SHUTDOWN diff --git a/tools/python/requirements.in b/tools/python/requirements.in index f48906d..8705e45 100644 --- a/tools/python/requirements.in +++ b/tools/python/requirements.in @@ -1,6 +1,5 @@ -c constraints.in -aiosql ExifRead aiohttp aiohttp_basicauth diff --git a/tools/python/requirements_lock.txt b/tools/python/requirements_lock.txt index 5c93185..fd233f9 100644 --- a/tools/python/requirements_lock.txt +++ b/tools/python/requirements_lock.txt @@ -1,7 +1,6 @@ aiohttp==3.8.4 aiohttp-basicauth==1.0.0 aiosignal==1.3.1 -aiosql==8.0 alabaster==0.7.13 async-lru==2.0.2 async-timeout==4.0.2