termd/internal/session/registry.go
2026-07-02 22:13:49 -03:00

68 lines
1.4 KiB
Go

package session
import (
"crypto/rand"
"encoding/hex"
"fmt"
"sort"
"sync"
)
// Registry is the daemon's set of live sessions.
type Registry struct {
mu sync.RWMutex
sessions map[string]*Session
}
func NewRegistry() *Registry {
return &Registry{sessions: make(map[string]*Session)}
}
// Create starts a new session and registers it under a fresh ID.
func (r *Registry) Create(opts Options) (*Session, error) {
r.mu.Lock()
defer r.mu.Unlock()
var id string
for {
b := make([]byte, 3)
if _, err := rand.Read(b); err != nil {
return nil, fmt.Errorf("generating session id: %w", err)
}
id = hex.EncodeToString(b)
if _, taken := r.sessions[id]; !taken {
break
}
}
s, err := New(id, opts)
if err != nil {
return nil, err
}
r.sessions[id] = s
return s, nil
}
// Get returns the session or nil.
func (r *Registry) Get(id string) *Session {
r.mu.RLock()
defer r.mu.RUnlock()
return r.sessions[id]
}
// List returns all sessions sorted by ID.
func (r *Registry) List() []*Session {
r.mu.RLock()
defer r.mu.RUnlock()
out := make([]*Session, 0, len(r.sessions))
for _, s := range r.sessions {
out = append(out, s)
}
sort.Slice(out, func(i, j int) bool { return out[i].ID < out[j].ID })
return out
}
// Remove unregisters a session (the caller is responsible for Kill).
func (r *Registry) Remove(id string) {
r.mu.Lock()
defer r.mu.Unlock()
delete(r.sessions, id)
}