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

119 lines
2.3 KiB
Go

package app
import (
"strings"
"time"
)
func (r *transportHealthRefresher) syncKnownClients(items []TransportClient) {
r.mu.Lock()
defer r.mu.Unlock()
known := make(map[string]struct{}, len(items))
for _, it := range items {
id := strings.TrimSpace(it.ID)
if id == "" {
continue
}
known[id] = struct{}{}
entry := r.entries[id]
if entry == nil {
entry = &transportHealthRefreshEntry{
swr: newRefreshCoordinator(
transportHealthFreshTTL,
transportHealthBackoffMin,
transportHealthBackoffMax,
),
}
r.entries[id] = entry
}
if ts, ok := parseTransportHealthLastCheck(it); ok {
entry.swr.setUpdatedAt(ts)
}
}
for id := range r.entries {
if _, ok := known[id]; !ok {
delete(r.entries, id)
}
}
}
func (r *transportHealthRefresher) begin(item TransportClient, force bool, now time.Time) bool {
id := strings.TrimSpace(item.ID)
if id == "" {
return false
}
r.mu.Lock()
defer r.mu.Unlock()
entry := r.entries[id]
if entry == nil {
entry = &transportHealthRefreshEntry{
swr: newRefreshCoordinator(
transportHealthFreshTTL,
transportHealthBackoffMin,
transportHealthBackoffMax,
),
}
r.entries[id] = entry
}
if ts, ok := parseTransportHealthLastCheck(item); ok {
entry.swr.setUpdatedAt(ts)
}
hasData := strings.TrimSpace(item.Health.LastCheck) != ""
return entry.swr.beginRefresh(now, force, hasData)
}
func (r *transportHealthRefresher) finishSuccess(id string, now time.Time) {
id = strings.TrimSpace(id)
if id == "" {
return
}
r.mu.Lock()
defer r.mu.Unlock()
entry := r.entries[id]
if entry == nil {
return
}
entry.swr.finishSuccess(now)
}
func (r *transportHealthRefresher) finishError(id, msg string, now time.Time) {
id = strings.TrimSpace(id)
if id == "" {
return
}
r.mu.Lock()
defer r.mu.Unlock()
entry := r.entries[id]
if entry == nil {
return
}
entry.swr.finishError(msg, now)
}
func (r *transportHealthRefresher) acquire() {
r.sem <- struct{}{}
}
func (r *transportHealthRefresher) release() {
select {
case <-r.sem:
default:
}
}
func parseTransportHealthLastCheck(item TransportClient) (time.Time, bool) {
ts := strings.TrimSpace(item.Health.LastCheck)
if ts == "" {
return time.Time{}, false
}
t, err := time.Parse(time.RFC3339, ts)
if err != nil {
return time.Time{}, false
}
return t, true
}