Pollen
Le bus de données pair-à-pair + orchestrateur de workflow déclaratif d'Amalgame. Pas de broker central, pas de cluster Zookeeper, pas de SPOF — chaque nœud parle directement aux autres en UDP, et tous lisent le même workflow.json sur un partage réseau pour savoir quoi faire à chaque étape. Sœur de Mosaic : là où Mosaic gère ton trafic HTTP entrant, Pollen diffuse tes données entre tes services et coordonne leurs traitements.
Pourquoi « Pollen »
Le pollen circule sans coordinateur central : porté de fleur en fleur par des transporteurs autonomes, il transporte ce qu'il y a de plus précieux à propager — l'information génétique. Chaque transporteur sait où aller, le pollen sait quoi devenir. C'est exactement le modèle d'exécution visé : des nœuds autonomes qui émettent et reçoivent en direct, sur un réseau où la coordination est dans la donnée partagée (le workflow.json), pas dans un chef d'orchestre.
Deux couches : un bus pair-à-pair et un orchestrateur de workflow
Pollen ne ressemble pas à RabbitMQ, Kafka ou NATS — qui sont tous des brokers centraux. Pollen est plus proche d'un mix entre ZeroMQ (pour le transport) et Argo Workflows (pour l'orchestration), mais entièrement décentralisé :
- Transport — UDP direct serveur à serveur, sans handshake TCP, sans intermédiaire. Le chemin le plus rapide possible entre deux process sur un même LAN.
- Coordination — un fichier
workflow.jsonsur un partage réseau commun. Il décrit les nœuds (qui fait quoi) et leur arborescence (qui suit qui). Chaque serveur lit ce fichier au démarrage, sait quels événements lui sont destinés et où envoyer le résultat.
Le workflow.json est l'orchestrateur. Il n'y a pas de process « orchestrator » à faire tourner quelque part. Le fichier est déclaratif, les nœuds sont autonomes — chacun sait à chaque étape ce qu'il a à faire.
Quand utiliser Pollen
- Réseau local / LAN — IoT, SCADA, capteurs industriels, supervision d'usine
- Pipelines de traitement distribués — chaîne de transformation (acquisition → filtrage → agrégation → archivage) sur plusieurs machines
- Topologies symétriques — pas de relation client/serveur, tous les nœuds émettent et reçoivent
- Zéro infra à provisionner — pas de VM dédiée, pas de Docker compose pour un broker, pas de serveur de workflow
- Latence faible — UDP, pas de handshake, pas de file d'attente intermédiaire
- Résilience aux ruptures réseau — un nœud qui revient relit
workflow.jsonet reprend sa place
workflow.json — l'orchestrateur déclaratif
L'idée centrale : aucun processus ne décide qui fait quoi. La décision est dans un fichier JSON posé sur un partage réseau accessible à tous les nœuds (NFS, SMB, partage cluster). Chaque serveur le lit et applique sa partie.
// workflow.json — exemple : chaîne de traitement de température { "name": "telemetry-pipeline", "version": 3, "nodes": { "acquisition-1": { "host": "sensor-gw-01.lan", "port": 5000, "emits": ["temperature.raw"], "next": ["filter-1"] }, "filter-1": { "host": "proc-01.lan", "port": 5000, "consumes": ["temperature.raw"], "emits": ["temperature.filtered"], "next": ["aggregator-1", "archive-1"] }, "aggregator-1": { "host": "proc-02.lan", "port": 5000, "consumes": ["temperature.filtered"], "emits": ["temperature.minute-avg"], "next": ["dashboard-1"] }, "archive-1": { "host": "storage-01.lan", "port": 5000, "consumes": ["temperature.filtered"] }, "dashboard-1": { "host": "web-01.lan", "port": 5000, "consumes": ["temperature.minute-avg"] } } }
Chaque serveur Pollen, en démarrant :
- ◐Lit
workflow.jsonsur le partage réseau partagé - ◐Identifie le ou les nœuds qui lui correspondent (matching par
host+port) - ◐S'abonne automatiquement aux topics
consumeset configure les destinationsnextpour ses émissions - ◐Écoute en UDP les messages de ses topics, applique son traitement, ré-émet vers les nœuds suivants
- ◐Surveille
workflow.jsonvia amalgame-io-filewatcher — toute modification recharge la topologie à chaud, sans redémarrer les services
Modifier la topologie = éditer un fichier JSON. Ajouter un nœud = ajouter une entrée. Réorienter un flux = changer next. Pas de redéploiement, pas d'API de management, pas de console centrale.
Architecture (issue du prototype TARMeule)
L'implémentation Node.js (github.com/BastienMOUGET/TARMeule) servira de référence fonctionnelle pour le port en Amalgame. Les concepts :
Topics versionnés
Chaque topic est identifié par un UUID + un schéma ({ valeur: "number", unité: "string" }) + une version. Les producteurs envoient en référençant une version. Les schémas évoluent sans casser les anciens consommateurs.
Souscriptions explicites
Chaque nœud déclare ses souscriptions : { ip, port, topics: [...] }. Les producteurs lisent cette liste pour savoir à qui envoyer. Pas de découverte multicast — annuaire de fichiers JSON partagé.
Transport UDP + ACK custom
Envoi UDP direct nœud → nœud, avec mécanisme d'accusé de réception applicatif (timeout + retry configurables, ackTimeout × maxRetries). UUID de message mémorisé pour déduplication.
Chiffrement AES optionnel
Si encryptionKey est configurée, chaque paquet est chiffré AES-256-CBC avant émission. Sinon, payload JSON en clair (réseau de confiance).
Synchronisation par notifications
Quand un nœud crée/modifie un topic ou une souscription, il diffuse un message SYNCHRONIZATION aux autres nœuds, qui rechargent le fichier correspondant. Les fichiers JSON sont la source de vérité persistée.
Cache RAM + persistance fichier
Tous les topics et souscriptions sont en RAM pour la perf. Les fichiers JSON dans sharedDir/ permettent au nœud de redémarrer sans tout perdre, et au cluster de se reformer après une coupure.
API Amalgame visée — un nœud qui suit le workflow
L'app côté serveur est minimale : on dit son nom dans le workflow, on enregistre une fonction par topic consommé, et Pollen gère le reste (lecture du JSON partagé, abonnements, routage UDP vers les nœuds suivants).
namespace App import Amalgame.Pollen public class Program { public static void Main(string[] args) { // Initialiser le nœud (lit config.json + workflow.json partagé) let node = Pollen.Node("filter-1", configDir: "./config") // Enregistrer un handler pour le topic consommé. // L'émission vers les nœuds "next" est faite automatiquement // par Pollen à partir du return du handler. node.On("temperature.raw", fn(msg) { let v = msg.Get("valeur") as float if (v < -50.0 || v > 150.0) { return Pollen.Drop() // hors gamme → ignoré } return Pollen.Emit("temperature.filtered", { valeur: v, unite: msg.GetString("unite"), source: msg.Source }) }) node.OnTimeout(fn(msgId) { log.Warn("ACK manqué pour {msgId}") }) node.Run() // boucle UDP + filewatch sur workflow.json } }
La couche bas niveau (héritée de TARMeule) reste accessible si tu as besoin de pub/sub libre sans workflow :
// Mode "raw" — pub/sub direct, sans workflow.json let bus = Pollen.Raw("./config") bus.UpsertTopic(null, "temperature", 1, { valeur: "number" }) bus.UpsertSouscription({ ip: "192.168.1.143", port: 5000, topics: ["temperature"] }) bus.SendMessage({ uuid: topicId, version: 1 }, { valeur: 25 })
Pourquoi porter en Amalgame
Le prototype Node.js est fonctionnel mais lourd à déployer sur les cibles visées (capteurs, passerelles industrielles, automates) : il faut Node.js et ses 50 Mo de runtime, gérer le keep-alive du process, npm install, etc.
En Amalgame, le port donnera :
- ◐Un binaire natif unique —
./pollen-node, ~3 Mo, démarre en quelques ms - ◐Aucun runtime à installer — déployable sur Raspberry Pi, automates Linux, Windows embedded
- ◐Latence UDP minimale — pas de GC pauses Node.js, RAM bornée
- ◐Intégration
amalgame-service— daemon systemd ou service Windows natif - ◐Chiffrement via
amalgame-crypto— partage le même code AES que le reste de l'écosystème (quand Argon2id/AES landent) - ◐API Amalgame typée — schémas de topics validés au build, plus de bugs de structure runtime
Roadmap envisagée
Trois phases, condition préalable : que amalgame-crypto ait livré AES (planifié dans Mosaic phase 2.1).
Port de la couche transport
Port AM de TARMeule : UDPManager, ACK + retry, cache RAM, fichiers JSON par nœud, notifications de synchro. Wire-compatible avec un nœud TARMeule Node.js.
Couche workflow
Lecture de workflow.json sur partage réseau, matching host:port → nœud, abonnements et routages next auto. Filewatch + rechargement à chaud via amalgame-io-filewatcher.
Validation de schéma
Validation des messages contre la structure du topic en émission ET en réception. Erreur explicite si un producteur envoie un payload incompatible.
QoS configurable
Trois modes : fire-and-forget (pas d'ACK), ack-required (le mode actuel), at-least-once (retry jusqu'au succès). Choix par topic ou par arête du workflow.
Discovery multicast (option)
Annonce multicast LAN optionnelle (239.x.x.x:port) pour les nœuds qui ne sont pas dans workflow.json — utile pour les capteurs dynamiques qui rejoignent et quittent.
Workflow editor visuel
Petit outil web (servi par Mosaic) pour éditer workflow.json graphiquement — drag & drop des nœuds, traçage des arêtes. Optionnel : on peut très bien éditer le JSON à la main.
Bridge vers Mosaic
Bridge AM optionnel pour exposer un topic Pollen comme WebSocket Mosaic, et inversement. Connecter une dashboard web aux capteurs sans broker tiers.
Authentification par clés
Aujourd'hui : clé symétrique AES partagée. Évolution : clés publiques (Ed25519 quand amalgame-crypto l'a) pour signer les messages et autoriser des publishers par identité.
Ce qu'Pollen n'est pas
- Pas un broker durable — pas de queue persistante, pas de replay façon Kafka. Un message manqué est perdu (sauf retry inclus dans la fenêtre ACK).
- Pas un Temporal / Argo Workflows complet — pas d'historique d'exécution, pas de retry-with-backoff stateful, pas de saga transactionnelle. Le workflow est topologique (qui parle à qui), pas séquentiel-stateful (étape A puis B puis C avec rollback).
- Pas du multi-datacenter — UDP a peu de chances de passer un firewall Internet. Pollen est conçu LAN ou VPN-LAN.
- Pas un remplacement de Mosaic — pour exposer une API web à des clients hors LAN, c'est Mosaic qu'il faut.
- Pas un MOM transactionnel — pas de transactions atomiques cross-topic, pas de dead-letter queue, pas de garanties d'ordre global.
Pour ces cas-là, l'écosystème propose les bons outils tiers : Kafka pour replay durable, RabbitMQ pour workflows transactionnels, MQTT pour IoT broker-centralisé. Pollen joue dans la case « pipeline temps-réel LAN, sans broker, sans serveur d'orchestration ».
Pas encore implémenté
Pollen est aujourd'hui un prototype Node.js fonctionnel (TARMeule) et une intention de port Amalgame. La priorité actuelle reste Mosaic ; Pollen démarrera quand amalgame-crypto aura livré AES.