125 lines
3.4 KiB
Python
125 lines
3.4 KiB
Python
"""Grotti starten. Kern und Seiten liegen daneben."""
|
|
|
|
import atexit
|
|
import signal
|
|
import threading
|
|
import time
|
|
|
|
from waitress import serve
|
|
|
|
from grotti import db, jobs, library, logutil, store
|
|
from grotti.config import load
|
|
from web.app import create_app
|
|
|
|
log = logutil.get("grotti.server")
|
|
|
|
|
|
def background(cfg):
|
|
def work():
|
|
try:
|
|
with db.connect(cfg["database_url"]) as conn:
|
|
library.sync_watch(conn, cfg, force=False)
|
|
jobs.sync_history(conn, cfg)
|
|
deleted = db.prune_run_samples(conn, keep_days=90)
|
|
if deleted:
|
|
log.info("Proben gelöscht: %s", deleted)
|
|
conn.commit()
|
|
except Exception as exc:
|
|
log.warning("Abgleich: %s", exc)
|
|
|
|
threading.Thread(target=work, name="grotti-abgleich", daemon=True).start()
|
|
|
|
|
|
def _retention_loop(cfg, stop_event):
|
|
"""Nächtlich alte run_samples entfernen."""
|
|
while not stop_event.wait(3600):
|
|
hour = time.localtime().tm_hour
|
|
if hour != 3:
|
|
continue
|
|
try:
|
|
with db.connect(cfg["database_url"]) as conn:
|
|
n = db.prune_run_samples(conn, keep_days=90)
|
|
conn.commit()
|
|
if n:
|
|
log.info("Retention: %s Proben gelöscht.", n)
|
|
except Exception as exc:
|
|
log.warning("Retention: %s", exc)
|
|
stop_event.wait(3600)
|
|
|
|
|
|
def main():
|
|
cfg = load()
|
|
logutil.setup(cfg.get("log_level") or "INFO")
|
|
cfg["data_dir"].mkdir(parents=True, exist_ok=True)
|
|
(cfg["data_dir"] / "eingang").mkdir(exist_ok=True)
|
|
db.prepare(cfg["database_url"])
|
|
db.init_pool(cfg["database_url"], min_size=2, max_size=16)
|
|
with db.connect(cfg["database_url"]) as conn:
|
|
store.seed_printers(conn, cfg["printers_file"])
|
|
store.seed_materials(conn)
|
|
conn.commit()
|
|
|
|
app = create_app(cfg)
|
|
watcher = app.extensions["watcher"]
|
|
dispatcher = app.extensions["print_queue"]
|
|
send_queue = app.extensions["send_queue"]
|
|
watcher.start()
|
|
dispatcher.start()
|
|
if hasattr(send_queue, "start"):
|
|
send_queue.start()
|
|
from grotti.daily_report import DailyReportThread
|
|
daily = DailyReportThread(cfg["database_url"], cfg, watcher=watcher)
|
|
daily.start()
|
|
app.extensions["daily_report"] = daily
|
|
|
|
stop_event = threading.Event()
|
|
retention = threading.Thread(
|
|
target=_retention_loop,
|
|
args=(cfg, stop_event),
|
|
name="grotti-retention",
|
|
daemon=True,
|
|
)
|
|
retention.start()
|
|
background(cfg)
|
|
|
|
def shutdown(*_args):
|
|
stop_event.set()
|
|
try:
|
|
watcher.stop()
|
|
except Exception:
|
|
pass
|
|
try:
|
|
dispatcher.stop()
|
|
except Exception:
|
|
pass
|
|
try:
|
|
if hasattr(send_queue, "stop"):
|
|
send_queue.stop()
|
|
except Exception:
|
|
pass
|
|
try:
|
|
daily.stop()
|
|
except Exception:
|
|
pass
|
|
db.close_pool()
|
|
|
|
atexit.register(shutdown)
|
|
for sig in (signal.SIGINT, signal.SIGTERM):
|
|
try:
|
|
signal.signal(sig, lambda *_: shutdown())
|
|
except (ValueError, OSError):
|
|
pass
|
|
|
|
log.info("Grotti: http://%s:%s/", cfg["host"], cfg["port"])
|
|
serve(
|
|
app,
|
|
host=cfg["host"],
|
|
port=cfg["port"],
|
|
threads=int(cfg.get("http_threads") or 16),
|
|
channel_timeout=120,
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|