htmgo/extensions/websocket/ws/register.go

78 lines
2.3 KiB
Go
Raw Normal View History

2024-10-16 20:23:36 +00:00
package ws
2024-10-16 20:00:57 +00:00
import (
2024-10-16 20:29:01 +00:00
"github.com/maddalax/htmgo/extensions/websocket/internal/wsutil"
2024-10-16 20:00:57 +00:00
"github.com/maddalax/htmgo/framework/h"
2024-10-16 20:43:34 +00:00
"github.com/maddalax/htmgo/framework/session"
2024-10-16 20:00:57 +00:00
"github.com/puzpuzpuz/xsync/v3"
"sync"
"sync/atomic"
)
type HandlerData struct {
2024-10-16 20:43:34 +00:00
SessionId session.Id
2024-10-16 20:23:36 +00:00
Socket *wsutil.SocketConnection
Manager *wsutil.SocketManager
2024-10-16 20:00:57 +00:00
}
type Handler func(data HandlerData)
type ServerSideEvent struct {
Event string
Payload map[string]any
2024-10-16 20:43:34 +00:00
SessionId session.Id
2024-10-16 20:00:57 +00:00
}
type KeyHash = string
var handlers = xsync.NewMapOf[KeyHash, Handler]()
2024-10-16 20:43:34 +00:00
var sessionIdToHashes = xsync.NewMapOf[session.Id, map[KeyHash]bool]()
var hashesToSessionId = xsync.NewMapOf[KeyHash, session.Id]()
2024-10-16 20:00:57 +00:00
var serverEventNamesToHash = xsync.NewMapOf[string, map[KeyHash]bool]()
2024-10-16 20:23:36 +00:00
var socketMessageListener = make(chan wsutil.SocketEvent, 100)
2024-10-16 20:00:57 +00:00
var serverSideMessageListener = make(chan ServerSideEvent, 100)
var lock = sync.Mutex{}
var callingHandler = atomic.Bool{}
func makeId() string {
return h.GenId(30)
}
func AddServerSideHandler(ctx *h.RequestContext, event string, handler Handler) *h.AttributeMapOrdered {
// If we are already in a handler, we don't want to add another handler
// this can happen if the handler renders another element that has a handler
if callingHandler.Load() {
return h.NewAttributeMap()
}
2024-10-16 20:43:34 +00:00
sessionId := session.GetSessionId(ctx)
2024-10-16 20:00:57 +00:00
hash := makeId()
handlers.LoadOrStore(hash, handler)
m, _ := serverEventNamesToHash.LoadOrCompute(event, func() map[KeyHash]bool {
return make(map[KeyHash]bool)
})
m[hash] = true
storeHashForSession(sessionId, hash)
storeSessionIdForHash(sessionId, hash)
return h.AttributePairs("data-handler-id", hash, "data-handler-event", event)
}
func AddClientSideHandler(ctx *h.RequestContext, event string, handler Handler) *h.AttributeMapOrdered {
hash := makeId()
handlers.LoadOrStore(hash, handler)
2024-10-16 20:43:34 +00:00
sessionId := session.GetSessionId(ctx)
2024-10-16 20:00:57 +00:00
storeHashForSession(sessionId, hash)
storeSessionIdForHash(sessionId, hash)
return h.AttributePairs("data-handler-id", hash, "data-handler-event", event)
}
2024-10-16 20:43:34 +00:00
func storeHashForSession(sessionId session.Id, hash KeyHash) {
2024-10-16 20:00:57 +00:00
m, _ := sessionIdToHashes.LoadOrCompute(sessionId, func() map[KeyHash]bool {
return make(map[KeyHash]bool)
})
m[hash] = true
}
2024-10-16 20:43:34 +00:00
func storeSessionIdForHash(sessionId session.Id, hash KeyHash) {
2024-10-16 20:00:57 +00:00
hashesToSessionId.Store(hash, sessionId)
}