@startuml 24_failure_retry_lost_native
title F6 — retryLostNative : reconnexion natif après panne réseau

participant "Node / Indexer" as Caller
participant "Native A\\n(vivant)" as NA
participant "Native B\\n(réseau instable)" as NB

note over Caller: StaticNatives = [NA, NB]\\nHeartbeats actifs vers NA et NB

== Panne réseau transitoire vers NB ==
NB ->x Caller: stream reset (timeout réseau)

Caller -> Caller: AfterDelete(NB)\\nStaticNatives = [NA]\\nlostNatives.Store(NB.addr)

== replenishNativesFromPeers — phase 1 ==
Caller -> NA: GET /opencloud/native/peers/1.0
NA --> Caller: GetPeersResponse{Peers:[NB]}

note over Caller: NB connu de NA, tentative de reconnexion directe

Caller -> NB: dial (échec — réseau toujours coupé)
note over Caller: Connexion impossible.\\nPassage en retryLostNative()

== retryLostNative : ticker 30s ==
loop toutes les 30s tant que NB absent
    Caller -> Caller: retryLostNative()\\nParcourt lostNatives
    Caller -> NB: StartNativeRegistration (dial + heartbeat + subscribe)
    NB --> Caller: dial échoue
    note over Caller: Retry loggé. Prochain essai dans 30s.
end

== Réseau rétabli ==
note over NB: Réseau rétabli\\nNB de nouveau joignable

Caller -> NB: StartNativeRegistration\\ndial (succès)
Caller -> NB: SendHeartbeat /opencloud/heartbeat/1.0 (goroutine longue durée)
Caller -> NB: /opencloud/native/subscribe/1.0\\nIndexerRegistration{FillRate: fillRateFn()}

NB --> Caller: subscribe ack

Caller -> Caller: lostNatives.Delete(NB.addr)\\nStaticNatives = [NA, NB] restauré

note over Caller: Mode nominal retrouvé.\\nnativeHeartbeatOnce non utilisé (goroutine déjà active pour NA).\\nNouvelle goroutine SendHeartbeat pour NB uniquement.

@enduml
