olahol / melody

:notes: Minimalist websocket framework for Go
BSD 2-Clause "Simplified" License
3.75k stars 366 forks source link

how get active sessions #65

Closed imanborumand closed 2 years ago

imanborumand commented 3 years ago

hi how i get active sessions for use in private chat?

thanks

hah commented 3 years ago

fork this repo and merge this change https://github.com/olahol/melody/pull/52

lesismal commented 3 years ago

fork this repo and merge this change #52

That's not a good way to manage all sessions if you copy all sessions to another map every time in a high concurrency service, it is very performance unfriendly.

lesismal commented 3 years ago

hi how i get active sessions for use in private chat?

thanks

if you just need to do some broadcast, use:

m.Broadcast
m.BroadcastFilter
m.BroadcastOthers
m.BroadcastMultiple
m.BroadcastBinary
m.BroadcastBinaryFilter
m.BroadcastBinaryOthers 

else if you need to do some more, you can manage all sessions at application layer, for example:

package main

import (
    "sync"

    "github.com/gin-gonic/gin"
    "github.com/olahol/melody"
)

type SessionMgr struct {
    mux      sync.RWMutex
    sessions map[interface{}]*melody.Session
}

func (mgr *SessionMgr) Get(id interface{}) (*melody.Session, bool) {
    mgr.mux.RLock()
    defer mgr.mux.RUnlock()
    sess, ok := mgr.sessions[id]
    return sess, ok
}

func (mgr *SessionMgr) Set(id interface{}, sess *melody.Session) {
    mgr.mux.Lock()
    defer mgr.mux.Unlock()
    mgr.sessions[id] = sess
}

func (mgr *SessionMgr) Delete(id interface{}) {
    mgr.mux.Lock()
    defer mgr.mux.Unlock()
    delete(mgr.sessions, id)
}

func (mgr *SessionMgr) ForEach(filter func(sess *melody.Session) bool, handler func(sess *melody.Session)) {
    mgr.mux.RLock()
    defer mgr.mux.RUnlock()
    for _, sess := range mgr.sessions {
        if filter(sess) {
            handler(sess)
        }
    }
}

var (
    sessionMgr = SessionMgr{
        sessions: map[interface{}]*melody.Session{},
    }
)

func main() {
    r := gin.Default()
    m := melody.New()

    m.HandleConnect(func(sess *melody.Session) {
        id := getIDFromSession(sess)
        sessionMgr.Set(id, sess)
    })

    m.HandleDisconnect(func(sess *melody.Session) {
        id := getIDFromSession(sess)
        sessionMgr.Delete(id)
    })

    r.GET("/ws", func(c *gin.Context) {
        m.HandleRequest(c.Writer, c.Request)
    })

    m.HandleMessage(func(s *melody.Session, msg []byte) {
        // ...
    })

    r.Run(":5000")
}
olahol commented 2 years ago

I merged #52, but as @lesismal says it's not very performant, although the package probably needs a performance rewrite anyway.