Tout le monde veut des mises à jour en temps réel jusqu'à ce qu'il réalise que « rapide » et « correct » ne sont pas la même chose. Dans un système distribué, les événements peuvent voyager à la vitesse de la lumière et pourtant arriver dans le mauvais ordre. Les WebSockets se déconnectent et se reconnectent. Les brokers de messages renvoient des paquets. Les workers en arrière-plan luttent contre les annulations par timeout. Le résultat ? Un client pourrait voir l'événement 42, puis l'événement 40, puis un instantané affirmant que le système est déjà à l'événement 45. Si vous construisez des workflows d'agents de longue durée, ce chaos n'est pas un cas particulier. C'est la norme. Réglez l'ordre de vos événements avant de vous soucier de gagner quelques millisecondes sur la livraison.

La réalité désordonnée du « temps réel »

Le temps réel est une propriété de transport. Il décrit la rapidité avec laquelle un paquet traverse un câble, et non la cohérence de l'histoire qu'il raconte. Les tâches de longue durée amplifient chaque incohérence car elles s'étendent dans le temps. Un job d'entraînement de modèle, un flux d'approbation multi-étapes ou un pipeline de rendu vidéo peut émettre des dizaines d'événements sur plusieurs minutes ou heures. Durant cette fenêtre, tout peut mal tourner.

Un broker peut tenter de renvoyer un message parce qu'un accusé de réception a été perdu. Un équilibreur de charge peut router deux événements via des chemins réseau différents, permettant au plus récent d'arriver en premier. Un processus worker peut mourir après avoir écrit dans une base de données mais avant d'avoir publié l'événement de succès, pour qu'ensuite un second worker reprenne la tâche et émette son propre progrès. Si votre frontend suppose que le dernier message est le plus fiable, il affichera un état qui n'a jamais existé. Les utilisateurs verront un badge « terminé » repasser brièvement à « en cours de traitement » ou, pire encore, une tâche annulée ressusciter soudainement. La vitesse sans l'ordonnancement n'est que de la confusion à une fréquence d'images plus élevée.

Les numéros de séquence sont la véritable horloge

La solution consiste à utiliser des numéros de séquence stricts et monotones générés par le producteur. Chaque opération qui modifie l'état reçoit un numéro qui augmente de exactement un, sans saut et sans rollback. Ce numéro doit être persisté dans la même transaction que l'événement lui-même. Si la ligne de la base de données est mise à jour mais que le commit de la séquence échoue, vous effectuez un rollback des deux. Cela permet de maintenir la chronologie logique de manière atomique avec le changement d'état.

Les ID d'événements restent utiles, mais ils résolvent un problème différent. Un ID d'événement identifie une charge utile spécifique afin que vous puissiez la dédupliquer lorsque le broker livre deux fois le même message. Un numéro de séquence, en revanche, vous indique où cette charge utile se situe dans la chaîne causale. Il révèle les lacunes. Il révèle l'ordre. Un horodatage (timestamp) ne fait ni l'un ni l'autre. Les horloges dérivent, le NTP recule et les machines virtuelles se mettent en pause. Utilisez les horodatages uniquement à des fins d'affichage, comme « Commencé il y a 3 minutes », et jamais comme clé de tri pour la logique métier.

Comment le client doit gérer le flux

Une fois que le producteur garantit une séquence monotone, le consommateur bénéficie de règles simples et strictes. Si un numéro de séquence entrant est inférieur ou égal au dernier numéro appliqué, ignorez-le. Il s'agit soit d'un doublon, soit d'un retardataire obsolète. Si la séquence est exactement supérieure de un au dernier numéro appliqué, appliquez-la immédiatement. C'est le chemin idéal. Si la séquence fait un bond en avant, par exemple si vous attendiez le 12 mais avez reçu le 15, il manque quelque chose. Mettez le nouvel événement en tampon et demandez au serveur un replay à partir de la séquence suivante attendue. Ne devinez pas. Ne sautez pas d'étapes en espérant que l'écart n'ait pas d'importance.

Les états terminaux doivent être traités comme irrévocables. Une fois qu'une tâche est marquée comme terminée, échouée ou annulée, le client doit rejeter tout changement d'état ultérieur pour cette opération. Cela semble évident jusqu'à ce que vous soyez confronté à