converge/pkg/models/state.go

99 lines
2.3 KiB
Go

package models
import (
"git.wamblee.org/converge/pkg/comms"
"sort"
"sync/atomic"
"time"
)
// Concurrency design:
// 1. State is immutable
// 2. The MatchMakers 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 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
// TODO add remote address.
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 server and used for updating the web client
// and prometheus metrics.
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
}
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
}