Édition #1 · 29 juillet 2026
Fiabilité, file d’attente & clips qui restent
Fin juillet, on a reconstruit le cœur du pipeline clips. Moins de jobs fantômes, plus de capacité, une facturation plus juste — et une UI qui ne clignote plus pour rien.
En une phrase
Upcut peut maintenant enchaîner beaucoup plus de générations en parallèle sans perdre tes clips à la fin — ni les marquer en erreur alors qu’ils sont prêts.
01 — Scale
Plusieurs machines, une seule file
Avant, chaque serveur Upcut gardait les jobs clips dans sa propre mémoire. Un redémarrage, un second serveur, et le job pouvait « disparaître » : l’interface affichait une erreur alors que le travail n’était peut‑être pas perdu — juste invisible.
On a basculé sur une file partagée dans Supabase. Tous les workers Railway piochent le prochain job dans le même ordre (FIFO), un à la fois par machine. Résultat : on peut monter à plusieurs replicas sans se marcher dessus.
- 1 job complet par replica (download + Whisper + rendu) pour ne pas faire exploser ffmpeg
- Jusqu’à 3 clips par vidéo en production
- Estimation de place dans la file côté interface
→ La file se vide, même quand beaucoup de créateurs lancent des jobs en même temps.
02 — Bug critique
Les clips « terminés » qui apparaissaient en erreur
Le symptôme le plus pénible : le worker avait bel et bien fini (clips uploadés), mais ton projet affichait STALE_JOB_TIMEOUT — zéro clip visible.
Un nettoyeur automatique (reaper) croyait que le job était mort parce qu’il attendait trop longtemps dans la file. Dès que le backend passait à « done », le reaper marquait encore l’UI en erreur… sans recopier les clips.
- Dès qu’un job finit côté worker, on synchronise immédiatement la fiche projet
- Si le backend est done avec des clips, on promote — on ne STALE jamais
- Un trigger Postgres garantit le miroir même si un worker crash pile au mauvais moment
- L’API projet soigne aussi les anciens faux STALE au prochain chargement
→ On a restauré une quinzaine de projets zombies en prod. Depuis : 0 nouveau cas STALE de ce type.
03 — Race technique
Done à l’écran, « 80 % » côté serveur
Autre fantôme : l’UI montrait tes clips (done), pendant que le serveur repassait à « processing » bloqué à 80 %.
Cause : une course. Le dernier update de progression (80 % = tous les clips rendus) partait en parallèle et pouvait écraser le statut « done » écrit une fraction de seconde plus tard — en vidant au passage la liste des clips côté base.
- Les écritures d’état sont maintenant sérialisées par job
- Interdiction de downgrader un job terminé vers « en cours »
- setDone attend bien la persistance avant de lâcher la main
- Trigger SQL : même attaque simulée en prod → le done tient
→ Plus de projets « done » qui repartent magiquement à 80 %.
04 — File longue
Ne plus tuer les jobs qui attendent tranquillement
Avec une vraie file, attendre 40 minutes avant d’être pris en charge peut être normal (beaucoup de monde, jobs longs).
L’ancien reaper se basait seulement sur la date de création : il tuait des jobs encore pending. On a aussi corrigé un reclaim trop agressif qui volait des jobs Whisper/ffmpeg encore vivants.
- On ne touche pas aux jobs dont le backend est encore pending ou processing
- Reclaim uniquement si plus de heartbeat depuis assez longtemps
→ Attendre dans la file ≠ erreur. Seuls les vrais zombies (worker mort) sont recyclés.
05 — Interface
Moins de flicker pendant le polling
Quand le backend mettait trop longtemps à répondre, l’UI passait parfois en erreur puis revenait — un flash désagréable sur la page projet.
Désormais, un timeout de poll est un soft-fail : on garde le dernier statut connu au lieu de faire croire que le job a planté.
→ La page projet respire : plus de yo-yo loading → erreur → loading.
06 — Argent
Stripe + crédits qui ne double-comptent pas
Le checkout Creator / Studio passe par Stripe (plus Lemon Squeezy sur le parcours principal).
La facturation des minutes de clips est retry-safe : même si tu recharges la page pile au moment où le job passe à done, on ne te re-débitera pas.
→ Upgrade clair depuis les tarifs, crédits cohérents même en cas de retry réseau.
07 — Qualité clips
Whisper, uploads, split & rendu
Dans le même sprint : découpage Whisper plus robuste, hooks plus propres sur les uploads, moins de faux positifs split sur les monologues, et un réglage ffmpeg pour éviter les plantages mémoire sur Railway Hobby.
Les uploads peuvent aussi court-circuiter la détection de « moments viraux » quand tu sais déjà ce que tu veux couper — moins d’attente inutile.
→ Moins d’échecs silencieux au rendu, meilleurs découpages sur podcasts et longs formats.
Chronologie express
- 28/07File partagée multi-replicas + capacité ×N
- 28/07Billing crédits idempotent + Stripe au premier plan
- 29/07Reaper STALE corrigé — plus de jobs morts à tort
- 29/07Poll UI soft-fail — plus de flicker
- 29/07Sync forcée done → projet + heal des zombies
- 29/07Race 80 % neutralisée (code + trigger SQL)
Pour les curieux
Sous le capot, sans jargon inutile
Tables clés : clip_jobs (ce que tu vois) et clip_backend_jobs (ce que les workers exécutent). Elles doivent rester alignées.
Claim SQL FIFO avec verrouillage coopératif, heartbeats, triggers Postgres pour le miroir done et l’interdiction de downgrade.
Détail technique interne : docs/MODIFS_28-29_JUILLET_2026.md dans le repo.
Prêt à générer ?
Colle un lien YouTube ou Twitch — Gaming, talk ou podcast, les clips suivent ce que tu as lancé.