mirror of
https://github.com/gookit/event
synced 2025-09-26 19:11:14 +08:00
155 lines
3.2 KiB
Go
155 lines
3.2 KiB
Go
package event
|
|
|
|
import (
|
|
"reflect"
|
|
"sort"
|
|
)
|
|
|
|
// There are some default priority constants
|
|
const (
|
|
Min = -300
|
|
Low = -200
|
|
BelowNormal = -100
|
|
Normal = 0
|
|
AboveNormal = 100
|
|
High = 200
|
|
Max = 300
|
|
)
|
|
|
|
/*************************************************************
|
|
* region Listener
|
|
*************************************************************/
|
|
|
|
// Listener interface
|
|
type Listener interface {
|
|
Handle(e Event) error
|
|
}
|
|
|
|
// ListenerFunc func definition.
|
|
type ListenerFunc func(e Event) error
|
|
|
|
// Handle event. implements the Listener interface
|
|
func (fn ListenerFunc) Handle(e Event) error {
|
|
return fn(e)
|
|
}
|
|
|
|
// Subscriber event subscriber interface.
|
|
//
|
|
// you can register multi event listeners in a struct func.
|
|
type Subscriber interface {
|
|
// SubscribedEvents register event listeners
|
|
//
|
|
// - key: is event name. eg "user.created" "user.*" "user.**"
|
|
// - value: can be Listener or ListenerItem interface
|
|
SubscribedEvents() map[string]any
|
|
}
|
|
|
|
// ListenerItem storage a event listener and it's priority value.
|
|
type ListenerItem struct {
|
|
Priority int
|
|
Listener Listener
|
|
}
|
|
|
|
/*************************************************************
|
|
* Listener Queue
|
|
*************************************************************/
|
|
|
|
// ListenerQueue storage sorted Listener instance.
|
|
type ListenerQueue struct {
|
|
items []*ListenerItem
|
|
}
|
|
|
|
// Len get items length
|
|
func (lq *ListenerQueue) Len() int {
|
|
return len(lq.items)
|
|
}
|
|
|
|
// IsEmpty get items length == 0
|
|
func (lq *ListenerQueue) IsEmpty() bool {
|
|
return len(lq.items) == 0
|
|
}
|
|
|
|
// Push get items length
|
|
func (lq *ListenerQueue) Push(li *ListenerItem) *ListenerQueue {
|
|
lq.items = append(lq.items, li)
|
|
return lq
|
|
}
|
|
|
|
// Sort the queue items by ListenerItem's priority.
|
|
//
|
|
// Priority:
|
|
//
|
|
// High > Low
|
|
func (lq *ListenerQueue) Sort() *ListenerQueue {
|
|
// if lq.IsEmpty() {
|
|
// return lq
|
|
// }
|
|
ls := ByPriorityItems(lq.items)
|
|
|
|
// check items is sorted
|
|
if !sort.IsSorted(ls) {
|
|
sort.Sort(ls)
|
|
}
|
|
|
|
return lq
|
|
}
|
|
|
|
// Items get all ListenerItem
|
|
func (lq *ListenerQueue) Items() []*ListenerItem {
|
|
return lq.items
|
|
}
|
|
|
|
// Remove a listener from the queue
|
|
func (lq *ListenerQueue) Remove(listener Listener) {
|
|
if listener == nil {
|
|
return
|
|
}
|
|
|
|
// unsafe.Pointer(listener)
|
|
ptrVal := getListenCompareKey(listener)
|
|
|
|
var newItems []*ListenerItem
|
|
for _, li := range lq.items {
|
|
liPtrVal := getListenCompareKey(li.Listener)
|
|
if liPtrVal == ptrVal {
|
|
continue
|
|
}
|
|
|
|
newItems = append(newItems, li)
|
|
}
|
|
|
|
lq.items = newItems
|
|
}
|
|
|
|
// Clear all listeners
|
|
func (lq *ListenerQueue) Clear() {
|
|
lq.items = lq.items[:0]
|
|
}
|
|
|
|
// getListenCompareKey get listener compare key
|
|
func getListenCompareKey(src Listener) reflect.Value {
|
|
return reflect.ValueOf(src)
|
|
}
|
|
|
|
/*************************************************************
|
|
* Sorted PriorityItems
|
|
*************************************************************/
|
|
|
|
// ByPriorityItems type. implements the sort.Interface
|
|
type ByPriorityItems []*ListenerItem
|
|
|
|
// Len get items length
|
|
func (ls ByPriorityItems) Len() int {
|
|
return len(ls)
|
|
}
|
|
|
|
// Less implements the sort.Interface.Less.
|
|
func (ls ByPriorityItems) Less(i, j int) bool {
|
|
return ls[i].Priority > ls[j].Priority
|
|
}
|
|
|
|
// Swap implements the sort.Interface.Swap.
|
|
func (ls ByPriorityItems) Swap(i, j int) {
|
|
ls[i], ls[j] = ls[j], ls[i]
|
|
}
|