Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit de00b4517ad4bc7740cfe6a89369f5be197e1973
parent d41d745959f3dc2cd76a0222afe089cf7ed5f5c8
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Thu, 24 Sep 2026 19:29:58 -0400

plans: a full sweep of a large Rumble channel must be paced — the 44-day the-quartering-rumble sync failure, step 1 (operator) and step 2 (slice after release 4)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Diffstat:
Aplans/rumble-sweep-pacing.md | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+), 0 deletions(-)

diff --git a/plans/rumble-sweep-pacing.md b/plans/rumble-sweep-pacing.md @@ -0,0 +1,54 @@ +# Plan — a full sweep of a large Rumble channel must be paced, or it never completes + +**Found 2026-09-24** (operator: "job `01M3AVGZC5EZ9GCD04R9QW6NWX` keeps trying and failing a full +playlist fetch … no sync has happened in 44 days"). Facts verified on the live corpus and +`4130aca1`: + +- `the-quartering-rumble` (`https://rumble.com/c/TheQuartering`, 7,866 listed / 7,871 archived) + has `lastFullSweepAt: null`, so `isFullSweepDue` (`common/jobs/deepSync.ts:33-40`) is true on + every sync and `sync()` (`common/ytdlp/runYtdlp.ts:1333-1336`) always takes `syncFullSweep`, + never `syncPaged`. +- The sweep's one `--flat-playlist` spawn walks the channel's listing pages back to back; Rumble + answers **HTTP 429 on page 155** (job log line 173). The patched extractor + (`~/Projects/yt-dlp-patched`, the pipx editable install the editor runs) logs the error and + finishes with 3,846 entries, but yt-dlp exits 1; `enumeratePlaylistUrls` + (`runYtdlp.ts:352-361`) throws on any exit other than 0/101 and discards stdout. Nothing stamps + `lastSyncedAt` (2026-08-11) or `lastFullSweepAt`; the next sync is a sweep again. Three + attempts on 2026-09-24 (16:05, 20:20, 23:20 UTC), identical. +- **Tolerating exit 1 is the wrong fix.** The 3,846-entry listing is half the channel. The shrink + guard (`common/controller/acceptListing.ts`, `fullSweepShrinkGuardPercent` 10 %, floor 25) + would reject it once, and a second identical partial read — the same 429 at the same page — + would *confirm* a mass deletion and truncate the stored `playlist`. The throw is what prevents + that today. + +**Step 1, applied by the operator 2026-09-24 (no code):** `fullSweepIntervalMinutes: 0` on the +channel, through `pnpm ops channel-config` (the `patchChannelConfig` writer), so every sync is +the paged walk (`--lazy-playlist -I start:end`, a few newest pages, stops at the first archived +hit) and new videos arrive on the next cadence. Cost until step 2: no maybe-missing detection for +this channel. + +**Step 2, a small slice after one-core Phase 3 release 4** (it edits `runYtdlp.ts`, in slice W's +file set, so it lands after W merges): + +1. **Pace the enumeration for Rumble.** Add `--sleep-requests <s>` to the sweep spawn when the + channel's platform is Rumble (a per-platform table beside `downloadQueueKey`, not a per-channel + knob; the value is an operator setting under `syncScheduler`, default ~1 s). Pacing applies to + every page request, which is exactly where the 429 comes from. +2. **A sweep that ends on a 429 is "incomplete", not "failed" and not "a listing".** Detect the + 429 in stderr (or the non-zero exit with a partial stdout) and record it on the roster as an + incomplete observation: it must not enter `acceptListing` as a reading (so two identical + partial walks can never confirm a deletion), and it must not stamp `lastFullSweepAt`. Log one + line naming the page it reached. +3. **Do not re-sweep on a cooldown.** After an incomplete sweep, the next syncs are paged walks + until a per-platform cooldown (reuse the rate-limit cooldown the download runner already keeps + for YouTube 429s, keyed `platform:rumble`) has elapsed — today a failed sweep is retried at + every cadence, each one another 155-page walk that keeps the limit tripped. +4. **Tests:** unit for the incomplete verdict (partial + 429 → no `acceptListing` call, no + stamp), the cooldown gate, and the pacing arg on a Rumble channel only; the `runYtdlp` e2e + fixtures with a fake yt-dlp that exits 1 after N pages. +5. **Rollout:** after the slice is live, restore the channel's `fullSweepIntervalMinutes` (delete + the override) and watch one paced sweep complete; the first complete listing after 44 days may + legitimately shrink — the two-observation guard handles that as designed. + +Out of scope: tolerating exit 1 generally; changing the shrink guard; anything in the patched +extractor (the pagination fix is in and working; the 429 is Rumble's rate limit, not a bug).