Change semantics of *WSUser to fix potential bugs, make it easier to test, to release memory more eagerly, and to make it faster.
Add CountSockets() method to *WSUser
This commit is contained in:
parent
e839bc5f2c
commit
97f411e02e
|
@ -23,16 +23,36 @@ type WSUserSocket struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *WSUser) Ping() error {
|
func (u *WSUser) Ping() error {
|
||||||
for _, socket := range u.Sockets {
|
var sockets []*WSUserSocket
|
||||||
if socket == nil {
|
var del int
|
||||||
continue
|
func() {
|
||||||
|
u.Lock()
|
||||||
|
defer u.Unlock()
|
||||||
|
for i, s := range u.Sockets {
|
||||||
|
if s == nil || s.conn == nil {
|
||||||
|
del++
|
||||||
|
u.Sockets[i] = u.Sockets[len(u.Sockets)-del]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
sockets = append(sockets, s)
|
||||||
}
|
}
|
||||||
socket.conn.SetWriteDeadline(time.Now().Add(time.Minute))
|
}()
|
||||||
e := socket.conn.WriteMessage(websocket.PingMessage, nil)
|
if del > 0 {
|
||||||
|
// TODO: Resize the capacity to release memory more eagerly?
|
||||||
|
u.Sockets = u.Sockets[:len(u.Sockets)-del]
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range sockets {
|
||||||
|
_ = s.conn.SetWriteDeadline(time.Now().Add(time.Minute))
|
||||||
|
e := s.conn.WriteMessage(websocket.PingMessage, nil)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
socket.conn.Close()
|
s.conn.Close()
|
||||||
|
u.Lock()
|
||||||
|
s.conn = nil
|
||||||
|
u.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,10 +126,16 @@ func (u *WSUser) WriteToPageBytesMulti(msgs [][]byte, page string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *WSUser) CountSockets() int {
|
||||||
|
u.Lock()
|
||||||
|
defer u.Unlock()
|
||||||
|
return len(u.Sockets)
|
||||||
|
}
|
||||||
|
|
||||||
func (u *WSUser) AddSocket(conn *websocket.Conn, page string) {
|
func (u *WSUser) AddSocket(conn *websocket.Conn, page string) {
|
||||||
u.Lock()
|
u.Lock()
|
||||||
// If the number of the sockets is small, then we can keep the size of the slice mostly static and just walk through it looking for empty slots
|
// If the number of the sockets is small, then we can keep the size of the slice mostly static and just walk through it looking for empty slots
|
||||||
if len(u.Sockets) < 6 {
|
/*if len(u.Sockets) < 6 {
|
||||||
for i, socket := range u.Sockets {
|
for i, socket := range u.Sockets {
|
||||||
if socket == nil {
|
if socket == nil {
|
||||||
u.Sockets[i] = &WSUserSocket{conn, page}
|
u.Sockets[i] = &WSUserSocket{conn, page}
|
||||||
|
@ -118,15 +144,35 @@ func (u *WSUser) AddSocket(conn *websocket.Conn, page string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
u.Sockets = append(u.Sockets, &WSUserSocket{conn, page})
|
u.Sockets = append(u.Sockets, &WSUserSocket{conn, page})
|
||||||
//fmt.Printf("%+v\n", u.Sockets)
|
//fmt.Printf("%+v\n", u.Sockets)
|
||||||
u.Unlock()
|
u.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *WSUser) RemoveSocket(conn *websocket.Conn) {
|
func (u *WSUser) RemoveSocket(conn *websocket.Conn) {
|
||||||
|
var del int
|
||||||
u.Lock()
|
u.Lock()
|
||||||
defer u.Unlock()
|
defer u.Unlock()
|
||||||
|
for i, socket := range u.Sockets {
|
||||||
|
if socket == nil || socket.conn == nil {
|
||||||
|
del++
|
||||||
|
u.Sockets[i] = u.Sockets[len(u.Sockets)-del]
|
||||||
|
} else if socket.conn == conn {
|
||||||
|
del++
|
||||||
|
u.Sockets[i] = u.Sockets[len(u.Sockets)-del]
|
||||||
|
//break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Logf("%+v\n", u.Sockets)
|
||||||
|
//Log("del: ", del)
|
||||||
|
if del > 0 {
|
||||||
|
// TODO: Resize the capacity to release memory more eagerly?
|
||||||
|
u.Sockets = u.Sockets[:len(u.Sockets)-del]
|
||||||
|
}
|
||||||
|
//Logf("%+v\n", u.Sockets)
|
||||||
|
return
|
||||||
|
|
||||||
if len(u.Sockets) < 6 {
|
if len(u.Sockets) < 6 {
|
||||||
for i, socket := range u.Sockets {
|
for i, socket := range u.Sockets {
|
||||||
if socket == nil {
|
if socket == nil {
|
||||||
|
|
73
misc_test.go
73
misc_test.go
|
@ -3201,3 +3201,76 @@ func TestTick(t *testing.T) {
|
||||||
expectNilErr(t, c.CTickLoop.Hourf())
|
expectNilErr(t, c.CTickLoop.Hourf())
|
||||||
expectNilErr(t, c.CTickLoop.Dayf())
|
expectNilErr(t, c.CTickLoop.Dayf())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWSHub(t *testing.T) {
|
||||||
|
ex, exf, h := exp(t), expf(t), &c.WsHub
|
||||||
|
exf(h.GuestCount() == 0, "GuestCount should be %d not %d", 0, h.GuestCount())
|
||||||
|
exf(h.UserCount() == 0, "UserCount should be %d not %d", 0, h.UserCount())
|
||||||
|
ex(!h.HasUser(-1), "HasUser(-1) should be false")
|
||||||
|
ex(!h.HasUser(0), "HasUser(0) should be false")
|
||||||
|
ex(!h.HasUser(1), "HasUser(1) should be false")
|
||||||
|
|
||||||
|
uid, e := c.Users.Create("WsHub Test", "WsHub Test", "", 1, true)
|
||||||
|
expectNilErr(t, e)
|
||||||
|
exf(!h.HasUser(uid), "HasUser(%d) should be false", uid)
|
||||||
|
exf(len(h.AllUsers()) == 0, "len(AllUsers()) should be %d not %d", 0, len(h.AllUsers()))
|
||||||
|
|
||||||
|
f := func(uid, guestCount, userCount, allUserListLen int, hasUser bool) {
|
||||||
|
exf(h.GuestCount() == guestCount, "GuestCount should be %d not %d", guestCount, h.GuestCount())
|
||||||
|
exf(h.UserCount() == userCount, "UserCount should be %d not %d", userCount, h.UserCount())
|
||||||
|
exf(len(h.AllUsers()) == allUserListLen, "len(AllUsers()) should be %d not %d", allUserListLen, len(h.AllUsers()))
|
||||||
|
if hasUser {
|
||||||
|
exf(h.HasUser(uid), "HasUser(%d) should be true", uid)
|
||||||
|
} else {
|
||||||
|
exf(!h.HasUser(uid), "HasUser(%d) should be false", uid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u, e := c.Users.Get(uid)
|
||||||
|
expectNilErr(t, e)
|
||||||
|
wsUser, e := h.AddConn(u, nil)
|
||||||
|
expectNilErr(t, e)
|
||||||
|
f(uid, 0, 1, 1, true)
|
||||||
|
|
||||||
|
uid, e = c.Users.Create("WsHub Test 2", "WsHub Test 2", "", 1, true)
|
||||||
|
expectNilErr(t, e)
|
||||||
|
u2, e := c.Users.Get(uid)
|
||||||
|
expectNilErr(t, e)
|
||||||
|
wsUser2, e := h.AddConn(u2, nil)
|
||||||
|
expectNilErr(t, e)
|
||||||
|
f(uid, 0, 2, 2, true)
|
||||||
|
|
||||||
|
h.RemoveConn(wsUser2, nil)
|
||||||
|
f(uid, 0, 1, 1, false)
|
||||||
|
h.RemoveConn(wsUser2, nil)
|
||||||
|
f(uid, 0, 1, 1, false)
|
||||||
|
h.RemoveConn(wsUser, nil)
|
||||||
|
f(uid, 0, 0, 0, false)
|
||||||
|
|
||||||
|
countSockets := func(wsUser *c.WSUser, expect int) {
|
||||||
|
exf(wsUser.CountSockets() == expect, "CountSockets() should be %d not %d", expect, wsUser.CountSockets())
|
||||||
|
}
|
||||||
|
wsUser2, e = h.AddConn(u2, nil)
|
||||||
|
expectNilErr(t, e)
|
||||||
|
f(uid, 0, 1, 1, true)
|
||||||
|
countSockets(wsUser2, 1)
|
||||||
|
wsUser2.RemoveSocket(nil)
|
||||||
|
f(uid, 0, 1, 1, true)
|
||||||
|
countSockets(wsUser2, 0)
|
||||||
|
h.RemoveConn(wsUser2, nil)
|
||||||
|
f(uid, 0, 0, 0, false)
|
||||||
|
countSockets(wsUser2, 0)
|
||||||
|
|
||||||
|
wsUser2, e = h.AddConn(u2, nil)
|
||||||
|
expectNilErr(t, e)
|
||||||
|
f(uid, 0, 1, 1, true)
|
||||||
|
countSockets(wsUser2, 1)
|
||||||
|
expectNilErr(t, wsUser2.Ping())
|
||||||
|
f(uid, 0, 1, 1, true)
|
||||||
|
countSockets(wsUser2, 0)
|
||||||
|
h.RemoveConn(wsUser2, nil)
|
||||||
|
f(uid, 0, 0, 0, false)
|
||||||
|
countSockets(wsUser2, 0)
|
||||||
|
|
||||||
|
// TODO: Add more tests
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue