fix(activity): runs keep their true outcome and spend, the page reaches every kept row, a closing dialog leaves the server log alone
Backend - A run's outcome write sits outside the job's own try: a database blip after a run that succeeded no longer records it as failed (the row waits for the next start's sweep). - An interrupted run keeps what it spent (the sweep sums its quota rows, as finish does). - The Scheduler's ad-hoc row says running while any backfill runs, not only the newest. - recent_runs reads each job's last runs off its index instead of ranking the whole table. - An interval change is stored with its audit row in one transaction, then rescheduled. - One API instance per database is the stated contract (.env.example, jobruns). - Turning full history on for a channel already complete records no run. - Migration 0109 round-trips interrupted and ad-hoc runs; the run words' DB CHECKs are test-held to the enums; the account filter is one helper for the four activity reads. - An audit row says how many of its request's log lines are still kept. Frontend - An "All" period reaches every row still kept (runs and admin actions outlive 90 days). - Back/Forward is followed in place by the server log: a closing dialog no longer turns Live off; a pivot still opens a fresh log. - Runs moved over from the audit log read their one-liner in the reader's language. - Filter choices or accounts that failed to load say so beside the filters, with a retry. - An old server-log link keeps its account, text and range; a remembered retired page opens its tab. - A request whose lines are gone says so instead of linking to an empty list. - The log lines and the history rows share one row frame, and the server log one list frame with the other tabs; an empty list is announced; each day's quota is readable.
This commit is contained in:
@@ -12,7 +12,8 @@ log writer runs behind the event).
|
||||
|
||||
Runs are not admin actions, so the audit log stops carrying them: the existing `job_run` audit rows
|
||||
MOVE into `job_runs` (start = end = when the row was written, the only time it kept), and leave the
|
||||
audit log. The downgrade moves every run back into the audit log as such a row, then drops the table.
|
||||
audit log. The downgrade moves every run back into the audit log as such a row (one still running as
|
||||
interrupted, a run's trigger and target in its `after`), then drops the table.
|
||||
"""
|
||||
|
||||
import sqlalchemy as sa
|
||||
@@ -70,15 +71,19 @@ def upgrade() -> None:
|
||||
postgresql_where=sa.text("run_id IS NOT NULL"),
|
||||
)
|
||||
|
||||
# The audit trail's runs move over. A status the run table does not know (none was ever
|
||||
# written) would fail the CHECK, so the move is limited to the three the scheduler wrote.
|
||||
# The audit trail's runs move over: the three statuses the scheduler wrote, and `interrupted`,
|
||||
# which a downgrade writes back (as it does a run's `trigger` and `target`, which the audit row
|
||||
# has no column for), so a rollback and a redeploy keep every run. A status the run table does
|
||||
# not know would fail the CHECK.
|
||||
op.execute(
|
||||
"""
|
||||
INSERT INTO job_runs (job, trigger, actor_id, status, started_at, finished_at, summary,
|
||||
result, error, failure)
|
||||
INSERT INTO job_runs (job, trigger, actor_id, target, status, started_at, finished_at,
|
||||
summary, result, error, failure)
|
||||
SELECT target_id,
|
||||
CASE WHEN actor_id IS NULL THEN 'scheduled' ELSE 'manual' END,
|
||||
coalesce(after::jsonb ->> 'trigger',
|
||||
CASE WHEN actor_id IS NULL THEN 'scheduled' ELSE 'manual' END),
|
||||
actor_id,
|
||||
after::jsonb ->> 'target',
|
||||
after::jsonb ->> 'status',
|
||||
created_at,
|
||||
created_at,
|
||||
@@ -89,7 +94,7 @@ def upgrade() -> None:
|
||||
FROM audit_log
|
||||
WHERE action = 'job_run'
|
||||
AND target_id IS NOT NULL
|
||||
AND after::jsonb ->> 'status' IN ('ok', 'error', 'skipped')
|
||||
AND after::jsonb ->> 'status' IN ('ok', 'error', 'skipped', 'interrupted')
|
||||
ORDER BY id
|
||||
"""
|
||||
)
|
||||
@@ -98,12 +103,15 @@ def upgrade() -> None:
|
||||
DELETE FROM audit_log
|
||||
WHERE action = 'job_run'
|
||||
AND target_id IS NOT NULL
|
||||
AND after::jsonb ->> 'status' IN ('ok', 'error', 'skipped')
|
||||
AND after::jsonb ->> 'status' IN ('ok', 'error', 'skipped', 'interrupted')
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# A run still `running` is one the rollback stopped: it goes back as interrupted. Its trigger and
|
||||
# target ride in `after` when the audit row's own columns cannot say them (an ad-hoc run of one
|
||||
# channel), so the upgrade restores them.
|
||||
op.execute(
|
||||
"""
|
||||
INSERT INTO audit_log (actor_id, action, target_type, target_id, summary, after, created_at)
|
||||
@@ -111,21 +119,26 @@ def downgrade() -> None:
|
||||
'job_run',
|
||||
'job',
|
||||
job,
|
||||
left(job || ': ' || status
|
||||
|| coalesce(' — ' || CASE WHEN status = 'error' THEN error ELSE summary END, ''),
|
||||
left(job || ': ' || st
|
||||
|| coalesce(' — ' || CASE WHEN st = 'error' THEN error ELSE summary END, ''),
|
||||
255),
|
||||
(jsonb_build_object(
|
||||
'status', status,
|
||||
'summary', CASE WHEN status = 'error' THEN error ELSE summary END)
|
||||
'status', st,
|
||||
'summary', CASE WHEN st = 'error' THEN error ELSE summary END)
|
||||
|| CASE
|
||||
WHEN status = 'error' AND failure IS NOT NULL
|
||||
WHEN st = 'error' AND failure IS NOT NULL
|
||||
THEN jsonb_build_object('result', failure)
|
||||
WHEN status <> 'error' AND result IS NOT NULL
|
||||
WHEN st <> 'error' AND result IS NOT NULL
|
||||
THEN jsonb_build_object('result', result)
|
||||
ELSE '{}'::jsonb
|
||||
END)::json,
|
||||
END
|
||||
|| CASE WHEN trigger = 'ad_hoc'
|
||||
THEN jsonb_build_object('trigger', trigger) ELSE '{}'::jsonb END
|
||||
|| CASE WHEN target IS NOT NULL
|
||||
THEN jsonb_build_object('target', target) ELSE '{}'::jsonb END)::json,
|
||||
coalesce(finished_at, started_at)
|
||||
FROM job_runs
|
||||
FROM (SELECT *, CASE WHEN status = 'running' THEN 'interrupted' ELSE status END AS st
|
||||
FROM job_runs) AS r
|
||||
ORDER BY id
|
||||
"""
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user