Monitord Acces Change

This commit is contained in:
mr
2026-05-27 16:09:45 +02:00
parent a9284314ef
commit 7c91a8b032
19 changed files with 2496 additions and 332 deletions
+89 -5
View File
@@ -10,6 +10,8 @@ import (
"cloud.o-forge.io/core/oc-lib/tools"
)
// ── considersCache (signal-only) ─────────────────────────────────────────────
// considersCache stocke les canaux en attente d'un PB_CONSIDERS,
// indexés par "executionsId:dataType". Un même message NATS réveille
// tous les waiters enregistrés sous la même clé (broadcast).
@@ -75,9 +77,78 @@ func (c *considersCache) confirm(key string) {
}
}
// ── sourcePresignedCache (value-bearing) ─────────────────────────────────────
// sourcePresignedCache stocke les canaux en attente d'une URL pré-signée pour
// une source privée (isReachable=false), indexés par la clé sourceConsidersKey.
// La valeur transportée est l'URL pré-signée elle-même.
type sourcePresignedCache struct {
mu sync.Mutex
pending map[string][]chan string
}
var globalSourceCache = &sourcePresignedCache{
pending: make(map[string][]chan string),
}
// sourceConsidersKey construit une clé unique pour une demande de source privée.
// La clé encode l'executionsID, le peerID du propriétaire et le resourceID
// pour permettre des requêtes parallèles distinctes.
func sourceConsidersKey(executionsID, peerID, resourceID string) string {
return executionsID + ":src:" + peerID + ":" + resourceID
}
// register inscrit un nouveau canal d'attente pour la clé donnée.
// Retourne le canal à lire et une fonction de désinscription à appeler en defer.
func (c *sourcePresignedCache) register(key string) (<-chan string, func()) {
ch := make(chan string, 1)
c.mu.Lock()
c.pending[key] = append(c.pending[key], ch)
c.mu.Unlock()
unregister := func() {
c.mu.Lock()
defer c.mu.Unlock()
list := c.pending[key]
for i, existing := range list {
if existing == ch {
c.pending[key] = append(list[:i], list[i+1:]...)
break
}
}
if len(c.pending[key]) == 0 {
delete(c.pending, key)
}
}
return ch, unregister
}
// confirm réveille tous les waiters enregistrés sous la clé donnée
// en leur transmettant l'URL pré-signée, puis les supprime du cache.
func (c *sourcePresignedCache) confirm(key, url string) {
c.mu.Lock()
list := c.pending[key]
delete(c.pending, key)
c.mu.Unlock()
for _, ch := range list {
select {
case ch <- url:
default:
}
}
}
// ── StartConsidersListener ────────────────────────────────────────────────────
// StartConsidersListener démarre un abonné NATS global via ListenNats (oclib)
// qui reçoit les messages CONSIDERS_EVENT et réveille les goroutines en attente
// via globalConsidersCache. Doit être appelé une seule fois au démarrage.
// qui reçoit les messages CONSIDERS_EVENT et réveille les goroutines en attente.
//
// Deux chemins de dispatch :
// - Si presigned_url est présent dans le payload → globalSourceCache (Phase 4).
// - Sinon → globalConsidersCache (Phases COMPUTE / STORAGE, signal sans valeur).
//
// Doit être appelé une seule fois au démarrage.
func StartConsidersListener() {
log := logs.GetLogger()
log.Info().Msg("Considers NATS listener starting on " + tools.CONSIDERS_EVENT.GenerateKey())
@@ -87,14 +158,27 @@ func StartConsidersListener() {
var body struct {
ExecutionsID string `json:"executions_id"`
PeerID string `json:"peer_id,omitempty"`
// PresignedURL est non-vide uniquement pour les réponses de source privée (Phase 4).
PresignedURL string `json:"presigned_url,omitempty"`
// ResourceID identifie la ressource Processing/Data pour la Phase 4.
ResourceID string `json:"resource_id,omitempty"`
}
if err := json.Unmarshal(resp.Payload, &body); err != nil {
log.Error().Msg("CONSIDERS_EVENT: cannot unmarshal payload: " + err.Error())
return
}
key := considersKey(body.ExecutionsID, resp.Datatype, body.PeerID)
log.Info().Msg(fmt.Sprintf("CONSIDERS_EVENT dispatched for key=%s", key))
globalConsidersCache.confirm(key)
if body.PresignedURL != "" {
// Phase 4 — source privée : transmettre l'URL pré-signée.
key := sourceConsidersKey(body.ExecutionsID, body.PeerID, body.ResourceID)
log.Info().Msg(fmt.Sprintf("CONSIDERS_EVENT (presigned) dispatched for key=%s", key))
globalSourceCache.confirm(key, body.PresignedURL)
} else {
// Phases COMPUTE / STORAGE — simple signal.
key := considersKey(body.ExecutionsID, resp.Datatype, body.PeerID)
log.Info().Msg(fmt.Sprintf("CONSIDERS_EVENT dispatched for key=%s", key))
globalConsidersCache.confirm(key)
}
},
})
}