better handler registration and dispatch

This commit is contained in:
admin 2025-07-10 10:23:03 +02:00
parent f27890e55e
commit c6bf54943a
15 changed files with 190 additions and 81 deletions

View File

@ -2,10 +2,11 @@ package serverevents
import (
gocontext "context"
di "git.apihub24.de/admin/generic-di"
"github.com/coder/websocket"
"sync"
"time"
di "git.apihub24.de/admin/generic-di"
"github.com/coder/websocket"
)
func init() {
@ -21,7 +22,7 @@ type IContext interface {
Get(key string) (any, bool)
RemoveMetaData(key string)
CleanupIn(lifetime time.Duration)
Dispatch(eventName string, data any, filter func(c IContext) bool)
Dispatch(event IEvent, filter func(c IContext) bool)
IsCaller(c IContext) bool
}
@ -84,9 +85,7 @@ func (context *context) RemoveMetaData(key string) {
context.mutex.Lock()
defer context.mutex.Unlock()
if _, ok := context.metadata[key]; ok {
delete(context.metadata, key)
}
delete(context.metadata, key)
}
func (context *context) CleanupIn(lifetime time.Duration) {
@ -110,10 +109,10 @@ func (context *context) CleanupIn(lifetime time.Duration) {
}(context.id)
}
func (context *context) Dispatch(eventName string, data any, filter func(c IContext) bool) {
func (context *context) Dispatch(event IEvent, filter func(c IContext) bool) {
ev := Event{
Type: eventName,
Data: data,
Type: event.GetEventName(),
Data: event.GetEventData(),
IsBackendOnly: filter == nil,
Filter: filter,
}

View File

@ -6,3 +6,8 @@ type Event struct {
IsBackendOnly bool `json:"-"`
Filter func(c IContext) bool `json:"-"`
}
type IEvent interface {
GetEventName() string
GetEventData() any
}

View File

@ -1,6 +1,7 @@
package serverevents
type IEventHandler interface {
GetConnectedEventName() string
CanExecute(IContext) bool
Handle(IContext, any)
}

View File

@ -0,0 +1,5 @@
package dto
type Greeting struct {
Message string `json:"message"`
}

View File

@ -0,0 +1,26 @@
package definitions
import (
serverevents "git.apihub24.de/admin/server_events/v2"
"git.apihub24.de/admin/server_events/v2/implementation_test/data/dto"
)
const GreeterEventName = "greet"
type greetEvent struct {
data dto.Greeting
}
func NewGreetEvent(data dto.Greeting) serverevents.IEvent {
return &greetEvent{
data: data,
}
}
func (ev *greetEvent) GetEventName() string {
return GreeterEventName
}
func (ev *greetEvent) GetEventData() any {
return ev.data
}

View File

@ -0,0 +1,23 @@
package definitions
import serverevents "git.apihub24.de/admin/server_events/v2"
const GreetMeEventName = "greet me"
type greetMeEvent struct {
data string
}
func NewGreetMeEvent(name string) serverevents.IEvent {
return &greetMeEvent{
data: name,
}
}
func (ev *greetMeEvent) GetEventName() string {
return GreetMeEventName
}
func (ev *greetMeEvent) GetEventData() any {
return ev.data
}

View File

@ -0,0 +1,19 @@
package definitions
import serverevents "git.apihub24.de/admin/server_events/v2"
const PingEventName = "ping"
type pingEvent struct{}
func NewPingEvent() serverevents.IEvent {
return &pingEvent{}
}
func (ev *pingEvent) GetEventName() string {
return PingEventName
}
func (ev *pingEvent) GetEventData() any {
return nil
}

View File

@ -0,0 +1,19 @@
package definitions
import serverevents "git.apihub24.de/admin/server_events/v2"
const PongEventName = "pong"
type pongEvent struct{}
func NewPongEvent() serverevents.IEvent {
return &pongEvent{}
}
func (ev *pongEvent) GetEventName() string {
return PongEventName
}
func (ev *pongEvent) GetEventData() any {
return nil
}

View File

@ -1,39 +0,0 @@
package events
import (
"fmt"
serverevents "git.apihub24.de/admin/server_events/v2"
)
func withSameUserName(context serverevents.IContext) func(context serverevents.IContext) bool {
return serverevents.CreateMetaDataFilter(context, func(c serverevents.IContext) string {
userName, _ := serverevents.MetadataAs[string](context, "UserName")
return userName
}, func(a string, b string) bool {
return a == b
})
}
type greeting struct {
Message string
}
type greeterEventHandler struct{}
func (handler greeterEventHandler) CanExecute(_ serverevents.IContext) bool {
return true
}
func (handler greeterEventHandler) Handle(context serverevents.IContext, data any) {
userName, ok := serverevents.ValueAs[string](data)
if !ok || len(userName) < 1 {
userName = "Anonymous"
}
context.Dispatch("greet", greeting{
Message: fmt.Sprintf("Hello, %s", userName),
}, withSameUserName(context))
}
func NewGreeterEventHandler() serverevents.IEventHandler {
return &greeterEventHandler{}
}

View File

@ -0,0 +1,34 @@
package handler
import (
"fmt"
serverevents "git.apihub24.de/admin/server_events/v2"
"git.apihub24.de/admin/server_events/v2/implementation_test/data/dto"
"git.apihub24.de/admin/server_events/v2/implementation_test/events/definitions"
"git.apihub24.de/admin/server_events/v2/implementation_test/filter"
)
type greetMeEventHandler struct{}
func NewGreetMeEventHandler() serverevents.IEventHandler {
return &greetMeEventHandler{}
}
func (handler *greetMeEventHandler) GetConnectedEventName() string {
return definitions.GreetMeEventName
}
func (handler *greetMeEventHandler) CanExecute(_ serverevents.IContext) bool {
return true
}
func (handler *greetMeEventHandler) Handle(context serverevents.IContext, data any) {
userName, ok := serverevents.ValueAs[string](data)
if !ok || len(userName) < 1 {
userName = "Anonymous"
}
context.Dispatch(definitions.NewGreetEvent(dto.Greeting{
Message: fmt.Sprintf("Hello, %s", userName),
}), filter.WithSameUserName(context))
}

View File

@ -0,0 +1,24 @@
package handler
import (
serverevents "git.apihub24.de/admin/server_events/v2"
"git.apihub24.de/admin/server_events/v2/implementation_test/events/definitions"
)
type pingEventHandler struct{}
func NewPingEventHandler() serverevents.IEventHandler {
return &pingEventHandler{}
}
func (handler *pingEventHandler) GetConnectedEventName() string {
return definitions.PingEventName
}
func (handler *pingEventHandler) CanExecute(_ serverevents.IContext) bool {
return true
}
func (handler *pingEventHandler) Handle(context serverevents.IContext, _ any) {
context.Dispatch(definitions.NewPongEvent(), context.IsCaller)
}

View File

@ -1,19 +0,0 @@
package events
import (
serverevents "git.apihub24.de/admin/server_events/v2"
)
type pingEventHandler struct{}
func NewPingEventHandler() serverevents.IEventHandler {
return &pingEventHandler{}
}
func (p pingEventHandler) CanExecute(_ serverevents.IContext) bool {
return true
}
func (p pingEventHandler) Handle(context serverevents.IContext, _ any) {
context.Dispatch("pong", nil, context.IsCaller)
}

View File

@ -0,0 +1,12 @@
package filter
import serverevents "git.apihub24.de/admin/server_events/v2"
func WithSameUserName(context serverevents.IContext) func(context serverevents.IContext) bool {
return serverevents.CreateMetaDataFilter(context, func(c serverevents.IContext) string {
userName, _ := serverevents.MetadataAs[string](context, "UserName")
return userName
}, func(a string, b string) bool {
return a == b
})
}

View File

@ -1,20 +1,21 @@
package main
import (
di "git.apihub24.de/admin/generic-di"
serverevents "git.apihub24.de/admin/server_events/v2"
"git.apihub24.de/admin/server_events/v2/implementation_test/events"
"log"
"net/http"
"time"
di "git.apihub24.de/admin/generic-di"
serverevents "git.apihub24.de/admin/server_events/v2"
"git.apihub24.de/admin/server_events/v2/implementation_test/events/handler"
)
func main() {
serverEventsMiddleware := di.Inject[serverevents.IMiddleware]()
eventRegistration := di.Inject[serverevents.IEventHandlerRegistration]()
eventRegistration.Add("ping", events.NewPingEventHandler)
eventRegistration.Add("greet me", events.NewGreeterEventHandler)
eventRegistration.Use(handler.NewPingEventHandler)
eventRegistration.Use(handler.NewGreetMeEventHandler)
router := http.NewServeMux()

View File

@ -2,8 +2,9 @@ package serverevents
import (
"fmt"
di "git.apihub24.de/admin/generic-di"
"sync"
di "git.apihub24.de/admin/generic-di"
)
func init() {
@ -11,7 +12,7 @@ func init() {
}
type IEventHandlerRegistration interface {
Add(eventType string, creator func() IEventHandler)
Use(creator func() IEventHandler)
GetHandler(eventType string) (IEventHandler, error)
}
@ -29,16 +30,14 @@ func newEventHandlerRegistration() IEventHandlerRegistration {
}
}
func (registration *eventHandlerRegistration) Add(eventType string, creator func() IEventHandler) {
func (registration *eventHandlerRegistration) Use(creator func() IEventHandler) {
registration.mutex.Lock()
defer registration.mutex.Unlock()
if _, ok := registration.instances[eventType]; ok {
delete(registration.instances, eventType)
}
if _, ok := registration.creators[eventType]; ok {
delete(registration.creators, eventType)
}
tmp := creator()
eventType := tmp.GetConnectedEventName()
delete(registration.instances, eventType)
delete(registration.creators, eventType)
registration.creators[eventType] = creator
}