Operational snapshot (2026-06-17, point-in-time) of why pmv2 autotrade buy/sell alerts arrive 20–38 min behind the source trade, plus a NEW finding: the scheduled-run job intermittently hits its 15-min systemd start timeout and is killed, dropping a whole cycle’s later-pipeline alerts. Facts gathered from journalctl on the polymarket-infra VM; extends the REST-poll lag already flagged as a strategic deferral in autotrade-3c2-complete-handoff.
Point-in-time snapshot + verification routing
All figures are a 2026-06-17 observation from
journalctl/manifest onpolymarket-infra. Run durations and the timeout counts are a moving target — re-verify before acting. Live VM facts here were gathered via direct read-only SSH; per operator policy, VM ops now route through@deployon babylon — do NOT SSH the VM directly to re-check.
Production scheduler (current manifest)
Source: terraform manifest ~/levandor/terraform/deploys/apps.yml. This is the current (2026-06-17) topology and supersedes the older service table in polymarket-fetch-deploy (that note is the 2026-05-27 deploy record — wallet-monitor was still present then; it is now decommissioned).
| Unit | Kind | State | Schedule / restart | Notes |
|---|---|---|---|---|
polymarket-fetch-scheduled-run | job | present | schedule: "*:0/30" (every 30 min) | cmd scheduled-run --dedup-seconds 300 --gap-warn-seconds 3600; image …/apps/polymarket-fetch:latest |
polymarket-fetch-bot | service | present | restart: always | Telegram bot |
polymarket-fetch-wallet-monitor | — | absent | decommissioned | was present at 2026-05-27 deploy |
pm-arb-validate | — | absent | decommissioned | |
weather-bet-run | service | present | continuous | |
weather-bet-resolve | job | present | daily 14:00 |
systemd unit type: Type=oneshot, TimeoutStartUSec=15min, RuntimeMaxUSec=infinity. The 15-min start timeout is the operative cap — a run that exceeds it is terminated mid-pipeline.
NEW finding — intermittent run timeouts
3 of 48 runs in 24h were KILLED at the 15-min start timeout
Over the last ~24h: 45 runs “Deactivated successfully” (normal) and 3 runs hit the
TimeoutStartUSec=15mincap → systemd logged “start operation timed out. Terminating”,status=130/SIGINTand killed the process mid-run.Timeouts at (UTC): Jun 16 20:00, Jun 17 08:30, Jun 17 09:00. The last two were consecutive (08:30 then 09:00) — a possible worsening trend; worth watching for a third in a row.
A killed run loses every later-pipeline stage that hadn’t run yet that cycle — exit/sell alerts especially, since they run after positions. Fire-and-forget
tokio::spawnTelegram sends in flight near the kill are also lost.
Typical successful run = ~6–9 min (e.g. 08:00:13 → 08:08:01). So most runs finish well inside the cap; the timeouts are intermittent, not deterministic on data size.
Where the autotrade step sits in a run
The autotrade entry step runs ~7.5–8 min into each run — e.g. a BUY dry-run alert logged at 09:08:08 for a run that started 09:00:29. That late position is structural: execute_pipeline (scheduled_run.rs) runs run_pmv2_collect (50 traders × up to 20 trade pages) → resolutions sync → leaderboard before run_pmv2_positions (which is where autotrade ingests). Exit/sell alerts run after positions, i.e. even later in the run — which is exactly the slice a 15-min kill tends to drop.
Latency decomposition — why alerts are so late
For Agents — autotrade alert latency budget
Net: buy alerts typically arrive ~20–25 min behind the source trade, up to ~38 min, occasionally a whole cycle skipped. Telegram delivery itself is sub-second and is NOT the cause. The latency is three stacked components:
- Detection lag (REST poll on the 30-min timer) → mean ~15 min, up to 30 min. The
first_mover_coretrigger is REST-polled, not WSS. (Same root deferral as autotrade-3c2-complete-handoff / autotrade-sources-signal-emitter.)- In-run delay (~8 min) before the autotrade step executes — collect + resolutions + leaderboard run first in
execute_pipeline.- Intermittent whole-cycle loss — when a run is killed at 15 min, later stages (exit/sell alerts run after positions) are dropped for that cycle, and in-flight fire-and-forget Telegram sends near the kill are lost.
Autotrade is live in DRY-RUN in prod (mode=off / dry): observed 🧪 DRY-RUN — would BUY … notifications with bet links and via 0x… · 0x… attribution lines. So these alerts are the dry-run rehearsal stream, not live fills.
Candidate causes of the 15-min timeout (hypotheses — NOT confirmed)
Most likely: an occasional silently-hanging proxied HTTP call
The timeouts are intermittent rather than data-size-deterministic, which points at a hang, not slow bulk work. Known gap: a proxied
reqwestclient withoutconnect_timeoutcan hang silently (zero warnings) — see thereference_proxied-client-connect-timeoutmemory. That failure mode matches an occasional whole-run stall.Where the hang is: the
09:00run got past the autotrade step (BUY dry-run logged09:08) and was killed at09:15→ the stall is somewhere in the later pipeline stages: trending alert / exit alert / category sync / paper copies / settlement / self sync / resolution check / overlap watcher / self-trade-changes.
Secondary contributor: the growing EXITED-events backlog. Observed slow query (exit-events cursor read):
SELECT proxy_wallet, condition_id, outcome_index, event_slug, slug, detected_ts
FROM pmv2_position_events
WHERE kind = 'EXITED' AND ($1::timestamptz IS NULL OR detected_ts > $1)
ORDER BY detected_ts ASCreturned 37,741 rows in 2.87s — a large/growing backlog suggesting the cursor may be near-NULL / not advancing. On its own 2.87s doesn’t blow a 15-min budget, but it compounds and will worsen as the backlog grows.
Suggested follow-ups (not yet done)
- Add
connect_timeout(not justtimeout) to every proxiedreqwestclient in the later pipeline stages; bound fan-out with per-itemtokio::timeout. (The known silent-hang fix.) - Watch for a 3rd consecutive timeout — 08:30 + 09:00 were back-to-back.
- Investigate why the
autotrade_exitscursor isn’t advancing past a 37k-rowEXITEDbacklog (cursor near-NULL). - Strategic: a real-time on-chain
OrderFilledWSS trigger removes component (1) of the latency budget and is already recommended before scaling past tiny caps (autotrade-3c2-complete-handoff). - Re-verify all of the above via
@deployon babylon, not direct SSH.
Related
- autotrade-3c2-complete-handoff — operator handoff; already flags the REST-poll lag (~30 min / mean ~15 min) as a strategic deferral; this note extends it with in-run delay + timeout-kill cycle loss
- autotrade-sources-signal-emitter — the
first_mover_coreREST-polled trigger (component 1 of the latency budget) - autotrade-exit-cursor-404-wedge-fix — the exit cursor +
process_exit_event/drain_pending_exitspaths (later-pipeline stages implicated in the hang) - autotrade-repo-exit-helpers —
autotrade_exit_eventsquery + cursor helpers (the 37k-row slow query) - pmv2-exit-alerts — exit-alert step that runs after positions (dropped by a 15-min kill)
- polymarket-fetch-deploy — 2026-05-27 deploy record (older service table; superseded here for current topology)
- lag-probe — separate read-only book-lag capture workload
- observability-flow — infra-side observability (how to inspect the VM via the sanctioned path)
- levandor-infra — infra overview; VM ops route through
@deployon babylon