server_events/v2/context.go

129 lines
2.5 KiB
Go

package serverevents
import (
gocontext "context"
"sync"
"time"
di "git.apihub24.de/admin/generic-di"
"github.com/coder/websocket"
)
func init() {
di.Injectable(newContext)
}
type IContext interface {
SetId(id string)
GetId() string
SetConnection(conn *websocket.Conn)
GetConnection() *websocket.Conn
Set(key string, data any)
Get(key string) (any, bool)
RemoveMetaData(key string)
CleanupIn(lifetime time.Duration)
Dispatch(event IEvent, filter func(c IContext) bool)
IsCaller(c IContext) bool
}
type context struct {
id string
metadata map[string]any
timer *time.Timer
hub IEventHub
mutex sync.RWMutex
c *websocket.Conn
ctx gocontext.Context
}
func newContext() IContext {
return &context{
id: "",
metadata: make(map[string]any),
timer: nil,
hub: di.Inject[IEventHub](),
mutex: sync.RWMutex{},
c: nil,
}
}
func (context *context) SetId(id string) {
context.mutex.Lock()
defer context.mutex.Unlock()
if context.timer != nil {
context.timer.Stop()
context.timer = nil
}
context.id = id
}
func (context *context) GetId() string {
return context.id
}
func (context *context) IsCaller(c IContext) bool {
return context.id == c.GetId()
}
func (context *context) Set(key string, data any) {
context.mutex.Lock()
defer context.mutex.Unlock()
context.metadata[key] = data
}
func (context *context) Get(key string) (any, bool) {
context.mutex.RLock()
defer context.mutex.RUnlock()
v, ok := context.metadata[key]
return v, ok
}
func (context *context) RemoveMetaData(key string) {
context.mutex.Lock()
defer context.mutex.Unlock()
delete(context.metadata, key)
}
func (context *context) CleanupIn(lifetime time.Duration) {
context.mutex.Lock()
defer context.mutex.Unlock()
if context.timer != nil {
context.timer.Stop()
}
context.timer = time.NewTimer(lifetime)
go func(currentId string) {
<-context.timer.C
context.mutex.Lock()
defer context.mutex.Unlock()
if context.timer != nil {
di.Destroy[IContext](context.id)
context.timer = nil
}
}(context.id)
}
func (context *context) Dispatch(event IEvent, filter func(c IContext) bool) {
ev := Event{
Type: event.GetEventName(),
Data: event.GetEventData(),
IsBackendOnly: filter == nil,
Filter: filter,
}
context.hub.Dispatch(ev, context)
}
func (context *context) GetConnection() *websocket.Conn {
return context.c
}
func (context *context) SetConnection(conn *websocket.Conn) {
context.c = conn
}