package session import ( "sync" "sync/atomic" "time" "realtime-gateway/internal/model" ) type Session struct { ID string Role model.Role Authenticated bool ChannelID string Subscriptions []model.Subscription CreatedAt time.Time } type Snapshot struct { ID string `json:"id"` Role model.Role `json:"role"` Authenticated bool `json:"authenticated"` ChannelID string `json:"channelId,omitempty"` CreatedAt time.Time `json:"createdAt"` Subscriptions []model.Subscription `json:"subscriptions"` } type Manager struct { mu sync.RWMutex sequence atomic.Uint64 sessions map[string]*Session } func NewManager() *Manager { return &Manager{ sessions: make(map[string]*Session), } } func (m *Manager) Create() *Session { id := m.sequence.Add(1) session := &Session{ ID: formatSessionID(id), Role: model.RoleConsumer, CreatedAt: time.Now(), } m.mu.Lock() m.sessions[session.ID] = session m.mu.Unlock() return session } func (m *Manager) Delete(sessionID string) { m.mu.Lock() delete(m.sessions, sessionID) m.mu.Unlock() } func (m *Manager) Get(sessionID string) (*Session, bool) { m.mu.RLock() defer m.mu.RUnlock() session, ok := m.sessions[sessionID] return session, ok } func (m *Manager) Count() int { m.mu.RLock() defer m.mu.RUnlock() return len(m.sessions) } func (m *Manager) List() []Snapshot { m.mu.RLock() defer m.mu.RUnlock() snapshots := make([]Snapshot, 0, len(m.sessions)) for _, current := range m.sessions { subscriptions := append([]model.Subscription(nil), current.Subscriptions...) snapshots = append(snapshots, Snapshot{ ID: current.ID, Role: current.Role, Authenticated: current.Authenticated, ChannelID: current.ChannelID, CreatedAt: current.CreatedAt, Subscriptions: subscriptions, }) } return snapshots } func formatSessionID(id uint64) string { return "sess-" + itoa(id) } func itoa(v uint64) string { if v == 0 { return "0" } var buf [20]byte i := len(buf) for v > 0 { i-- buf[i] = byte('0' + v%10) v /= 10 } return string(buf[i:]) }