Files
go-sip/cmd/sip-go-agent/dispatcher_session.go
T

61 lines
2.2 KiB
Go

package main
import (
"context"
"errors"
"fmt"
"log/slog"
"time"
"git.ipao.vip/rogee/go-sip/internal/dispatcher"
)
// maintainAgentSession renews before the ten-minute Agent session expires.
// A failed or invalid renewal stops admission rather than using the old lease.
func maintainAgentSession(ctx context.Context, active dispatcher.AgentSession, before time.Duration, renew func(context.Context, dispatcher.AgentSession) (dispatcher.AgentSession, error)) error {
if ctx == nil || renew == nil || before <= 0 {
return errors.New("Agent session renewal requires a context, interval and renewal operation")
}
for {
if ctx.Err() != nil {
return nil
}
if active.ExpiresAtUnixMs <= time.Now().UnixMilli() {
return fmt.Errorf("Agent %s session generation %d expired before renewal", active.AgentID, active.SessionGeneration)
}
wait := time.Until(time.UnixMilli(active.ExpiresAtUnixMs).Add(-before))
if wait < 0 {
wait = 0
}
timer := time.NewTimer(wait)
select {
case <-ctx.Done():
timer.Stop()
return nil
case <-timer.C:
}
if ctx.Err() != nil {
return nil
}
if active.ExpiresAtUnixMs <= time.Now().UnixMilli() {
return fmt.Errorf("Agent %s session generation %d expired before renewal", active.AgentID, active.SessionGeneration)
}
requestCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
next, err := renew(requestCtx, active)
cancel()
if err != nil {
if ctx.Err() != nil {
return nil
}
return fmt.Errorf("renew Agent %s session generation %d: %w", active.AgentID, active.SessionGeneration, err)
}
if next.AgentID != active.AgentID || next.CellID != active.CellID || next.BootID != active.BootID ||
next.DispatcherEpoch != active.DispatcherEpoch || next.SessionGeneration <= active.SessionGeneration ||
next.ExpiresAtUnixMs <= active.ExpiresAtUnixMs || next.ExpiresAtUnixMs <= time.Now().Add(before).UnixMilli() {
return fmt.Errorf("Agent %s session generation %d renewal returned no usable session", active.AgentID, active.SessionGeneration)
}
slog.Info("Agent session renewed", "agent_id", next.AgentID, "session_generation", next.SessionGeneration, "expires_at_unix_ms", next.ExpiresAtUnixMs)
active = next
}
}