converge/pkg/models/state.go
2024-08-16 00:41:04 +02:00

98 lines
2.4 KiB
Go

package models
import (
"git.wamblee.org/converge/pkg/comms"
"sort"
"sync/atomic"
"time"
)
type RendezVousId string
type AgentGuid string
type ClientGuid string
type ClientId string
type SessionType string
type RemoteAddr string
type Agent struct {
Guid AgentGuid
RemoteAddr RemoteAddr
PublicId RendezVousId
StartTime time.Time
EnvironmentInfo comms.EnvironmentInfo
expiryTime int64
}
func (agent *Agent) SetExpiryTime(t time.Time) {
atomic.StoreInt64(&agent.expiryTime, t.UnixNano())
}
func (agent *Agent) GetExpiryTime() time.Time {
t := atomic.LoadInt64(&agent.expiryTime)
return time.Unix(0, t)
}
type Client struct {
Guid ClientGuid
RemoteAddr RemoteAddr
PublicId RendezVousId
ClientId ClientId
AgentGuid AgentGuid
StartTime time.Time
SessionType SessionType
EnvironmentInfo comms.EnvironmentInfo
}
// State is a description of the current state of converge.
// Created by the matchmaker and used for updating the web client
// and prometheus metrics.
//
// Concurrency design:
// 1. State is immutable
// 2. The MatchMaker uses copy-on-write and never modifies a state directly.
// 3. the matchmaker modifies the expiry time of the agent. This is dealt with using the
// sync/atomic package by storing the expiry time as an int64 using time.Time.UnixNano()
type State struct {
Agents map[AgentGuid]*Agent
Clients map[ClientGuid]*Client
}
func NewState() *State {
return &State{
Agents: make(map[AgentGuid]*Agent),
Clients: make(map[ClientGuid]*Client),
}
}
// for copy on write
func (state *State) Copy() *State {
res := NewState()
for k, v := range state.Agents {
res.Agents[k] = v
}
for k, v := range state.Clients {
res.Clients[k] = v
}
return res
}
// Return agents and clients slices sorted on starttime ascending.
func (state *State) Slices() ([]*Agent, []*Client) {
agents := make([]*Agent, 0, len(state.Agents))
clients := make([]*Client, 0, len(state.Clients))
for _, agent := range state.Agents {
agents = append(agents, agent)
}
for _, client := range state.Clients {
clients = append(clients, client)
}
sort.Slice(agents, func(i int, j int) bool {
return agents[i].StartTime.Before(agents[j].StartTime)
})
sort.Slice(clients, func(i int, j int) bool {
return clients[i].StartTime.Before(clients[j].StartTime)
})
return agents, clients
}