Zoha/agent-skills

À utiliser lors de la mise en cache de lectures GraphQL dans une application NestJS (code-first) — câbler un module de cache stale-while-revalidate (SWR) une fois, décider quoi mettre en cache et où le monter (service, champ, opération ou CDN), et le maintenir sans fuite. Se déclenche lorsque vous avez besoin de SWR, de déduplication à vol d'oiseau, d'invalidation par tag, de cadrage par utilisateur ou public, d'observabilité du cache, d'une ruée ou d'un échec bloquant à l'expiration du TTL, d'une fuite de données par clé partagée, d'un commutateur dev/ops désactivant entièrement le cache, ou d'une référence de configuration unique (module, placement des fichiers, stockage, TTL/GC des références, identité de l'appelant, exécution du décorateur, fail-open).

Qu'est-ce que agent-skills ?

Ce skill fournit un guide complet pour implémenter un cache stale-while-revalidate (SWR) dans une application NestJS GraphQL en mode code-first. Au lieu d'un simple mécanisme de mise en cache avec TTL, il propose une approche par intention, gérée via un module unique, des décorateurs, et un flux d'événements observable. Il couvre le montage au niveau service par défaut (avec possibilité d'escalade vers le champ, l'opération ou le transport), la sécurité contre les fuites de données entre utilisateurs, l'invalidation atomique par tags, et l'observabilité via des traces par requête et événements structurés. Les règles sont classées par priorité (de critique à moyenne) et chaque règle est détaillée dans un fichier séparé sous `rules/`. Le skill supporte les pilotes `async-cache-dedupe` (service level, agnostique au transport) et `mercurius-cache` (field level, SWR réel), et donne des directives claires pour configurer le module une fois, gérer les clés, les tags, les décorateurs, et le switch de désactivation pour le développement ou les incidents. Une section complète de sécurité (No-Leak Checklist) garantit que les lectures variantes par appelant sont marquées `perUser` pour éviter les fuites.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Zoha/agent-skills/tree/HEAD/skills/nestjs-graphql-swr-caching

Installed? Explore more Recherche et analyse de données skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Mise en cache GraphQL SWR (NestJS, code-first)

Vue d'ensemble

Mettez en cache par intention, pas par mécanisme. Une seule forme de politique, un seul flux d'événements observable, une seule trace par requête. Montez au niveau service par défaut ; passez au champ / opération / transport uniquement lorsque mesuré.

Trois vérités fondamentales qui guident chaque décision :

  1. Apollo Server n'a pas de stale-while-revalidate intégré. Son responseCachePlugin est limité au TTL et au niveau opération. Le vrai SWR vient de votre propre couche (async-cache-dedupe, ou mercurius-cache sur le pilote Mercurius) ou d'un CDN.
  2. La portée par défaut est public. Une entrée publique est partagée textuellement par tous les appelants, donc elle n'est correcte que lorsque le résultat est identique octet pour octet pour tous. Dès qu'une valeur varie selon l'appelant, elle doit être marquée perUser — sinon elle fuit.
  3. Les intercepteurs Nest ne encapsulent pas les méthodes de service, et le CacheInterceptor de @nestjs/cache-manager ne fonctionne pas avec GraphQL. Donc le décorateur au niveau service que vous voulez est un encapsuleur de méthode sur un moteur de déduplication — pas un interceptor framework.

Quand utiliser

  • NestJS GraphQL (code-first) où les résolveurs/services accèdent à une base de données ou à une API externe de manière répétée.
  • Vous devez éliminer les pics de latence et les ruées à l'expiration du TTL (vrai SWR).
  • Vous devez raisonner sur la sécurité du cache multi-utilisateurs / les fuites.
  • Vous avez besoin de visibilité sur les décisions hit / stale / miss.
  • Vous devez désactiver entièrement la mise en cache — dev, CI, ou incident — avec un seul indicateur (voir Section 1, setup-disable-switch).
  • Vous mettez en place la fonctionnalité de cache dans une application pour la première fois (voir Section 1).

Quand NE PAS utiliser :

  • Vous êtes déjà derrière un CDN faisant de la mise en cache de réponses pour le trafic public GET/APQ — commencez par là.
  • Chemins d'écriture/mutation, ou données par utilisateur sans réutilisation et avec une faible amplification de lecture (la mise en cache ajoute du risque pour peu de gain).

Le contrat des callbacks

key, @CacheTag et @InvalidateTags prennent des fonctions. Maîtrisez leurs arguments ou le cache échoue silencieusement et les tags ne se purgent pas silencieusement.

CallbackSignatureCe qu'est args
key(args, ctx) => unknown[] | Promise<unknown[]>la liste d'arguments de la méthode, dans l'ordre d'appel — args[0], jamais args.id
@CacheTag(result, args) => string[] | nullla même liste ; result est la valeur de retour de la méthode
@InvalidateTags(result, args) => string[]la même liste ; result est la valeur de retour de l'écriture
  • Positionnel, pas nommé. Pour getTitle(id: string), l'id est args[0].
  • Le résultat vient en premier pour les deux callbacks de tag. Les references du moteur brut sont (args, key, result) — ordre différent, premier argument différent (voir driver-async-cache-dedupe).
  • ctx (userId, tenantId, locale, plus gen) est dérivé de la requête et assemblé par buildCacheContext ; il est vide en dehors d'une requête, donc un job passe ce dont il a besoin comme argument.
  • Typage : les valeurs par défaut sont unknown[] / unknown — annotez le tuple (@Cacheable<[string]>, @CacheTag<[string]>) ou les corps des callbacks ne compileront pas.
  • Le niveau champ est différent : ici args est l'objet d'arguments nommés du résolveur et ctx est le contexte GraphQL (driver-mercurius-cache).

Contrat complet, le bundle de clé { a, k, u }, et les cas limites de sérialisation : policy-key-derivation. Implémentation d'exécution : setup-decorator-runtime.

Catégories de règles par priorité

PrioritéCatégorieImpactPréfixe
1Configuration UniqueCRITIQUEsetup-
2Politique de CacheCRITIQUEpolicy-
3Sécurité contre les FuitesCRITIQUEsafety-
4InvalidationHAUTEinvalidation-
5ObservabilitéMOYENNEobservability-
6PilotesMOYENNEdriver-

Référence rapide

1. Configuration Unique (CRITIQUE)

  • setup-decorator-runtime - Implémentez les Décorateurs comme Encapsuleurs de Méthode avec des Noms Stables
  • setup-disable-switch - Livrez un Commutateur de Configuration Qui Contourne le Cache au Niveau Service
  • setup-engine-choice - Utilisez un Moteur de Déduplication et Comptez le TTL en Secondes
  • setup-fail-open - Échouez Ouvertement et Ne Mettez Jamais les Erreurs en Cache
  • setup-file-placement - Placez la Fonctionnalité en Fonction de Qui l'Importe
  • setup-identity-context - Lisez l'Appelant depuis AsyncLocalStorage, Pas depuis Scope.REQUEST
  • setup-module-wiring - Câblez le Module de Cache une Fois avec forRootAsync
  • setup-storage-and-invalidation - Activez l'Invalidation et Définissez referencesTTL et GC

2. Politique de Cache (CRITIQUE)

  • policy-five-knobs - Connaissez les Cinq Boutons
  • policy-key-derivation - Dérivez la Clé Automatiquement, Jamais avec JSON.stringify
  • policy-mount-at-service - Montez au Niveau Service par Défaut
  • policy-one-writing-pattern - Les Décorateurs Sont le Seul Modèle d'Écriture
  • policy-service-escape-hatch - L'API de Service Est une Porte de Sortie, Pas un Deuxième Modèle

3. Sécurité contre les Fuites (CRITIQUE)

  • safety-default-public - La Portée par Défaut est Publique — Marquez les Lectures Qui Varient par Appelant comme perUser
  • safety-key-dimensions - La Portée Couvre Uniquement l'Utilisateur — Toute Autre Dimension Va dans la Clé
  • safety-no-leak-checklist - Exécutez la Checklist Sans Fuite sur Chaque Lecture en Cache

4. Invalidation (HAUTE)

  • invalidation-after-success - Invalidez Uniquement Après une Écriture Réussie
  • invalidation-atomic-purge - Purgez Atomiquement et Limitez la Cardinalité des Tags
  • invalidation-generation-prefix - Utilisez un Préfixe de Génération pour les Domaines Très Larges ou Grossiers
  • invalidation-tags-purge-only - Les Tags Sont Uniquement pour la Purge, Jamais pour la Recherche

5. Observabilité (MOYENNE)

  • observability-limits-of-events - Sachez Ce Que le Moteur Ne Peut Pas Reporter
  • observability-metrics-and-tests - Suivez les Métriques Qui Prouvent la Correction et Testez sur les Résultats
  • observability-per-request-trace - Affichez une Trace par Requête, Réservée au Développement sur GraphQL
  • observability-structured-events - Émettez des Événements de Cache Structurés, Pas des Chaînes de Log

6. Pilotes (MOYENNE)

  • driver-apollo-response-cache - Option C — Apollo responseCachePlugin (Niveau Opération, TTL Uniquement)
  • driver-apollo-vs-mercurius - Choisissez l'Option au Niveau Champ de Votre Pilote
  • driver-async-cache-dedupe - Option A — async-cache-dedupe (Niveau Service, Agnostique au Transport)
  • driver-cdn-transport - Option E — Transport / CDN SWR (Lectures Publiques Uniquement)
  • driver-envelop-response-cache - Option D — Envelop useResponseCache (Pas Natif à NestJS)
  • driver-federation-router - Fédération Uniquement — Mise en Cache des Réponses du Routeur Apollo
  • driver-mercurius-cache - Option B — mercurius-cache (Niveau Champ, Vrai SWR)
  • driver-version-pinning - Épinglez les Versions — Ce Domaine Évolue Rapidement

Comment utiliser

Commencez par la section Configuration Unique, puis lisez les règles de politique, sécurité et invalidation pour la décision à prendre. Les fichiers de règles se trouvent sous rules/ :

rules/setup-module-wiring.md
rules/_sections.md

Chaque fichier de règle contient :

  • Ce qu'est la règle et l'échec qu'elle prévient
  • Un exemple incorrect avec une explication
  • Un exemple correct avec une explication
  • Références

Document complet compilé

Pour le guide complet avec toutes les règles développées dans un seul document, voir AGENTS.md.

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

Skills associés