mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-14 03:52:26 +08:00
fix(channel-monitor-v2): default mode v1 and gentle adaptive backfill
Default channel_monitor_mode to v1 (opt-in V2) so upgrades keep active probes; existing explicit v2 rows are left alone via ON CONFLICT DO NOTHING plus migration checksum compatibility for already-applied 195. V2 first-enable backfill no longer compresses ticks to 5s or uses 24h chunks. Each tick does recent overlap plus at most one historical chunk with depth-based ceilings (2h/4h/6h), adaptive grow/shrink, and failure backoff. Error request_id dedup is bounded by a 90-minute lookback so ops_error_logs is not scanned for full history. Also align hide_throughput parse default with privacy-preserving public runtime (missing key → true).
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
# Channel Monitor V2 Safe Defaults & Gentle Backfill
|
||||
|
||||
**Date:** 2026-08-08
|
||||
**Status:** Approved for implementation
|
||||
**Branch:** `fix/channel-monitor-v2-ops-ui-blockers` (onto channel-monitor-v2)
|
||||
|
||||
## Problem
|
||||
|
||||
1. **H2** — Migration 195 and code defaults set `channel_monitor_mode=v2`, so every upgrade without an existing key auto-opts into passive V2, stops V1 probes, and may leave users on an empty V2 view.
|
||||
2. **M1** — First-enable bootstrap forces 5s ticks and ~24h `RecomputeRange` chunks until `now-30d`, hammering the primary DB.
|
||||
3. Error dedup SQL matches `request_id` without a `created_at` bound, scanning `ops_error_logs` history via `candidate_ids`.
|
||||
|
||||
## Decisions
|
||||
|
||||
| Topic | Decision |
|
||||
|-------|----------|
|
||||
| Default mode | **v1** (keep active probes). V2 is explicit opt-in. |
|
||||
| Existing `channel_monitor_mode=v2` rows | **Unchanged** (`ON CONFLICT DO NOTHING` / no force rewrite). |
|
||||
| Switch to v2 | V1 runner `fire()` and `RunCheck` require `ActiveProbesAllowed()` → probes stop. |
|
||||
| Backfill | Unified hard gates + adaptive soft gates (same rules, different observed load). |
|
||||
| Optional profile knob | **Not in this change** (YAGNI). |
|
||||
|
||||
## Mode defaults
|
||||
|
||||
- Migration `195_channel_monitor_mode.sql`: insert `'v1'` when key missing.
|
||||
- If 195 already applied with old checksum, add migration checksum compatibility (do not force rewrite applied DBs to v1).
|
||||
- Code: `defaultChannelMonitorMode = v1`; empty/invalid normalize → v1.
|
||||
- Frontend Settings form default and public feature flag fallback → v1 when missing/invalid.
|
||||
- Nil settings on V1 `RunCheck` path remains **fail-closed** (no probes) for test safety — independent of product default.
|
||||
|
||||
## Gentle backfill (low-resource phases)
|
||||
|
||||
### Hard gates (all servers)
|
||||
|
||||
- Tick interval = `refresh_interval` (60 or 300s). **No 5s bootstrap override.**
|
||||
- Each tick: (1) recent overlap (~10m), then (2) **at most one** historical chunk while product bootstrap incomplete / retention walk ongoing.
|
||||
- Single leader lock; single short transaction budget (~55s).
|
||||
- Chunk ceiling by depth (product phases 90m → 1d → 7d → 30d → silent 90d).
|
||||
|
||||
### Soft gates (adaptive)
|
||||
|
||||
- Initial historical chunk: **1h** (first seed still **2h** for 90m UI).
|
||||
- Min chunk: **15m**; max by depth: ≤1d → **2h**, ≤7d → **4h**, older → **6h**.
|
||||
- Success + fast: grow slowly (×1.5) up to depth max.
|
||||
- Failure/timeout: halve chunk; exponential backoff on wait (cap 10m).
|
||||
- Progressive UI: show whatever is covered; bootstrap banner vs 30d product window.
|
||||
|
||||
### Error dedup
|
||||
|
||||
- Bound the `request_id IN candidate_ids` branch with
|
||||
`created_at >= $1 - INTERVAL '90 minutes' AND created_at < $2`.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Force existing v2 → v1.
|
||||
- Separate backfill workers / read replicas.
|
||||
- Admin `backfill_profile` setting (may add later).
|
||||
Reference in New Issue
Block a user