-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy patheventhandler.go
142 lines (119 loc) · 2.77 KB
/
eventhandler.go
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
package sseio
import (
"errors"
"sync"
)
// EventHandler interface
type EventHandler interface {
SendMessage(roomId string, message interface{})
addClientToRoom(roomId string, clientId string)
removeClientFromRoom(roomId string, clientId string)
}
type room struct {
lock sync.RWMutex
clients map[string]interface{}
}
// HandlerOptions defines option functions to configure the eventHandler.
type HandlerOptions func(e *eventHandler)
// SetFetchFunc will be triggered once a client is connected.
// And the returned data will be send to the client, and nil data will be ignored.
//
// It's optional.
func SetFetchFunc(fetch fetch) HandlerOptions {
return func(e *eventHandler) {
e.fetch = fetch
}
}
// SetGetRoomIdFunc sets the getRoomId function to determine
// which room the incoming client belongs to.
//
// It's required!
func SetGetRoomIdFunc(getRoomId getRoomId) HandlerOptions {
return func(e *eventHandler) {
e.getRoomId = getRoomId
}
}
func enableHandlerEvent(eventChan chan Event) HandlerOptions {
return func(e *eventHandler) {
e.eventEnable = true
e.eventChan = eventChan
}
}
type eventHandler struct {
eventEnable bool
event string
eventChan chan Event
rooms sync.Map
manager *manager
getRoomId getRoomId
fetch fetch
}
// NewEventHandler will return pointer to eventHandler
func NewEventHandler(event string, manager *manager, opts ...HandlerOptions) (EventHandler, error) {
e := &eventHandler{
event: event,
manager: manager,
}
for _, opt := range opts {
opt(e)
}
if e.getRoomId == nil {
return nil, errors.New("HandlerOptions \"GetRoomId\" is required")
}
return e, nil
}
// SendMessage sends data to all the clients in room
func (e *eventHandler) SendMessage(roomId string, data interface{}) {
v, ok := e.rooms.Load(roomId)
if !ok {
return
}
if data == nil {
return
}
room := v.(*room)
room.lock.RLock()
for clientId := range room.clients {
client := e.manager.getClient(clientId)
if client != nil {
client.sendMessage(e.event, data)
}
}
room.lock.RUnlock()
}
func (e *eventHandler) addClientToRoom(roomId string, clientId string) {
v, ok := e.rooms.LoadOrStore(roomId, &room{
clients: map[string]interface{}{
clientId: nil,
},
})
if !ok {
if e.eventEnable {
e.eventChan <- &RoomCreateEvent{
RoomId: roomId,
}
}
return
}
room := v.(*room)
room.lock.Lock()
room.clients[clientId] = nil
room.lock.Unlock()
}
func (e *eventHandler) removeClientFromRoom(roomId string, clientId string) {
v, ok := e.rooms.Load(roomId)
if ok {
room := v.(*room)
room.lock.Lock()
delete(room.clients, clientId)
if len(room.clients) == 0 {
e.rooms.Delete(roomId)
if e.eventEnable {
e.eventChan <- &RoomEmptyEvent{
RoomId: roomId,
}
}
}
room.lock.Unlock()
}
}