68 lines
2.4 KiB
Python
68 lines
2.4 KiB
Python
"""notify-send, every 60 seconds: seed the rules, note a new build, run the watch checks (at most every 15 minutes)
|
|||
|
|
and deliver the events nobody has handled yet. Not pausable."""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import time as clock
|
||
|
|
from datetime import datetime
|
||
|
|
|
||
|
|
from ...feed.config import FeedSettings
|
||
|
|
from ...notify import seed as seed_rules
|
||
|
|
from ...notify import send, watch
|
||
|
|
from . import Counts, JobContext, JobSpec, directory, reload_departments
|
||
|
|
|
||
|
|
EVERY_SECONDS = 60
|
||
|
|
WATCH_SECONDS = 15 * 60
|
||
|
|
WATCH_KEY = "notify.watch_at"
|
||
|
|
BUILD_KEY = "notify.build_noted"
|
||
|
|
|
||
|
|
|
||
|
|
def _due(ctx: JobContext, key: str, seconds: float) -> bool:
|
||
|
|
"""True once per `seconds` per worker process; marks the time when it says so."""
|
||
|
|
now = clock.monotonic()
|
||
|
|
with ctx.stack.lock:
|
||
|
|
last = ctx.stack.cache.get(key)
|
||
|
|
if last is not None and now - float(last) < seconds:
|
||
|
|
return False
|
||
|
|
ctx.stack.cache[key] = now
|
||
|
|
return True
|
||
|
|
|
||
|
|
|
||
|
|
def run(ctx: JobContext) -> Counts:
|
||
|
|
conn, s = ctx.conn, ctx.settings
|
||
|
|
counts: Counts = {}
|
||
|
|
added = seed_rules(conn, s)
|
||
|
|
if added:
|
||
|
|
counts["seeded"] = len(added)
|
||
|
|
if _due(ctx, BUILD_KEY, float("inf")):
|
||
|
|
try:
|
||
|
|
if watch.note_build(conn, s.ps_build) is not None:
|
||
|
|
counts["version_deployed"] = s.ps_build
|
||
|
|
except Exception as e:
|
||
|
|
ctx.stack.drop(BUILD_KEY) # try again on the next run
|
||
|
|
ctx.error(f"version check: {type(e).__name__}", degrade=False)
|
||
|
|
if _due(ctx, WATCH_KEY, WATCH_SECONDS):
|
||
|
|
for name, check in (("drawings", watch.check_drawings), ("change orders", watch.check_change_orders)):
|
||
|
|
try:
|
||
|
|
counts.update(check(conn))
|
||
|
|
except Exception as e:
|
||
|
|
ctx.log.exception("watch check %s failed", name)
|
||
|
|
ctx.error(f"watch {name}: {type(e).__name__}")
|
||
|
|
pending = conn.execute(
|
||
|
|
"SELECT EXISTS (SELECT 1 FROM notification_events WHERE dispatched_at IS NULL AND event_type IS NOT NULL)"
|
||
|
|
).fetchone()[0]
|
||
|
|
if pending:
|
||
|
|
reload_departments(conn)
|
||
|
|
out = send.dispatch_pending(conn, s, directory(ctx))
|
||
|
|
counts.update(out)
|
||
|
|
if out.get("failed") or out.get("retry"):
|
||
|
|
ctx.degrade(f"{out.get('failed', 0)} failed, {out.get('retry', 0)} waiting for the directory")
|
||
|
|
return counts
|
||
|
|
|
||
|
|
|
||
|
|
def _cadence(_: FeedSettings, __: datetime) -> int:
|
||
|
|
return EVERY_SECONDS
|
||
|
|
|
||
|
|
|
||
|
|
SPEC = JobSpec(name="notify-send", run=run, cadence=_cadence, pausable=False)
|