mirror of
https://github.com/screentinker/screentinker.git
synced 2026-08-15 23:03:14 -06:00
docs(#146): fallout doc — auto-quarantine (P0) + band-aware downloads (P1.2)
Updated the item-B section for the in-memory time-limited auto-quarantine (no DB block, auto-clears) and the item-C section for band-aware downloads (serve freely when healthy, caps only under load). Both reference the new /api/status debug observability. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4547a677ab
commit
73e9992ffc
|
|
@ -26,22 +26,35 @@ watch, and the measured worst-case blocking cost per hot path.
|
||||||
(20) per `CONNECT_RATE_WINDOW_MS` (5min), keyed via the identity chain. Emits
|
(20) per `CONNECT_RATE_WINDOW_MS` (5min), keyed via the identity chain. Emits
|
||||||
`device:throttled {reason:'connect_rate'}` + disconnect. Sweep started in server.js.
|
`device:throttled {reason:'connect_rate'}` + disconnect. Sweep started in server.js.
|
||||||
- **Wider blast radius:** shares the `device:throttled` event with the #142 reconnect
|
- **Wider blast radius:** shares the `device:throttled` event with the #142 reconnect
|
||||||
throttle (clients already handle it). Auto-quarantine writes `devices.blocked=1` after
|
throttle (clients already handle it).
|
||||||
`CONNECT_RATE_QUARANTINE_TRIPS` (5) trips — a hard flapper self-blocks.
|
- **Auto-quarantine (P0 — behavior change):** after `CONNECT_RATE_QUARANTINE_TRIPS` (5)
|
||||||
- **Soak signals:** `[flap] refused …` and `[flap] auto-quarantined …` logs. A legit
|
trips a hard flapper is quarantined **IN-MEMORY for `CONNECT_RATE_QUARANTINE_MS`
|
||||||
device on a flaky network reconnecting >20×/5min would be refused — if false positives
|
(30min) and AUTO-CLEARS** — it is **NOT** a DB block. A stuck-then-recovered device
|
||||||
appear, raise `CONNECT_RATE_MAX`. The global anon bucket (cap 60) collectively caps
|
comes back on its own with no human action. `devices.blocked` is written **only** by an
|
||||||
truly-unidentifiable clients; real fleet devices always resolve to device_id/fingerprint.
|
operator (dashboard / direct SQLite). (Was: a permanent `blocked=1` auto-write — a
|
||||||
|
self-healing auto-action must not survive as a durable DB row.)
|
||||||
|
- **Soak signals:** `[flap] quarantined <id> for 30m after N trips` (logged once at the
|
||||||
|
START); repeat refusals are coalesced. Also visible on `/api/status` →
|
||||||
|
`debug.flap.{buckets,quarantined}`. A legit device on a flaky network reconnecting
|
||||||
|
>20×/5min would be refused — if false positives appear, raise `CONNECT_RATE_MAX`. The
|
||||||
|
global anon bucket (cap 60) collectively caps truly-unidentifiable clients; real fleet
|
||||||
|
devices always resolve to device_id/fingerprint.
|
||||||
|
|
||||||
### C — OTA under SNAT (`apk-cache.js`, `ota-download-guard.js`, server.js)
|
### C — OTA under SNAT (`apk-cache.js`, `ota-download-guard.js`, server.js)
|
||||||
- **Touches:** `/api/update/check` early-returns before any fs on no-offer; APK
|
- **Touches:** `/api/update/check` early-returns before any fs on no-offer; APK
|
||||||
metadata cached (60s refresh); `/download/apk` gains global concurrency + rate caps +
|
metadata cached (60s refresh); `/download/apk` gains BAND-AWARE global concurrency +
|
||||||
critical-band shed (**503 Retry-After**); IP-keyed log throttle replaced by a per-window
|
rate caps + critical-band shed (**503 Retry-After**); IP-keyed log throttle replaced by
|
||||||
served/shed aggregate.
|
a per-window served/shed aggregate.
|
||||||
- **Behavior change (watch):** downloads can now return **503** under flood/critical —
|
- **Band-aware downloads (P1.2 — behavior):** the concurrency/rate caps are a **load-time
|
||||||
|
backstop, not a healthy-state limiter**. Under `band=normal` downloads serve **FREELY**
|
||||||
|
(no cap) — a coordinated whole-fleet rollout is NOT staggered when the server is
|
||||||
|
healthy. The caps engage only under `elevated`; `critical` sheds (503). This fixes
|
||||||
|
rollout staggering (a shed 503 costs a client a full ~30-min re-check cycle).
|
||||||
|
- **Behavior change (watch):** downloads can return **503** only under elevated/critical —
|
||||||
clients retry per Retry-After. A freshly-swapped APK is picked up within the 60s cache
|
clients retry per Retry-After. A freshly-swapped APK is picked up within the 60s cache
|
||||||
refresh (slight delay by design). If legit downloads get shed, raise
|
refresh (slight delay by design). Observable on `/api/status` →
|
||||||
`OTA_DOWNLOAD_MAX_CONCURRENT` / `OTA_DOWNLOAD_MAX_PER_WINDOW`.
|
`debug.ota_download.{inFlight,servedThisWindow,shedThisWindow}`. If legit downloads get
|
||||||
|
shed under load, raise `OTA_DOWNLOAD_MAX_CONCURRENT` / `OTA_DOWNLOAD_MAX_PER_WINDOW`.
|
||||||
- **Soak signals:** `[ota] downloads last 60s: X served, Y shed` — a flood is now VISIBLE.
|
- **Soak signals:** `[ota] downloads last 60s: X served, Y shed` — a flood is now VISIBLE.
|
||||||
|
|
||||||
### D — operator block (`deviceSocket`, `routes/devices.js`, frontend)
|
### D — operator block (`deviceSocket`, `routes/devices.js`, frontend)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue