Files
elmprodvpn/selective-vpn-api/app/transport_health_refresh_probe.go

82 lines
1.9 KiB
Go

package app
import (
"strings"
"time"
)
func transportRunHealthProbe(clientID string) {
id := strings.TrimSpace(clientID)
if id == "" {
return
}
transportHealthSWR.acquire()
defer transportHealthSWR.release()
now := time.Now().UTC()
transportMu.Lock()
st := loadTransportClientsState()
idx := findTransportClientIndex(st.Items, id)
if idx < 0 {
transportMu.Unlock()
transportHealthSWR.finishError(id, "client not found", now)
return
}
prev := st.Items[idx]
transportMu.Unlock()
backend := selectTransportBackend(prev)
probe := backend.Health(prev)
backendID := backend.ID()
transportMu.Lock()
st = loadTransportClientsState()
idx = findTransportClientIndex(st.Items, id)
if idx < 0 {
transportMu.Unlock()
transportHealthSWR.finishError(id, "client not found", now)
return
}
prev = st.Items[idx]
next := applyTransportHealthProbeSnapshot(prev, backendID, probe, now)
healthChanged := transportHealthChanged(prev, next)
persist := transportShouldPersistHealthSnapshot(prev, next, now)
if persist {
st.Items[idx] = next
if err := saveTransportClientsState(st); err != nil {
transportMu.Unlock()
transportHealthSWR.finishError(id, "save failed: "+err.Error(), now)
return
}
}
transportMu.Unlock()
if healthChanged {
events.push("transport_client_health_changed", map[string]any{
"id": id,
"status": next.Status,
"latency_ms": next.Health.LatencyMS,
"last_error": strings.TrimSpace(next.Health.LastError),
"last_check": strings.TrimSpace(next.Health.LastCheck),
})
publishTransportRuntimeObservabilitySnapshotChanged(
"transport_client_health_changed",
[]string{id},
nil,
)
}
if probe.OK {
transportHealthSWR.finishSuccess(id, now)
return
}
msg := strings.TrimSpace(probe.Message)
if msg == "" {
msg = "transport health probe failed"
}
transportHealthSWR.finishError(id, msg, now)
}