The matchmaker uses copy on write every time a new agent or client connects or disconnects.
81 lines
1.9 KiB
Go
81 lines
1.9 KiB
Go
package models
|
|
|
|
import (
|
|
"git.wamblee.org/converge/pkg/comms"
|
|
"git.wamblee.org/converge/pkg/support/collections"
|
|
"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 *collections.LinkedMap[AgentGuid, *Agent]
|
|
Clients *collections.LinkedMap[ClientGuid, *Client]
|
|
}
|
|
|
|
func NewState() *State {
|
|
return &State{
|
|
Agents: collections.NewLinkedMap[AgentGuid, *Agent](),
|
|
Clients: collections.NewLinkedMap[ClientGuid, *Client](),
|
|
}
|
|
}
|
|
|
|
// for copy on write
|
|
func (state *State) Copy() *State {
|
|
res := NewState()
|
|
for entry := range state.Agents.RangeEntries() {
|
|
res.Agents.Put(entry.Key, entry.Value)
|
|
}
|
|
for entry := range state.Clients.RangeEntries() {
|
|
res.Clients.Put(entry.Key, entry.Value)
|
|
}
|
|
return res
|
|
}
|