Add Len() to fetch number of connected sessions. Close #16.
This commit is contained in:
@@ -1,3 +1,7 @@
|
|||||||
|
## 2017-01-20
|
||||||
|
|
||||||
|
* Add `Len()` to fetch number of connected sessions.
|
||||||
|
|
||||||
## 2016-12-09
|
## 2016-12-09
|
||||||
|
|
||||||
* Add metadata management for sessions.
|
* Add metadata management for sessions.
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package melody
|
package melody
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
type hub struct {
|
type hub struct {
|
||||||
sessions map[*Session]bool
|
sessions map[*Session]bool
|
||||||
broadcast chan *envelope
|
broadcast chan *envelope
|
||||||
@@ -7,6 +11,7 @@ type hub struct {
|
|||||||
unregister chan *Session
|
unregister chan *Session
|
||||||
exit chan bool
|
exit chan bool
|
||||||
open bool
|
open bool
|
||||||
|
rwmutex *sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func newHub() *hub {
|
func newHub() *hub {
|
||||||
@@ -17,6 +22,7 @@ func newHub() *hub {
|
|||||||
unregister: make(chan *Session),
|
unregister: make(chan *Session),
|
||||||
exit: make(chan bool),
|
exit: make(chan bool),
|
||||||
open: true,
|
open: true,
|
||||||
|
rwmutex: &sync.RWMutex{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,14 +31,19 @@ loop:
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case s := <-h.register:
|
case s := <-h.register:
|
||||||
|
h.rwmutex.Lock()
|
||||||
h.sessions[s] = true
|
h.sessions[s] = true
|
||||||
|
h.rwmutex.Unlock()
|
||||||
case s := <-h.unregister:
|
case s := <-h.unregister:
|
||||||
if _, ok := h.sessions[s]; ok {
|
if _, ok := h.sessions[s]; ok {
|
||||||
|
h.rwmutex.Lock()
|
||||||
delete(h.sessions, s)
|
delete(h.sessions, s)
|
||||||
s.conn.Close()
|
s.conn.Close()
|
||||||
close(s.output)
|
close(s.output)
|
||||||
|
h.rwmutex.Unlock()
|
||||||
}
|
}
|
||||||
case m := <-h.broadcast:
|
case m := <-h.broadcast:
|
||||||
|
h.rwmutex.RLock()
|
||||||
for s := range h.sessions {
|
for s := range h.sessions {
|
||||||
if m.filter != nil {
|
if m.filter != nil {
|
||||||
if m.filter(s) {
|
if m.filter(s) {
|
||||||
@@ -42,14 +53,24 @@ loop:
|
|||||||
s.writeMessage(m)
|
s.writeMessage(m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
h.rwmutex.RUnlock()
|
||||||
case <-h.exit:
|
case <-h.exit:
|
||||||
|
h.rwmutex.Lock()
|
||||||
for s := range h.sessions {
|
for s := range h.sessions {
|
||||||
delete(h.sessions, s)
|
delete(h.sessions, s)
|
||||||
s.conn.Close()
|
s.conn.Close()
|
||||||
close(s.output)
|
close(s.output)
|
||||||
}
|
}
|
||||||
h.open = false
|
h.open = false
|
||||||
|
h.rwmutex.Unlock()
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *hub) len() int {
|
||||||
|
h.rwmutex.RLock()
|
||||||
|
defer h.rwmutex.RUnlock()
|
||||||
|
|
||||||
|
return len(h.sessions)
|
||||||
|
}
|
||||||
|
|||||||
@@ -153,3 +153,8 @@ func (m *Melody) BroadcastBinaryOthers(msg []byte, s *Session) {
|
|||||||
func (m *Melody) Close() {
|
func (m *Melody) Close() {
|
||||||
m.hub.exit <- true
|
m.hub.exit <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Len return the number of connected sessions.
|
||||||
|
func (m *Melody) Len() int {
|
||||||
|
return m.hub.len()
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package melody
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -79,6 +80,51 @@ func TestEcho(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLen(t *testing.T) {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
|
connect := int(rand.Int31n(1000))
|
||||||
|
disconnect := rand.Float32()
|
||||||
|
conns := make([]*websocket.Conn, connect)
|
||||||
|
defer func() {
|
||||||
|
for _, conn := range conns {
|
||||||
|
if conn != nil {
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
echo := NewTestServerHandler(func(session *Session, msg []byte) {})
|
||||||
|
server := httptest.NewServer(echo)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
disconnected := 0
|
||||||
|
for i := 0; i < connect; i++ {
|
||||||
|
conn, err := NewDialer(server.URL)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rand.Float32() < disconnect {
|
||||||
|
conns[i] = nil
|
||||||
|
disconnected += 1
|
||||||
|
conn.Close()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
conns[i] = conn
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
|
|
||||||
|
connected := connect - disconnected
|
||||||
|
|
||||||
|
if echo.m.Len() != connected {
|
||||||
|
t.Errorf("melody len %d should equal %d", echo.m.Len(), connected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestEchoBinary(t *testing.T) {
|
func TestEchoBinary(t *testing.T) {
|
||||||
echo := NewTestServer()
|
echo := NewTestServer()
|
||||||
echo.m.HandleMessageBinary(func(session *Session, msg []byte) {
|
echo.m.HandleMessageBinary(func(session *Session, msg []byte) {
|
||||||
|
|||||||
Reference in New Issue
Block a user