mirror of
https://gitlab.dit.htwk-leipzig.de/htwk-software/htwkalender.git
synced 2025-07-22 04:28:47 +02:00
60 lines
1.1 KiB
Go
60 lines
1.1 KiB
Go
package hook
|
|
|
|
import (
|
|
"datamanager/backend/tools/security"
|
|
"errors"
|
|
"fmt"
|
|
"sync"
|
|
)
|
|
|
|
type Handler[T any] func(e T) error
|
|
type handlerPair[T any] struct {
|
|
id string
|
|
handler Handler[T]
|
|
}
|
|
|
|
type Hook[T any] struct {
|
|
mux sync.RWMutex
|
|
handlers []*handlerPair[T]
|
|
}
|
|
|
|
var StopPropagation = errors.New("event hook propagation stopped")
|
|
|
|
func (h *Hook[T]) Trigger(data T, oneOffHandlers ...Handler[T]) error {
|
|
h.mux.RLock()
|
|
|
|
handlers := make([]*handlerPair[T], 0, len(h.handlers)+len(oneOffHandlers))
|
|
handlers = append(handlers, h.handlers...)
|
|
|
|
// append the one off handlers
|
|
for i, oneOff := range oneOffHandlers {
|
|
handlers = append(handlers, &handlerPair[T]{
|
|
id: fmt.Sprintf("@%d", i),
|
|
handler: oneOff,
|
|
})
|
|
}
|
|
|
|
// unlock is not deferred to avoid deadlocks in case Trigger
|
|
// is called recursively by the handlers
|
|
h.mux.RUnlock()
|
|
|
|
for _, item := range handlers {
|
|
err := item.handler(data)
|
|
if err == nil {
|
|
continue
|
|
}
|
|
|
|
if errors.Is(err, StopPropagation) {
|
|
return nil
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func generateHookId() string {
|
|
return security.PseudorandomString(8)
|
|
}
|