Aller au contenu
use-cases / a-ci-cache-thats-just-two-curl-commands / hero
PIPE · CI · OPTIMISATION DES COÛTS

Un cache CI qui n'est que deux commandes curl

Le premier job de votre pipeline tar node_modules et le pipe vers une URL Hoody. Vingt jobs en aval font curl sur la même URL et untar. Avec ?n=20, le producteur attend que les vingt workers se connectent, puis diffuse une fois — fanné à tous. Pas de bucket S3, pas d'action de cache, pas de facture d'egress.

Lire la doc pipe
use-cases / a-ci-cache-thats-just-two-curl-commands / flow

Toute la mécanique en deux lignes shell

Pas de bibliothèque cliente, pas de daemon, pas de SDK. Le producteur diffuse son tarball dans PUT /pipe/cache?n=20. Chaque worker le diffuse à la sortie de GET /pipe/cache?n=20. Le pipe ne retient les octets que tant qu'ils sont en vol — jamais sur disque.

PUT · PRODUCTEUREXÉCUTÉ UNE FOIS PAR BUILD

Produire le cache

$tar c node_modules|zstd|curl -T -
https://hoody.com/pipe/cache?n=20
# blocks until 20 receivers connect, then streams once

tar empaquette node_modules ; zstd compresse à la volée ; curl PUT les octets directement dans le chemin du pipe. Pas de fichier temporaire, pas d'étape upload-artifact, pas de credentials de bucket.

GET · CONSOMMATEUREXÉCUTÉ SUR CHAQUE WORKER

Consommer le cache

$curlhttps://hoody.com/pipe/cache?n=20
| zstd -d | tar x
# fan-out: every worker gets an identical copy

Chaque worker de test fait GET sur la même URL, décompresse, et untar dans son répertoire de travail. Les workers lents appliquent la backpressure au producteur mais ne bloquent pas les plus rapides.

TOUTE LA SURFACE DE COORDINATION?n=20

Un seul paramètre de requête. Producteur et consommateur s'accordent sur le même n. Le pipe retient l'upload jusqu'à ce qu'exactement ce nombre de récepteurs soit connecté, puis ouvre les vannes.

use-cases / a-ci-cache-thats-just-two-curl-commands / relief

Ce que vous arrêtez de payer

La mise en cache CI était une taxe : du stockage que vous écraserez demain, de l'egress chaque fois qu'un worker tire, du temps d'ingénierie sur les caprices de l'action de cache. Le pipe supprime les trois lignes de facture d'un coup.

Pas de bucket. Pas de facture d'egress.

Pas de bucket S3 parce qu'il n'y a pas de stockage. Le pipe oublie les octets à la seconde où le transfert se termine, donc rien à facturer par Go-mois ou par Go-sortant. Le cache cesse d'être une ligne de facture.

Pas de caprices d'action de cache

Pas de clés encodées en yaml, pas de scission save-cache / restore-cache, pas de débogage pour comprendre pourquoi un cache hit ne s'est pas produit sur le bon runner. Juste curl. Les deux mêmes lignes tournent sur GitHub Actions, BuildKite, Jenkins, votre laptop, ou un conteneur cron.

Pas de collisions de clés entre branches

Les branches utilisent simplement des chemins différents. /pipe/cache/main, /pipe/cache/feat-x, /pipe/cache/PR-742. Rien à invalider. Rien à évincer. Quand la branche meurt, son chemin n'est plus demandé et c'est tout le cycle de vie.

use-cases / a-ci-cache-thats-just-two-curl-commands / compare

La forme du coût, avant et après

Sur une charge réelle — node_modules autour de 800 Mo, vingt workers de test parallèles, une centaine de runs CI par jour — la majeure partie de la facture est de l'egress, pas du stockage.

S3 + GH ACTIONS CACHE

20× egress

Chacun des vingt workers tire le cache hors de S3. Vingt téléchargements d'un tarball de 800 Mo, c'est 16 Go d'egress par run CI. Le bucket lui-même est la partie facile — c'est l'egress qui s'accumule.

VS
HOODY PIPE · ?n=20

1× transfert

Le producteur diffuse les 800 Mo une fois. Le pipe fanne les octets aux vingt récepteurs en vol. Un seul transfert sur le câble, pas de multiplicateur par récepteur, pas de facture de stockage.

Les chiffres sont illustratifs pour un cache de monorepo Node typique. Les économies réelles dépendent de la taille du tarball, du fan-out de workers, et du prix d'egress que votre fournisseur facture hors de la région du cache. La forme — linéaire vs. constante en nombre de workers — est invariante.

use-cases / a-ci-cache-thats-just-two-curl-commands / punchline

La couche de cache, c'est HTTP. Ça l'a toujours été. On ne l'avait juste pas remarqué.

Les caches n'ont jamais été une question de stockage. Ils étaient une question d'amener les mêmes octets à N workers sans reconstruire. HTTP fait déjà ça — une fois qu'on laisse une URL faire fan-out vers un nombre connu de récepteurs. Le bucket était un contournement pour le fan-out qu'on n'avait pas.

OCTETS

Diffuser une fois, fan-out

Un PUT, n GET, octets identiques. La backpressure est par récepteur donc le worker lent ne ralentit pas les rapides.

PUT /pipe/cache?n=20
TEMPS

Vivant uniquement en vol

Le pipe retient les octets pour le transfert et les oublie quand il se termine. Rien à évincer, rien à passer en cycle de vie, rien à sauvegarder.

TTL ≤ 5 min · puis évincé
CHEMIN

Les branches sont des chemins

Chaque branche choisit son propre chemin. Pas d'espace de clés partagé, pas de collisions. Le chemin est la clé de cache et l'URL en même temps.

/pipe/cache/[branch]
Lire l'API pipe
use-cases / a-ci-cache-thats-just-two-curl-commands / replaces

Ce que cela remplace

La plupart des caches CI résolvent le même problème : amener le même tarball à N workers. Ils le font via stockage et egress. Le pipe le fait via le câble.

  • AWS S3 (bucket de cache + egress)Stockage que vous écraserez demain + egress par tirage
  • Cache GitHub ActionsClés yaml, caprices spécifiques aux runners, plafond de 10 Go
  • Caches BuildJet / Garnix CIPlus rapide, toujours par fournisseur, toujours au byte
  • Cache distant BazelExcellent si vous êtes tout-Bazel ; lourd sinon
  • Cache distant TurborepoHébergé par Vercel, en forme de monorepo, avec a priori
  • Cache satellite EarthlyEncore un daemon, encore un bucket, encore une facture
  • Caches rsync personnalisésUne box NFS et une clé SSH que tout le monde oublie de roter
use-cases / a-ci-cache-thats-just-two-curl-commands / cta

Deux commandes curl. Une URL. Vingt workers nourris.

Lire la doc pipe
use-cases / a-ci-cache-thats-just-two-curl-commands / related

Découvrez les autres