From 3574b64842e7c3fc7ce8ef13afd47bef486ec891 Mon Sep 17 00:00:00 2001 From: Erik Brakkee Date: Fri, 16 Aug 2024 00:25:17 +0200 Subject: [PATCH] Server side sorting for the websessions page. No longer using LinkedMap as a result. --- cmd/converge/pagehandler.go | 2 +- cmd/converge/prometheus.go | 4 ++-- cmd/templaterender/render.go | 10 ++++---- pkg/models/state.go | 36 +++++++++++++++++++++------- pkg/server/admin/admin.go | 10 ++++---- pkg/server/matchmaker/matchmaker.go | 4 ++-- pkg/server/matchmaker/websessions.go | 3 ++- pkg/server/templates/sessions.templ | 20 ++++++++-------- 8 files changed, 55 insertions(+), 34 deletions(-) diff --git a/cmd/converge/pagehandler.go b/cmd/converge/pagehandler.go index cf48c88..f7cb909 100644 --- a/cmd/converge/pagehandler.go +++ b/cmd/converge/pagehandler.go @@ -21,7 +21,7 @@ func pageHandler(w http.ResponseWriter, r *http.Request) { case "downloads.html": templates2.DownloadsTab().Render(r.Context(), w) case "sessions.html": - templates2.SessionsTab(nil, access.Location).Render(r.Context(), w) + templates2.SessionsTab(nil, nil, access.Location).Render(r.Context(), w) default: http.NotFound(w, r) } diff --git a/cmd/converge/prometheus.go b/cmd/converge/prometheus.go index 335ab31..53c69af 100644 --- a/cmd/converge/prometheus.go +++ b/cmd/converge/prometheus.go @@ -24,10 +24,10 @@ func NewPrometheusState(state *models.State) *PrometheusState { agents: collections.NewLinkedMap[models.AgentGuid, *models.Agent](), clients: collections.NewLinkedMap[models.ClientGuid, *models.Client](), } - for agent := range state.Agents.RangeValues() { + for _, agent := range state.Agents { res.agents.Put(agent.Guid, agent) } - for client := range state.Clients.RangeValues() { + for _, client := range state.Clients { res.clients.Put(client.Guid, client) } return &res diff --git a/cmd/templaterender/render.go b/cmd/templaterender/render.go index bcffddb..472f809 100644 --- a/cmd/templaterender/render.go +++ b/cmd/templaterender/render.go @@ -70,7 +70,7 @@ func main() { render(dir, "downloads.html", templates2.Downloads) render(dir, "sessions-none.html", func() templ.Component { - return templates2.SessionsTab(nil, netherlands) + return templates2.SessionsTab(nil, nil, netherlands) }) render(dir, "sessions.html", func() templ.Component { @@ -94,7 +94,7 @@ func main() { }, } agent.SetExpiryTime(time.Now().In(japan).Add(10 * time.Minute)) - state.Agents.Put(agent.Guid, &agent) + state.Agents[agent.Guid] = &agent client := models.Client{ Guid: models.ClientGuid(strconv.Itoa(rand.Int())), RemoteAddr: models.RemoteAddr("10.1.3.3"), @@ -104,7 +104,9 @@ func main() { StartTime: time.Now().In(japan), SessionType: models.SessionType("sftp"), } - state.Clients.Put(client.Guid, &client) - return templates2.SessionsTab(state, netherlands) + state.Clients[client.Guid] = &client + + agents, clients := state.Slices() + return templates2.SessionsTab(agents, clients, netherlands) }) } diff --git a/pkg/models/state.go b/pkg/models/state.go index 8d0c269..8fefd8e 100644 --- a/pkg/models/state.go +++ b/pkg/models/state.go @@ -2,7 +2,7 @@ package models import ( "git.wamblee.org/converge/pkg/comms" - "git.wamblee.org/converge/pkg/support/collections" + "sort" "sync/atomic" "time" ) @@ -56,25 +56,43 @@ type Client struct { // 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] + Agents map[AgentGuid]*Agent + Clients map[ClientGuid]*Client } func NewState() *State { return &State{ - Agents: collections.NewLinkedMap[AgentGuid, *Agent](), - Clients: collections.NewLinkedMap[ClientGuid, *Client](), + Agents: make(map[AgentGuid]*Agent), + Clients: make(map[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 k, v := range state.Agents { + res.Agents[k] = v } - for entry := range state.Clients.RangeEntries() { - res.Clients.Put(entry.Key, entry.Value) + 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 +} diff --git a/pkg/server/admin/admin.go b/pkg/server/admin/admin.go index 9043cee..97dd57e 100644 --- a/pkg/server/admin/admin.go +++ b/pkg/server/admin/admin.go @@ -140,7 +140,7 @@ func (admin *Admin) AddAgent(publicId models.RendezVousId, agentInfo comms.Envir agent := newAgent(commChannel, publicId, agentInfo) admin.state = admin.state.Copy() - admin.state.Agents.Put(agent.Info.Guid, agent.Info) + admin.state.Agents[agent.Info.Guid] = agent.Info admin.agents[publicId] = agent return agent, nil } @@ -175,7 +175,7 @@ func (admin *Admin) AddClient(publicId models.RendezVousId, clientConn iowrapper } admin.state = admin.state.Copy() - admin.state.Clients.Put(client.Info.Guid, client.Info) + admin.state.Clients[client.Info.Guid] = client.Info admin.clients[client.Info.ClientId] = client return client, nil } @@ -206,7 +206,7 @@ func (admin *Admin) RemoveAgent(publicId models.RendezVousId) error { log.Printf("Could not close yamux client session for '%s'\n", publicId) } admin.state = admin.state.Copy() - admin.state.Agents.Delete(agent.Info.Guid) + delete(admin.state.Agents, agent.Info.Guid) delete(admin.agents, publicId) return nil } @@ -222,7 +222,7 @@ func (admin *Admin) RemoveClient(client *clientConnection) error { _ = client.clientConnection.Close() admin.state = admin.state.Copy() - admin.state.Clients.Delete(client.Info.Guid) + delete(admin.state.Clients, client.Info.Guid) delete(admin.clients, client.Info.ClientId) return nil } @@ -230,7 +230,7 @@ func (admin *Admin) RemoveClient(client *clientConnection) error { func (admin *Admin) SetSessionType(clientId models.ClientId, sessionType models.SessionType) { admin.mutex.Lock() defer admin.mutex.Unlock() - for client := range admin.state.Clients.RangeValues() { + for _, client := range admin.state.Clients { if client.ClientId == clientId { client.SessionType = sessionType break diff --git a/pkg/server/matchmaker/matchmaker.go b/pkg/server/matchmaker/matchmaker.go index ba8c292..b243fcf 100644 --- a/pkg/server/matchmaker/matchmaker.go +++ b/pkg/server/matchmaker/matchmaker.go @@ -134,7 +134,7 @@ func logStatusImpl(admin *models.State, notifier Notifier) { lines = append(lines, fmt.Sprintf(format, "AGENT", "ACTIVE_SINCE", "EXPIRY_TIME", "USER", "HOST", "OS")) - for agent := range admin.Agents.RangeValues() { + for _, agent := range admin.Agents { lines = append(lines, fmt.Sprintf(format, agent.PublicId, agent.StartTime.Format(time.DateTime), agent.GetExpiryTime().Format(time.DateTime), @@ -145,7 +145,7 @@ func logStatusImpl(admin *models.State, notifier Notifier) { lines = append(lines, "") format = "%-10s %-20s %-20s %-20s %-20s" lines = append(lines, fmt.Sprintf(format, "CLIENT", "AGENT", "ACTIVE_SINCE", "REMOTE_ADDRESS", "SESSION_TYPE")) - for client := range admin.Clients.RangeValues() { + for _, client := range admin.Clients { lines = append(lines, fmt.Sprintf(format, client.ClientId, client.PublicId, diff --git a/pkg/server/matchmaker/websessions.go b/pkg/server/matchmaker/websessions.go index ba9a3b6..64708dd 100644 --- a/pkg/server/matchmaker/websessions.go +++ b/pkg/server/matchmaker/websessions.go @@ -137,7 +137,8 @@ func (session *WebSession) WriteNotifications(location *time.Location, ctx conte } func (session *WebSession) writeNotificationToClient(location *time.Location, notification *models.State) bool { - err := templates.State(notification, location).Render(context.Background(), session.conn) + agents, clients := notification.Slices() + err := templates.State(agents, clients, location).Render(context.Background(), session.conn) if err != nil { log.Printf("WS connection closed: %v", err) return false diff --git a/pkg/server/templates/sessions.templ b/pkg/server/templates/sessions.templ index f8e7937..9385c48 100644 --- a/pkg/server/templates/sessions.templ +++ b/pkg/server/templates/sessions.templ @@ -7,7 +7,7 @@ import ( ) -templ Sessions(state *models.State, loc *time.Location) { +templ Sessions(agents []*models.Agent, clients []*models.Client, loc *time.Location) {
sessions
- if state != nil { - @State(state, loc) + if len(agents) > 0 { + @State(agents, clients, loc) } else { Loading... } @@ -26,12 +26,12 @@ templ Sessions(state *models.State, loc *time.Location) { } -templ State(state *models.State, location *time.Location) { +templ State(agents []*models.Agent, clients []*models.Client, location *time.Location) {

agents

- if state.Agents.Len() == 0 { + if len(agents) == 0 {

-

} else { @@ -46,7 +46,7 @@ templ State(state *models.State, location *time.Location) { - for agent := range state.Agents.RangeValues() { + for _, agent := range agents { @@ -64,7 +64,7 @@ templ State(state *models.State, location *time.Location) {

clients

- if state.Clients.Len() == 0 { + if len(clients) == 0 {

-

} else {
shell
{string(agent.PublicId)} {agent.StartTime.In(location).Format(time.DateTime)}
@@ -80,7 +80,7 @@ templ State(state *models.State, location *time.Location) { - for client := range state.Clients.RangeValues() { + for _, client := range clients { @@ -98,8 +98,8 @@ templ State(state *models.State, location *time.Location) { } -templ SessionsTab(state *models.State, loc *time.Location) { +templ SessionsTab(agents []*models.Agent, clients []*models.Client, loc *time.Location) { @BasePage(4) { - @Sessions(state, loc) + @Sessions(agents, clients, loc) } }
shell
{string(client.ClientId)} {client.StartTime.In(location).Format(time.DateTime)}