← EXTRACT

Project thumbs — timing & unstable loading

Large project grids (hundreds of crews × many timecode columns) can stampede the browser and the CREWS static server if every thumbnail loads at once. CREWS throttles hydrate from the client; knobs live in options.json.

Defaults: 3 parallel fetches · pause 120 ms every 4 completed loads. Tune slower if the UI freezes; faster only on a quiet host.

1. Timing options

Stored in options.json at the CREWS app root (not uploaded by FTPS). Also exposed via GET /api/options and mergeable with POST /api/options. The viewer reads them on boot (frames_ui/thumb_hydrate.jsloadHydrateConfig / pumpThumbQueue).

Option Default Range Meaning
thumb_hydrate_concurrency 3 1–16 Max parallel thumb network fetches
thumb_hydrate_batch_size 4 1–64 After every N completed loads, insert a pause
thumb_hydrate_pause_ms 120 0–2000 Pause length in ms (0 = no batch pause)
thumb_hydrate_cache_concurrency 6 1–32 Parallel Cache API / HTTP-cache probes before network

2. How to change them

Inspect current values:

curl -sS "https://crews.championship.technology/api/options" | python3 -m json.tool

Slow the client down (example — gentler on a busy host):

curl -sS -X POST "https://crews.championship.technology/api/options" \
  -H "Content-Type: application/json" \
  -d '{"thumb_hydrate_concurrency":2,"thumb_hydrate_batch_size":3,"thumb_hydrate_pause_ms":200}'

Or edit options.json on the host:

{
  "thumb_hydrate_concurrency": 2,
  "thumb_hydrate_batch_size": 3,
  "thumb_hydrate_pause_ms": 200,
  "thumb_hydrate_cache_concurrency": 4
}

After changing options, hard-refresh the shell and reopen the project tab so the iframe reloads hydrate config. Python defaults live in server.pyDEFAULT_OPTIONS (restart CREWS after deploying Python changes that add/coerce these keys).

3. Troubleshooting unstable loading

Symptoms we chased and how they map to fixes:

Symptom Likely cause What to do
UI freezes / server hangs when opening a large tab Too many concurrent image requests (browser + Python static server) Lower thumb_hydrate_concurrency (e.g. 2) and raise thumb_hydrate_pause_ms (e.g. 200–300)
Thumbs stay blank / placeholders forever Hydrate never kicked (iframe visibility race) or requests starved Hard-refresh; click the tab again; confirm frames_ui/thumb_hydrate.js loads (Network). Shell injects it into baked viewers.
Row height jumps; empty cells look square Unloaded / absent cells used square aspect in table layout Placeholders use explicit height calc(var(--thumb-size) / 2.4) — hard-refresh so frames_ui/head.html / hydrate CSS apply
Broken image icons in empty timecode columns Missing frames still emitted as <img> Re-extract (or rebuild viewer) so empty cells use .frame-absent
Fast on second open, slow first time Cold hydrate vs warm HTTP / Cache API path Normal. First open fills cache; later opens reuse it under the same throttle.
Slideshow waterfall + thumbs both fighting the host Waterfall advances one row; hydrate still fills the grid Stop waterfall (play icon / Play all) while cold-loading, or slow hydrate further
Options POST ignored / keys missing Process still on old server.py, or typo in key name Restart CREWS after deploying Python; confirm keys in GET /api/options

4. Quick triage order

  1. Hard-refresh shell → reopen project tab
  2. GET /api/options → confirm thumb_* values
  3. Browser Network: many parallel .jpg? → lower concurrency / raise pause
  4. Host CPU / load while tab open — if pegged, slow hydrate more
  5. Verify frames_ui/thumb_hydrate.js and slide_waterfall.js return 200

5. Where it’s implemented

crw >x< crush · viewer docs · thumb hydrate timing