Embed cherrypy directly

This commit is contained in:
Reid 'arrdem' McKenzie 2023-06-03 10:34:25 -06:00
parent 37226f4cd5
commit e0b97f5f7a
3 changed files with 68 additions and 40 deletions

View file

@ -6,12 +6,12 @@ py_project(
main_deps = [ main_deps = [
"//projects/anosql", "//projects/anosql",
"//projects/anosql-migrations", "//projects/anosql-migrations",
"//projects/cherry-shim",
py_requirement("attrs"), py_requirement("attrs"),
py_requirement("click"), py_requirement("click"),
py_requirement("flask"), py_requirement("flask"),
py_requirement("jinja2"), py_requirement("jinja2"),
py_requirement("octorest"), py_requirement("octorest"),
py_requirement("cherrypy"),
], ],
lib_data = [ lib_data = [
"//projects/tentacles/src/python/tentacles/static/css", "//projects/tentacles/src/python/tentacles/static/css",

View file

@ -3,13 +3,13 @@
"""The core app entrypoint.""" """The core app entrypoint."""
from datetime import datetime from datetime import datetime
import logging
from pathlib import Path from pathlib import Path
import tomllib import tomllib
import cherrypy
import click import click
from flask import Flask, request from flask import Flask, request
from cherry_shim import shim
from tentacles.blueprints import ( from tentacles.blueprints import (
api, api,
file_ui, file_ui,
@ -19,7 +19,7 @@ from tentacles.blueprints import (
) )
from tentacles.globals import _ctx, Ctx, ctx from tentacles.globals import _ctx, Ctx, ctx
from tentacles.store import Store from tentacles.store import Store
from tentacles.workers import create_workers from tentacles.workers import Worker
@click.group() @click.group()
@ -27,7 +27,7 @@ def cli():
pass pass
def store_factory(app): def db_factory(app):
store = Store(app.config.get("db", {}).get("uri")) store = Store(app.config.get("db", {}).get("uri"))
store.connect() store.connect()
return store return store
@ -35,7 +35,7 @@ def store_factory(app):
def custom_ctx(app, wsgi_app): def custom_ctx(app, wsgi_app):
def helper(environ, start_response): def helper(environ, start_response):
store = store_factory(app) store = db_factory(app)
token = _ctx.set(Ctx(store)) token = _ctx.set(Ctx(store))
try: try:
return wsgi_app(environ, start_response) return wsgi_app(environ, start_response)
@ -76,21 +76,11 @@ def user_session():
ctx.is_admin = user.group_id == 0 ctx.is_admin = user.group_id == 0
@cli.command() def make_app():
@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__) app = Flask(__name__)
if config:
with open(config, "rb") as fp:
app.config.update(tomllib.load(fp))
print(app.config)
# Before first request # Before first request
create_j2_request_global(app) create_j2_request_global(app)
shutdown_event = create_workers(app, store_factory)
# Before request # Before request
app.before_request(user_session) app.before_request(user_session)
@ -104,13 +94,51 @@ def serve(hostname: str, port: int, config: Path):
# Shove our middleware in there # Shove our middleware in there
app.wsgi_app = custom_ctx(app, app.wsgi_app) app.wsgi_app = custom_ctx(app, app.wsgi_app)
cherry = shim(app)
# And run the blame thing return app
try:
cherry.run(host=hostname, port=port)
finally: @cli.command()
shutdown_event.set() @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()
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -11,13 +11,13 @@ from contextlib import closing
from datetime import datetime, timedelta from datetime import datetime, timedelta
import logging import logging
from pathlib import Path from pathlib import Path
from threading import Event, Thread from threading import Event
from time import sleep from time import sleep
from typing import Callable
from urllib import parse as urlparse from urllib import parse as urlparse
from cherrypy.process.plugins import Monitor
from fastmail import FastMailSMTP from fastmail import FastMailSMTP
from flask import Flask as App, render_template from flask import Flask as App
from octorest import OctoRest as _OR from octorest import OctoRest as _OR
from requests import Response from requests import Response
from requests.exceptions import ( from requests.exceptions import (
@ -271,18 +271,18 @@ def send_emails(app, store: Store):
store.send_email(message.id) store.send_email(message.id)
@corn_job(timedelta(seconds=5)) class Worker(Monitor):
def run_worker(app: App, db_factory): def __init__(self, bus, app, db_factory, **kwargs):
with app.app_context(), closing(db_factory(app)) as store: self._app = app
poll_printers(app, store) self._db_factory = db_factory
assign_jobs(app, store) super().__init__(bus, self.callback, **kwargs)
push_jobs(app, store)
revoke_jobs(app, store)
pull_jobs(app, store)
send_emails(app, store)
def callback(self):
def create_workers(app, db_factory: Callable[[App], Store]) -> Event: log.debug("Tick")
Thread(target=run_worker, args=[app, db_factory]).start() with self._app.app_context(), closing(self._db_factory(self._app)) as store:
poll_printers(self._app, store)
return SHUTDOWN 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)