FEAT: Broker de jobs d'analyse — RabbitMQ + MassTransit (mutualisation IA/GPU inter-sites) #72

Closed
opened 2026-08-12 09:46:39 +02:00 by nonobis · 0 comments
Owner

🎯 Contexte

Objectif produit : mutualiser les ressources IA/GPU entre sites. Un site sans GPU doit pouvoir déléguer l'analyse de ses frames à des agents équipés GPU, même sur un autre site physique. Ce broker est le socle, extensible à toute opération déléguable (YOLO, OCR plaque, encodage clip, agrégation).

Décision d'architecture (vérifiée — fiche KB-HEIMDALL-ORLEANS du 12/08/2026) : Microsoft.Orleans est écarté — non-goal déclaré par les mainteneurs (pas de connexion directe de tiers au cluster ; TCP direct entre silos requis ; détection de panne WAN inadaptée : un silo déclaré mort se tue lui-même ; multi-clustering retiré depuis v2 et epic #7485 non livré depuis 2022). Les agents Heimdall sont derrière des NAT différents → le pattern passerelle actuel (HTTPS heartbeat) est le bon, et la mutualisation passe par une file de jobs durable : RabbitMQ + MassTransit (solution B retenue). Les agents restent producteurs/consommateurs en sortie NAT (connexion AMQP sortante vers le broker central), aucun port entrant à ouvrir.

🔍 État actuel (vérifié dans le code)

Analyse 100 % locale aujourd'hui : l'agent capture (CameraStreamService → SnapshotPipelineService) et appelle FrameAnalyzerService.AnalyzeFrameAsync (stub RunInference → [], pas encore d'inférence réelle — cf. ticket #2). Le central orchestre l'assignation caméras→agents via Hangfire (heartbeat-monitor, agent-failover /1 min) et pousse la config par pull HTTPS (ConfigReceiverService). Aucune file de messages dans le stack (aucun conteneur RabbitMQ, aucun package MassTransit).

🧩 À faire

  • Ajouter le conteneur rabbitmq:3-management au docker-compose (dev + prod) : user/vhost dédiés Heimdall, credentials via secrets/env, port management exposé au central uniquement
  • Ajouter les packages MassTransit + MassTransit.RabbitMQ au projet Web (central) et au projet Agent
  • Définir les contrats de messages partagés (nouveau projet Heimdall.Contracts ou dossier commun) : AnalysisJobRequested, AnalysisJobCompleted, AnalysisJobFailed, AnalysisJobCancelled (+ enveloppe : JobId, SiteId, CameraId, OperationType, Priority, PayloadRef, Timestamps)
  • Configurer le bus : endpoint RabbitMQ central, retry policy (ex. 3 tentatives avec backoff), dead-letter exchange, prefetch count
  • Abstraire derrière IAnalysisJobQueue (publish/subscribe) pour testabilité — l'implémentation RabbitMQ/MassTransit est derrière l'interface
  • Côté central : consommer les résultats (AnalysisJobCompleted) et les relier aux événements caméra existants (reporting détections)
  • Côté agent : config du broker (URL, credentials) via les settings distants (ConfigReceiverService) avec fallback local
  • Health check broker (connexion AMQP, file vide/accumulation) + métriques OpenTelemetry (jobs publiés/consommés/échoués, latence)
  • Tests : publication/consommation (Testcontainers RabbitMQ ou transport in-memory MassTransit), retry, dead-letter

🧪 Critères d'acceptation

  • Un job soumis par l'agent capteur (site A) est consommé et exécuté par l'agent GPU (site B) — sites différents
  • Un échec d'exécution déclenche le retry puis le dead-letter après N tentatives (job visible en DLQ, pas perdu)
  • Aucun port entrant requis côté agent (connexion sortante uniquement)
  • Le broker redémarre sans perte de jobs en vol (durabilité des files)
  • make test vert

📁 Fichiers concernés

docker/docker-compose.yml, docker/docker-compose.prod.yml, src/Heimdall.Contracts/ (nouveau), src/Heimdall.Web/Program.cs, src/Heimdall.Web/appsettings.json, src/Heimdall.Agent/Program.cs, src/Heimdall.Infrastructure/ (config bus + services), tests/

⚠️ Impact

Ajoute un point d'infrastructure central (RabbitMQ) — à sécuriser (credentials), sauvegarder et surveiller. Risque de régression faible : l'existant (Hangfire, SignalR, heartbeat) reste inchangé tant que les agents ne basculent pas en mode remote.

📝 Notes

Dépend de : ticket #2 (inférence réelle) pour que les jobs produisent des détections ; tickets capacités GPU + ordonnanceur pour le routage ; ticket docker GPU pour que les consommateurs aient accès au matériel. Fiche de recherche : ~/.hermes/profiles/the-librarian/cache/fiches/KB-HEIMDALL-ORLEANS/.

## 🎯 Contexte **Objectif produit : mutualiser les ressources IA/GPU entre sites.** Un site sans GPU doit pouvoir déléguer l'analyse de ses frames à des agents équipés GPU, même sur un autre site physique. Ce broker est le socle, extensible à toute opération déléguable (YOLO, OCR plaque, encodage clip, agrégation). **Décision d'architecture (vérifiée — fiche KB-HEIMDALL-ORLEANS du 12/08/2026) :** Microsoft.Orleans est **écarté** — non-goal déclaré par les mainteneurs (pas de connexion directe de tiers au cluster ; TCP direct entre silos requis ; détection de panne WAN inadaptée : un silo déclaré mort se tue lui-même ; multi-clustering retiré depuis v2 et epic #7485 non livré depuis 2022). Les agents Heimdall sont derrière des NAT différents → le pattern passerelle actuel (HTTPS heartbeat) est le bon, et la mutualisation passe par une **file de jobs durable** : **RabbitMQ + MassTransit (solution B retenue)**. Les agents restent producteurs/consommateurs en sortie NAT (connexion AMQP sortante vers le broker central), aucun port entrant à ouvrir. ## 🔍 État actuel (vérifié dans le code) Analyse **100 % locale** aujourd'hui : l'agent capture (CameraStreamService → SnapshotPipelineService) et appelle `FrameAnalyzerService.AnalyzeFrameAsync` (stub `RunInference` → `[]`, pas encore d'inférence réelle — cf. ticket #2). Le central orchestre l'assignation caméras→agents via Hangfire (`heartbeat-monitor`, `agent-failover` /1 min) et pousse la config par pull HTTPS (`ConfigReceiverService`). **Aucune file de messages dans le stack** (aucun conteneur RabbitMQ, aucun package MassTransit). ## 🧩 À faire - [ ] Ajouter le conteneur `rabbitmq:3-management` au docker-compose (dev + prod) : user/vhost dédiés Heimdall, credentials via secrets/env, port management exposé au central uniquement - [ ] Ajouter les packages `MassTransit` + `MassTransit.RabbitMQ` au projet Web (central) et au projet Agent - [ ] Définir les **contrats de messages partagés** (nouveau projet `Heimdall.Contracts` ou dossier commun) : `AnalysisJobRequested`, `AnalysisJobCompleted`, `AnalysisJobFailed`, `AnalysisJobCancelled` (+ enveloppe : JobId, SiteId, CameraId, OperationType, Priority, PayloadRef, Timestamps) - [ ] Configurer le bus : endpoint RabbitMQ central, retry policy (ex. 3 tentatives avec backoff), dead-letter exchange, prefetch count - [ ] Abstraire derrière `IAnalysisJobQueue` (publish/subscribe) pour testabilité — l'implémentation RabbitMQ/MassTransit est derrière l'interface - [ ] Côté central : consommer les résultats (`AnalysisJobCompleted`) et les relier aux événements caméra existants (reporting détections) - [ ] Côté agent : config du broker (URL, credentials) via les settings distants (`ConfigReceiverService`) avec fallback local - [ ] Health check broker (connexion AMQP, file vide/accumulation) + métriques OpenTelemetry (jobs publiés/consommés/échoués, latence) - [ ] Tests : publication/consommation (Testcontainers RabbitMQ ou transport in-memory MassTransit), retry, dead-letter ## 🧪 Critères d'acceptation - [ ] Un job soumis par l'agent capteur (site A) est consommé et exécuté par l'agent GPU (site B) — **sites différents** - [ ] Un échec d'exécution déclenche le retry puis le dead-letter après N tentatives (job visible en DLQ, pas perdu) - [ ] Aucun port entrant requis côté agent (connexion sortante uniquement) - [ ] Le broker redémarre sans perte de jobs en vol (durabilité des files) - [ ] `make test` vert ## 📁 Fichiers concernés docker/docker-compose.yml, docker/docker-compose.prod.yml, src/Heimdall.Contracts/ (nouveau), src/Heimdall.Web/Program.cs, src/Heimdall.Web/appsettings.json, src/Heimdall.Agent/Program.cs, src/Heimdall.Infrastructure/ (config bus + services), tests/ ## ⚠️ Impact Ajoute un point d'infrastructure central (RabbitMQ) — à sécuriser (credentials), sauvegarder et surveiller. Risque de régression faible : l'existant (Hangfire, SignalR, heartbeat) reste inchangé tant que les agents ne basculent pas en mode remote. ## 📝 Notes Dépend de : ticket #2 (inférence réelle) pour que les jobs produisent des détections ; tickets capacités GPU + ordonnanceur pour le routage ; ticket docker GPU pour que les consommateurs aient accès au matériel. Fiche de recherche : `~/.hermes/profiles/the-librarian/cache/fiches/KB-HEIMDALL-ORLEANS/`.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
nonobis/Heimdall#72
No description provided.