Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-22 09:42:01

0001 """Helpers over the epicprod action stream for alarm detectors.
0002 
0003 The action stream is the structured record of epicprod actions in
0004 ``swf_applog`` (``app_name='epicprod'``, structured fields in ``extra_data``)
0005 — see swf-monitor docs/EPICPROD_ACTION_STREAM.md. Detectors reach it through
0006 ``client.db_conn``, the engine's psycopg connection attached in run.py.
0007 """
0008 from __future__ import annotations
0009 
0010 
0011 def latest_action(conn, action: str, *, outcome: str | None = None):
0012     """Newest action record as a dict (timestamp, extra_data), or None."""
0013     sql = (
0014         "SELECT timestamp, extra_data FROM swf_applog "
0015         "WHERE app_name = 'epicprod' AND extra_data->>'action' = %s"
0016     )
0017     params = [action]
0018     if outcome is not None:
0019         sql += " AND extra_data->>'outcome' = %s"
0020         params.append(outcome)
0021     sql += " ORDER BY id DESC LIMIT 1"
0022     with conn.cursor() as cur:
0023         cur.execute(sql, params)
0024         return cur.fetchone()
0025 
0026 
0027 def action_count(conn, action: str, *, minutes: int) -> int:
0028     """Count of action records in the trailing window."""
0029     with conn.cursor() as cur:
0030         cur.execute(
0031             "SELECT count(*) AS n FROM swf_applog "
0032             "WHERE app_name = 'epicprod' AND extra_data->>'action' = %s "
0033             "AND timestamp >= now() - make_interval(mins => %s)",
0034             [action, minutes])
0035         row = cur.fetchone()
0036         return int(row["n"]) if row else 0