Leçon 5 / 20

Définir le contrat d’une tâche de facture

15 min Node.js — production, files d’attente et sécurité Gratuit

Objectif : Définir un contrat minimal, versionné et validable pour demander la génération différée d’une facture à partir d’une commande.

Une demande de facture ne doit pas transporter toute la commande ni dépendre de l’objet reçu par une route Express. Si son contenu est incomplet ou change sans règle, le traitement différé ne peut pas retrouver de façon fiable les données nécessaires.

Vous allez définir un message petit, explicite et vérifiable, qui indique quelle commande traiter et selon quel format. La leçon précédente a distingué les traitements immédiats des traitements différés ; ici, vous fixez les données échangées pour la génération différée d’une facture.

Un message de tâche minimal

Un message de tâche est la représentation des informations nécessaires pour demander une opération différée. Pour générer une facture, le message doit identifier l’opération et la commande concernée : il ne contient donc ici que type, version et commandeId. L’identifiant de commande est l’identifiant métier : il permet au traitement de retrouver la commande dans la source de données faisant autorité.

Ne recopiez pas dans le message le prix, l’adresse ou les lignes de commande si le traitement peut les relire à partir de commandeId. Une copie risque de devenir périmée entre la demande et la génération. Le worker devra vérifier que la commande existe et appliquer les règles métier à partir de ses données actuelles ; ces étapes seront détaillées dans les leçons consacrées au worker et à la résistance aux échecs.

Versionner le contrat

Le champ version désigne la forme du message, et non la version de l’application. C’est le versionnement du format de tâche : quand la structure change de manière incompatible, une nouvelle version permet au consommateur de distinguer les anciens messages des nouveaux. Le champ type indique l’opération, ce qui évite de traiter par erreur un message destiné à un autre usage.

Ajoutez le contrat dans le fichier déjà prévu src/queues/factures.js. La fabrique valide les données à la création, et la fonction de validation vérifie également les messages reçus : une file peut contenir des données anciennes, mal formées ou produites par un autre composant. Les erreurs sont explicites afin que l’appelant puisse identifier le champ à corriger.

JavaScript
// src/queues/factures.js
const TYPE_TACHE_FACTURE = 'facture.generer';
const VERSION_TACHE_FACTURE = 1;

function validerTacheFacture(tache) {
  if (!tache || typeof tache !== 'object' || Array.isArray(tache)) {
    throw new TypeError('La tâche doit être un objet.');
  }

  if (tache.type !== TYPE_TACHE_FACTURE) {
    throw new TypeError('Le type de tâche est inconnu.');
  }

  if (tache.version !== VERSION_TACHE_FACTURE) {
    throw new TypeError('La version de tâche n’est pas prise en charge.');
  }

  if (typeof tache.commandeId !== 'string' || tache.commandeId.trim() === '') {
    throw new TypeError('commandeId doit être une chaîne non vide.');
  }

  return tache;
}

function creerTacheFacture({ commandeId }) {
  return validerTacheFacture({
    type: TYPE_TACHE_FACTURE,
    version: VERSION_TACHE_FACTURE,
    commandeId
  });
}

module.exports = {
  creerTacheFacture,
  validerTacheFacture
};

// Exemple d’utilisation autonome :
const tache = creerTacheFacture({ commandeId: 'cmd-1042' });
console.log(JSON.stringify(tache));
Aperçu du rendu
Chargement de l'aperçu…
Résultat attendu
{"type":"facture.generer","version":1,"commandeId":"cmd-1042"}

Le module n’accède ni à la base de données ni à une file particulière : il définit et contrôle uniquement le contrat. L’exemple de fin montre la forme exacte du message produit. Lorsqu’un consommateur recevra ce message, il saura qu’il doit générer une facture et qu’il doit retrouver la commande cmd-1042.

Vérifier le contrat avant de publier

La validation ne remplace pas les contrôles métier : elle vérifie que le message respecte le format attendu, pas que la commande existe ou puisse être facturée. Cette séparation permet de rejeter tôt les messages mal formés tout en laissant au service de facturation la responsabilité de ses règles.

L’identifiant de corrélation, présenté dans la leçon sur la journalisation structurée, pourra être propagé pour relier les journaux de l’API et du traitement. Il ne remplace pas commandeId : le premier sert au suivi d’une demande, le second identifie l’objet métier à traiter. Son intégration au flux sera abordée lors de l’assemblage du projet.

À retenir

  • Un message de facture identifie l’opération, la version de son format et la commande concernée.
  • Utilisez l’identifiant métier pour retrouver les données faisant autorité, plutôt que de dupliquer la commande dans le message.
  • Validez les messages à la création et à la réception, notamment leur type, leur version et leur identifiant.
  • Faites évoluer de manière explicite les formats incompatibles ; ne modifiez pas silencieusement le contrat.

Dans la prochaine leçon, vous publierez ce message depuis l’API après avoir établi le contrat entre la route et la file.

Envie d'aller plus loin ?

Les cours Enovatic sont gratuits et le resteront. Si vous cherchez un accompagnement encadré, nos formations professionnelles sont animées par les mêmes formateurs.