Add two-stage run verification and 24-hour Activity filter
All checks were successful
Deploy / deploy (push) Successful in 57s

Status now reads "Sent" when the confirmation click lands, since that
only means MassPrice accepted the run request, not that it finished —
their own processing is async and takes anywhere from ~1 to ~22
minutes in observed practice. A new "Complete" column tracks that
separately: run_rule() captures a watermark (the target rule's current
top data-activitylogid on /Activity/List, not the displayed timestamp
string, to sidestep fragile date/timezone parsing) before submitting,
and scheduler.py schedules a one-off verify_run() job
VERIFY_DELAY_MINUTES later to check whether a new "Complete" entry
appeared past that watermark.

rebuild_jobs() now only clears recurring "rule-*" jobs, not the one-off
"verify-*" jobs, so editing a schedule can't cancel a verification
that's already in flight for an earlier run.

Also scopes the Activity page to the last 24 hours per request.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H6TgffxTvYhqxykAbVQg2v
This commit is contained in:
Barely Removable 2026-08-31 21:49:45 -07:00
parent 988db5d5c4
commit 8b58dadc5a
8 changed files with 249 additions and 20 deletions

View file

@ -39,6 +39,12 @@ tool is confirmed working, so there's exactly one thing triggering runs.
`workers = 1` for this reason — a second worker would instantiate a
second scheduler and duplicate every run. Fine for a low-traffic
single-user tool.
- Also schedules **one-off** `verify-<entry_id>` jobs (APScheduler
`date` trigger, not recurring) `VERIFY_DELAY_MINUTES` after a run is
confirmed sent — see `automation.verify_run()` below.
`rebuild_jobs()` only ever removes `rule-*` jobs, deliberately, so
editing a schedule mid-flight can't cancel a verification that's
already in progress for an earlier run.
- **`automation.py`** — all Playwright logic. `list_rules()` scrapes
`https://massprice.tcgplayer.com/Rule/List` for the live rule
id/name pairs (cached to `rules_cache.json`, refreshed via the
@ -63,6 +69,25 @@ tool is confirmed working, so there's exactly one thing triggering runs.
and its request (`POST /Rule/Run`, confirmed by live network capture)
is almost certainly anti-forgery-token protected, so automation
drives the real page rather than replaying a raw HTTP POST.
- **Run verification** — confirming the modal only means MassPrice
*accepted* the run; it still processes asynchronously on their side
(queued → running → Complete), taking anywhere from ~1 to ~22 minutes
in observed practice. `run_rule()` captures a "watermark" — the
`data-activitylogid` of that rule's current top entry on
`/Activity/List` (a stable, monotonically increasing ID; deliberately
*not* parsing the displayed timestamp string, which would need
fragile date/timezone handling) — **before** submitting, logs the run
as `status: "sent"` with `verification: "pending"`, and the caller in
`scheduler.py` schedules `verify_run()` to run `VERIFY_DELAY_MINUTES`
later. `verify_run()` re-checks `/Activity/List`: a new entry (higher
`data-activitylogid` than the watermark) whose status text contains
"Complete" → `verification: "complete"`; otherwise
`verification: "not_confirmed"` (which can mean "still processing",
not necessarily "failed" — the delay is a reasonable middle ground,
not a guarantee it's had enough time). `_find_latest_activity()` is
shared by the watermark capture and the follow-up check. The Activity
page's "Complete" column surfaces this; "Status" shows whether the
click itself was sent, independent of whether MassPrice finished it.
- **Session persistence** — a Playwright `storage_state` (cookies +
localStorage) is saved to `/data/auth_state.json` and reused across
runs: scheduled runs never touch the login form at all, they just load