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 }