5.8 KiB
NATS dans oc-scheduler
Vue d'ensemble
oc-scheduler utilise NATS comme bus d'événements pour deux objectifs :
- Recevoir les planners (disponibilité des ressources) publiés par
oc-discovery. - Réagir aux modifications de workflows pour diffuser un planner actualisé et signaler les streams WebSocket actifs.
Tout le code NATS se trouve dans infrastructure/nats.go.
Canaux écoutés
PROPALGATION_EVENT — réception des planners
Condition d'acceptation : resp.FromApp == "oc-discovery" et prop.Action == PB_PLANNER.
Ce qui se passe :
- Le payload est désérialisé en
planner.Planner. - Le champ
peer_idest extrait pour identifier le pair. - Le planner est stocké dans
PlannerCache[peerID]viastorePlanner(). - Si c'est la première apparition de ce
peerIDdans le cache, une goroutine de TTL est lancée (voir §TTL ci-dessous). - Tous les abonnés en attente d'un changement sur ce
peerIDsont notifiés.
CREATE_RESOURCE — modification d'un workflow
Condition d'acceptation : resp.Datatype == WORKFLOW.
Ce qui se passe :
- Le payload est désérialisé en
workflow.Workflow. broadcastPlanner(wf)est appelé : pour chaque pair (storage + compute) du workflow dont le planner n'est pas encore en cache, un événementPB_PLANNERest émis sur NATS afin de demander un planner frais àoc-discovery.notifyWorkflowWatchers(wf.GetID())est appelé : tous les streams WebSocket qui observent ce workflow sont signalés pour rafraîchir leur liste de pairs surveillés.
Canaux émis
PROPALGATION_EVENT — deux actions possibles
| Action | Déclencheur | Effet attendu |
|---|---|---|
PB_PLANNER |
Workflow modifié, pair inconnu du cache | oc-discovery renvoie le planner du pair |
PB_CLOSE_PLANNER |
TTL expiré ou déconnexion WebSocket | Les consommateurs (oc-discovery, autres schedulers) libèrent leur état pour ce pair |
Cache des planners (PlannerCache)
PlannerCache : map[string]*planner.Planner // clé = peerID
plannerAddedAt : map[string]time.Time // horodatage de première insertion
- Protégé par
plannerMu(RWMutex). - Alimenté uniquement via
storePlanner()(appelé par le listener NATS). - Supprimé via
EmitNATS(peerID, PB_CLOSE_PLANNER), qui efface l'entrée et notifie les abonnés.
TTL de 24 heures
À la première insertion d'un peerID, une goroutine est lancée :
sleep(24h)
→ si l'entrée existe encore : EmitNATS(peerID, PB_CLOSE_PLANNER)
Cela évite que des planners obsolètes stagnent indéfiniment. L'entrée est supprimée et les streams actifs reçoivent une notification « plus de planner » pour ce pair.
Pub/sub interne
Un registre d'abonnements en mémoire permet à d'autres composants (notamment le controller WebSocket) de réagir aux événements sans coupler directement le code NATS et les goroutines HTTP.
Deux registres distincts :
| Registre | Clé | Signification |
|---|---|---|
plannerSubs |
peerID |
« le planner de ce pair a changé » |
workflowSubs |
workflowID |
« ce workflow a été modifié » |
API
// S'abonner aux changements de planners pour plusieurs pairs
ch, cancel := SubscribePlannerUpdates(peerIDs []string)
// S'abonner aux modifications d'un workflow
ch, cancel := SubscribeWorkflowUpdates(wfID string)
Chaque canal est bufférisé (capacity 1) : si un signal est déjà en attente, les suivants sont ignorés sans bloquer.
Intégration avec le stream WebSocket (GET /oc/:id/check)
Le handler CheckStream dans controllers/workflow_sheduler.go exploite ces mécanismes :
- Ouverture : résolution des
peerIDsdu workflow, abonnement àSubscribePlannerUpdatesetSubscribeWorkflowUpdates. - Boucle de streaming :
plannerChreçoit un signal → re-calcul duCheckResultet envoi au client.wfChreçoit un signal (workflow modifié) → recalcul despeerIDs, désabonnement + ré-abonnement aux nouveaux pairs, re-calcul et envoi.
- Fermeture (déconnexion client) :
- Désabonnement des deux registres.
EmitNATS(peerID, PB_CLOSE_PLANNER)pour chaque pair surveillé : le cache est purgé etoc-discoveryest informé que le scheduler n'a plus besoin du planner.
Flux de données résumé
oc-discovery ──PROPALGATION_EVENT(PB_PLANNER)──► ListenNATS
│
storePlanner()
PlannerCache[peerID] = planner
notifyPlannerWatchers(peerID)
│
SubscribePlannerUpdates
│
CheckStream (WS) ──► client
Workflow modifié ──CREATE_RESOURCE(WORKFLOW)──► ListenNATS
│
broadcastPlanner(wf)
PROPALGATION_EVENT(PB_PLANNER) → oc-discovery
notifyWorkflowWatchers(wfID)
│
SubscribeWorkflowUpdates
│
CheckStream refresh peerIDs ──► client
TTL 24h / déconnexion WS ──► EmitNATS(PB_CLOSE_PLANNER)
│
delete PlannerCache[peerID]
notifyPlannerWatchers(peerID)
PROPALGATION_EVENT(PB_CLOSE_PLANNER) → NATS bus