Pollen 🟢 Porté en Amalgame — package v0.3.0

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, 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.

C'est fait : le port Amalgame est livré

Pollen était un prototype Node.js (TARMeule). Il est aujourd'hui un package Amalgame, amalgame-pollen v0.3.0 — réutilisable, installable via amc package add pollen, validé par ~200 assertions de test. Trois repos composent le produit :

  • amalgame-pollen (v0.3.0) — la bibliothèque AM officielle : transport, registre de capacités, et le moteur de workflow v3. Embarquable dans une app Mosaic ou n'importe quel programme AM.
  • pollen — un binaire CLI de référence (transport TCP), issu du prototype TARMeule.
  • pollen-manager — l'éditeur web de workflow.json + dashboard d'exécutions (app Mosaic, en chantier).

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 — le package amalgame-pollen utilise des connexions TCP longue durée, en JSON délimité par ligne (un message = une ligne), avec ACK applicatif. Direct nœud à nœud, sans broker intermédiaire.
  • Coordination — un fichier workflow.json (schéma pollen/v3) sur un partage réseau commun. Il décrit les actions (topics abstraits) et les entries (qui réagit à quoi, et comment). Chaque serveur lit ce fichier, identifie son rôle et exécute sa partie.

Le workflow.json est l'orchestrateur. Il n'y a pas de process « orchestrator » à faire tourner. 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
  • Orchestration dans la donnée — modifier la topologie = éditer un JSON, sans redéployer
  • Résilience aux ruptures réseau — un nœud qui revient relit workflow.json et reprend sa place

workflow.json v3 — 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 (NFS, SMB, partage cluster). Le schéma pollen/v3 apporte un vrai moteur de contrôle de flux — plus seulement un DAG statique.

// workflow.json — exemple : chaîne de traitement de température
{
  "schema":  "pollen/v3",
  "name":    "telemetry-pipeline",
  "version": 1,

  // actions = topics abstraits, résolus via le registre de capacités
  "actions": {
    "filter":  { "topic": "temperature.filtered" },
    "archive": { "topic": "temperature.archive" },
    "alert":   { "topic": "ops.alert" }
  },

  // entries = handlers déclenchés par un topic entrant
  "entries": [
    {
      "name": "main",
      "on":   "temperature.raw",
      "do": [
        { "type": "call", "action": "filter" },
        { "type": "if", "cases": [
            { "when": "msg.data.valeur > 80",
              "do": { "type": "call", "action": "alert", "mode": "all" } },
            { "else": true,
              "do": { "type": "call", "action": "archive" } }
        ] }
      ]
    }
  ]
}

Le moteur v3 est un tree-walker qui exécute une séquence de steps typés :

  • call — invoque une action ; mode: "one" | "all" (un fournisseur ou tous), on_error: "fail" | "log" | "drop"
  • if — branchement premier-match (cases avec when + else: true)
  • for / while — itération sur une liste, boucle bornée par maxIter
  • set — mute l'état d'exécution via une expression CEL-lite
  • goto + anchor — saut entre entries (avec params / returns, pile jusqu'à 64 frames) et point de reprise nommé pour les patterns de retry

Modifier la topologie = éditer un fichier JSON. Le chargeur valide le schéma (entries non définies, cycles de goto, ancres, syntaxe des expressions) avant exécution.

API Amalgame — un nœud qui suit le workflow

L'app côté serveur est minimale : on déclare son rôle et le partage, on charge le workflow v3, on annonce ses capacités, puis on bloque dans la boucle d'écoute. Pollen gère le reste (dispatch v3, routage vers les fournisseurs, load balancing).

namespace App
import Amalgame.Pollen

public class Program {
    public static void Main(string[] args) {
        Pollen.WorkflowSetSharedDir("./shared")
        Pollen.WorkflowSetSelf("filter-1", "127.0.0.1", 5000)
        Pollen.WorkflowLoadV3("./shared/workflow.json")

        // Annonce les capacités de ce nœud + lit le registre des autres
        Pollen.StartCapabilityWriter("filter-1", "127.0.0.1", 5000)
        Pollen.StartCapabilityReader()
        Pollen.SetLoadBalance(true)        // forwarding résolu par le registre

        Pollen.StartListener(5000)         // boucle TCP : reçoit, dispatch v3, ré-émet
    }
}

Injecter un message dans le workflow depuis l'extérieur (un capteur, une app Mosaic, un script) :

// fire-and-forget
Pollen.Publish("proc-01.lan", 5000, "temperature.raw", 1, dataJson)

// attend l'ACK applicatif (timeout en ms)
Pollen.PublishSync("proc-01.lan", 5000, "temperature.raw", 1, dataJson, 2000)

Briques livrées (issues du prototype TARMeule)

Le prototype Node.js (github.com/BastienMOUGET/TARMeule) a servi de référence fonctionnelle. Voici ce que la v0.3.0 implémente réellement :

livré

Transport TCP + ACK

Connexions TCP, enveloppes JSON une par ligne (messageId, type, topic, data, timestamp), ACK applicatif. TCP garantit l'ordre et l'absence de doublons en flux.

livré

Moteur de workflow v3

Chargeur JSON → AST, validateur (8 règles), dispatcher tree-walking. Steps call / goto / anchor / if / for / while / set.

livré

Expressions CEL-lite

Lexer + parser Pratt + évaluateur. Arithmétique, comparaisons, booléens, in, ternaire ; builtins len, int, float, string, contains, startsWith… Chemins state.X, params.Y, msg.data.Z.

livré

Registre de capacités + load balancing

Chaque nœud annonce ses actions dans capabilities/. Les actions du workflow sont résolues à l'exécution en fournisseur concret, avec un load balancer power-of-two-choices.

livré

État + traçage d'exécutions

État par exécution persisté atomiquement dans sharedDir/state/. Chaque hop est enregistré dans sharedDir/executions/ — base du dashboard live du manager.

v0.4.0

Chiffrement AES-256

Chiffrement de paquet optionnel (clé partagée), prévu pour v0.4.0 une fois amalgame-crypto stabilisé. Aujourd'hui : payload JSON en clair (réseau de confiance).

Pollen Manager — l'éditeur visuel

pollen-manager est une application Mosaic (servie sur :3000) qui lit/écrit le workflow.json et surface les exécutions live que chaque nœud écrit dans sharedDir/executions/. Ce n'est pas un control-plane : Pollen reste chorégraphié (chaque nœud connaît sa partie) — le manager édite la partition et visualise les runs.

  • API REST GET/PUT /api/workflow (lecture/écriture + validation), /api/executions, /api/capabilities, POST /api/inject
  • Rendu SVG du DAG + flowchart du workflow v3
  • Éditeur drag & drop, overlay d'exécutions live sur le graphe, broadcast SYNC à la sauvegarde — en cours

Statut : v0.1.0-dev, scaffold de phase 4.0. Le build est momentanément bloqué par une limite du packager Amalgame (les classes des fichiers sources frères ne sont pas encore liées) — suivi en amont côté compilateur.

Pourquoi l'avoir porté en Amalgame

Le prototype Node.js était fonctionnel mais lourd à déployer sur les cibles visées (capteurs, passerelles industrielles, automates) : Node.js et ses ~50 Mo de runtime, le keep-alive du process, npm install… Le port AM donne :

  • Un binaire natif unique — quelques Mo, démarre en quelques ms
  • Aucun runtime à installer — déployable sur Raspberry Pi, automates Linux, Windows embedded
  • RAM bornée, pas de pauses GC Node.js — comportement temps-réel prévisible
  • Réutilisable — un package, pas un binaire figé : embarquable dans une app Mosaic (bridge HTTP → Pollen)
  • Intégration amalgame-service — daemon systemd ou service Windows natif (à venir)
  • Chiffrement via amalgame-crypto — partagera le code AES du reste de l'écosystème (v0.4.0)

Roadmap

v0.1 → v0.3

Le cœur (livré)

Transport TCP + ACK, moteur de workflow v3 (tree-walker + 8 règles de validation), expressions CEL-lite, registre de capacités + load balancing power-of-two, état par exécution + traçage.

v0.4

Sécurité & observabilité

Chiffrement AES-256 (clé partagée) via amalgame-crypto. Métriques Prometheus. Validation de schéma plus riche en émission/réception.

v0.5+

QoS & bridge Mosaic

Modes QoS configurables (fire-and-forget / ack-required / at-least-once) par action. Re-landing du bridge Mosaic (exposer un topic Pollen en WebSocket, et inversement) pour brancher une dashboard web aux capteurs.

v1.x

Identité & manager mature

Authentification par clés publiques (Ed25519) + ACLs par topic. Manager : drag & drop des nœuds, overlay d'exécutions live, intervention manuelle (force-ACK, replay).

Ce que 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 — le moteur v3 fait du contrôle de flux (if/for/while/goto + état), mais pas d'historique d'exécution durable, ni de saga transactionnelle avec rollback.
  • Pas du multi-datacenter — conçu LAN ou VPN-LAN. Pas pensé pour traverser l'Internet ouvert.
  • 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 ».

Tester Pollen

Pollen est porté en Amalgame (package v0.3.0) et utilisable. Le manager visuel et le chiffrement AES suivent.