-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsessions.go
More file actions
149 lines (119 loc) · 3.66 KB
/
sessions.go
File metadata and controls
149 lines (119 loc) · 3.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package neogate
import (
"slices"
"sync"
"github.com/gofiber/websocket/v2"
)
// Used to provide information for session creation
type SessionInfo[T any] struct {
UserId string // Identifier of the user
sessionId string // Identifier of this user session
Data T // Session data you can decide how to fill
}
// Convert the session information to a session that can be used by neogate.
func (sessionInfo SessionInfo[T]) toSession(conn *websocket.Conn) *Session[T] {
return &Session[T]{
conn: conn,
userId: sessionInfo.UserId,
sessionId: sessionInfo.sessionId,
data: sessionInfo.Data,
wsMutex: &sync.Mutex{},
dataMutex: &sync.RWMutex{},
}
}
type Session[T any] struct {
conn *websocket.Conn
userId string
sessionId string
data T
dataMutex *sync.RWMutex
wsMutex *sync.Mutex
}
func (session *Session[T]) GetData() T {
session.dataMutex.RLock()
defer session.dataMutex.RUnlock()
return session.data
}
func (session *Session[T]) SetData(data T) {
session.dataMutex.Lock()
defer session.dataMutex.Unlock()
session.data = data
}
func (session *Session[T]) GetUserId() string {
return session.userId
}
func (session *Session[T]) GetSessionId() string {
return session.sessionId
}
func (instance *Instance[T]) addSession(session *Session[T]) {
// Add the session
_, loaded := instance.connectionsCache.LoadOrStore(getKey(session.userId, session.sessionId), session)
// If the session is not yet added, make sure to add it to the list
if !loaded {
instance.createSession(session)
}
}
func getKey(id string, session string) string {
return id + ":" + session
}
func (instance *Instance[T]) createSession(session *Session[T]) {
_, sessionAdapterName := instance.Config.SessionAdapterHandler(session.GetUserId(), session.GetSessionId())
instance.Adapt(CreateAction{
ID: sessionAdapterName,
OnEvent: func(c *AdapterContext) error {
if err := instance.sendToSessionWS(session, c.Message); err != nil {
instance.ReportSessionError(session, "couldn't send received message", err)
return err
}
return nil
},
// Disconnect the user on error
OnError: func(err error) {
instance.RemoveAdapter(sessionAdapterName)
},
})
sessionList := &SessionsList{
mutex: &sync.RWMutex{},
sessions: []string{session.GetSessionId()},
}
sessionAny, loaded := instance.sessions.LoadOrStore(session.GetUserId(), sessionList)
if loaded {
sessionList = sessionAny.(*SessionsList)
}
sessionList.mutex.Lock()
defer sessionList.mutex.Unlock()
if loaded {
sessionList.sessions = append(sessionList.sessions, session.GetSessionId())
}
instance.sessions.Store(session.GetUserId(), sessionList) // Store here in case the thing was deleted while the mutex was locked
}
func (instance *Instance[T]) removeSession(userId string, session string) {
// Remove adapter for session
_, sessionAdapter := instance.Config.SessionAdapterHandler(userId, session)
instance.RemoveAdapter(sessionAdapter)
sessionAny, ok := instance.sessions.Load(userId)
if !ok {
return
}
sessionList := sessionAny.(*SessionsList)
sessionList.mutex.Lock()
defer sessionList.mutex.Unlock()
sessionList.sessions = slices.DeleteFunc(sessionList.sessions, func(s string) bool {
return s == session
})
if len(sessionList.sessions) == 0 {
instance.sessions.Delete(userId)
}
}
func (instance *Instance[T]) GetSessions(userId string) []string {
sessionListAny, ok := instance.sessions.Load(userId)
if !ok {
return []string{}
}
sessionList := sessionListAny.(*SessionsList)
sessionList.mutex.RLock()
sessionIds := make([]string, len(sessionList.sessions))
copy(sessionIds, sessionList.sessions)
sessionList.mutex.RUnlock()
return sessionIds
}