event

package module
v1.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 6, 2024 License: MIT Imports: 7 Imported by: 94

README

Event

GitHub go.mod Go version GoDoc Actions Status Coverage Status Go Report Card

Lightweight event management, dispatch tool library implemented by Go

  • Support for custom definition event objects
  • Support for adding multiple listeners to an event
  • Support setting the priority of the event listener, the higher the priority, the first to trigger
  • Support for a set of event listeners based on the event name prefix PREFIX.*.
    • ModeSimple(default) - app.* event listen, trigger app.run app.end, Both will fire the app.* listener
  • New match mode: ModePath
    • * Only match a segment of characters that are not ., allowing for finer monitoring and matching
    • ** matches any number of characters and can only be used at the beginning or end
  • Support for using the wildcard * to listen for triggers for all events
  • Support async trigger event by go channel consumers. use Async(), FireAsync()
  • Complete unit testing, unit coverage > 95%

中文说明

中文说明请看 README.zh-CN

GoDoc

Install

go get github.com/gookit/event

Main method

  • On/Listen(name string, listener Listener, priority ...int) Register event listener
  • Subscribe/AddSubscriber(sbr Subscriber) Subscribe to support registration of multiple event listeners
  • Trigger/Fire(name string, params M) (error, Event) Trigger event by name and params
  • MustTrigger/MustFire(name string, params M) Event Trigger event, there will be panic if there is an error
  • FireEvent(e Event) (err error) Trigger an event based on a given event instance
  • FireBatch(es ...interface{}) (ers []error) Trigger multiple events at once
  • Async/FireC(name string, params M) Push event to chan, asynchronous consumption processing
  • FireAsync(e Event) Push event to chan, asynchronous consumption processing
  • AsyncFire(e Event) Async fire event by 'go' keywords

Quick start

package main

import (
	"fmt"
	
	"github.com/gookit/event"
)

func main() {
	// Register event listener
	event.On("evt1", event.ListenerFunc(func(e event.Event) error {
		fmt.Printf("handle event: %s\n", e.Name())
		return nil
	}), event.Normal)

	// Register multiple listeners
	event.On("evt1", event.ListenerFunc(func(e event.Event) error {
		fmt.Printf("handle event: %s\n", e.Name())
		return nil
	}), event.High)

	// ... ...

	// Trigger event
	// Note: The second listener has a higher priority, so it will be executed first.
	event.MustFire("evt1", event.M{"arg0": "val0", "arg1": "val1"})
}

Note: The second listener has a higher priority, so it will be executed first.

Using the wildcard

Match mode ModePath

Register event listener and name end with wildcard *:

func main() {
	dbListener1 := event.ListenerFunc(func(e event.Event) error {
		fmt.Printf("handle event: %s\n", e.Name())
		return nil
	})

	event.On("app.db.*", dbListener1, event.Normal)
}

Trigger events on other logic:

func doCreate() {
	// do something ...
	// Trigger event
	event.MustFire("app.db.create", event.M{"arg0": "val0", "arg1": "val1"})
}

func doUpdate() {
	// do something ...
	// Trigger event
	event.MustFire("app.db.update", event.M{"arg0": "val0"})
}

Like the above, triggering the app.db.create app.db.update event will trigger the execution of the dbListener1 listener.

Match mode ModePath

ModePath It is a new pattern of v1.1.0, and the wildcard * matching logic has been adjusted:

  • * Only match a segment of characters that are not ., allowing for finer monitoring and matching
  • ** matches any number of characters and can only be used at the beginning or end
em := event.NewManager("test", event.UsePathMode)

// register listener
em.On("app.**", appListener)
em.On("app.db.*", dbListener)
em.On("app.*.create", createListener)
em.On("app.*.update", updateListener)

// ... ...

// fire event
// TIP: will trigger appListener, dbListener, createListener
em.Fire("app.db.create", event.M{"arg0": "val0", "arg1": "val1"})

Async fire events

Use chan fire events

You can use the Async/FireC/FireAsync method to trigger events, and the events will be written to chan for asynchronous consumption. You can use CloseWait() to close the chan and wait for all events to be consumed.

Added option configuration:

  • ChannelSize Set buffer size for chan
  • ConsumerNum Set how many coroutines to start to consume events
func main() {
	// Note: close event chan on program exit
	defer event.CloseWait()
	// defer event.Close()
	
    // register event listener
    event.On("app.evt1", event.ListenerFunc(func(e event.Event) error {
        fmt.Printf("handle event: %s\n", e.Name())
        return nil
    }), event.Normal)
    
    event.On("app.evt1", event.ListenerFunc(func(e event.Event) error {
        fmt.Printf("handle event: %s\n", e.Name())
        return nil
    }), event.High)
    
    // ... ...
    
    // Asynchronous consumption of events
    event.FireC("app.evt1", event.M{"arg0": "val0", "arg1": "val1"})
}

Note: The event chan should be closed when the program exits. You can use the following method:

  • event.Close() Close chan and no longer accept new events
  • event.CloseWait() Close chan and wait for all event processing to complete

Write event listeners

Using anonymous functions

You can use anonymous function for quick write an event lister.

package mypgk

import (
	"fmt"

	"github.com/gookit/event"
)

var fnHandler = func(e event.Event) error {
	fmt.Printf("handle event: %s\n", e.Name())
	return nil
}

func Run() {
	// register
	event.On("evt1", event.ListenerFunc(fnHandler), event.High)
}
Using the structure method

You can use struct write an event lister, and it should implementation interface event.Listener.

interface:

// Listener interface
type Listener interface {
	Handle(e Event) error
}

example:

Implementation interface event.Listener

package mypgk

import "github.com/gookit/event"

type MyListener struct {
	// userData string
}

func (l *MyListener) Handle(e event.Event) error {
	e.Set("result", "OK")
	return nil
}

Register multiple event listeners

Can implementation interface event.Subscriber for register multiple event listeners at once.

interface:

// 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
	// value: can be Listener or ListenerItem interface
	SubscribedEvents() map[string]interface{}
}

Example

Implementation interface event.Subscriber

package mypgk

import (
	"fmt"

	"github.com/gookit/event"
)

type MySubscriber struct {
	// ooo
}

func (s *MySubscriber) SubscribedEvents() map[string]interface{} {
	return map[string]interface{}{
		"e1": event.ListenerFunc(s.e1Handler),
		"e2": event.ListenerItem{
			Priority: event.AboveNormal,
			Listener: event.ListenerFunc(func(e Event) error {
				return fmt.Errorf("an error")
			}),
		},
		"e3": &MyListener{},
	}
}

func (s *MySubscriber) e1Handler(e event.Event) error {
	e.Set("e1-key", "val1")
	return nil
}

Write custom events

If you want to customize the event object or define some fixed event information in advance, you can implement the event.Event interface.

interface:

// Event interface
type Event interface {
	Name() string
	// Target() interface{}
	Get(key string) interface{}
	Add(key string, val interface{})
	Set(key string, val interface{})
	Data() map[string]interface{}
	SetData(M) Event
	Abort(bool)
	IsAborted() bool
}

examples:

package mypgk

import "github.com/gookit/event"

type MyEvent struct {
	event.BasicEvent
	customData string
}

func (e *MyEvent) CustomData() string {
	return e.customData
}

Usage:

e := &MyEvent{customData: "hello"}
e.SetName("e1")
event.AddEvent(e)

// add listener
event.On("e1", event.ListenerFunc(func(e event.Event) error {
	fmt.Printf("custom Data: %s\n", e.(*MyEvent).CustomData())
	return nil
}))

// trigger
event.Fire("e1", nil)
// OR
// event.FireEvent(e)

Note: is used to add pre-defined public event information, which is added in the initialization phase, so it is not locked. Event dynamically created in business can be directly triggered by FireEvent()

Gookit packages

  • gookit/ini Go config management, use INI files
  • gookit/rux Simple and fast request router for golang HTTP
  • gookit/gcli build CLI application, tool library, running CLI commands
  • gookit/slog Lightweight, extensible, configurable logging library written in Go
  • gookit/event Lightweight event manager and dispatcher implements by Go
  • gookit/cache Generic cache use and cache manager for golang. support File, Memory, Redis, Memcached.
  • gookit/config Go config management. support JSON, YAML, TOML, INI, HCL, ENV and Flags
  • gookit/color A command-line color library with true color support, universal API methods and Windows support
  • gookit/filter Provide filtering, sanitizing, and conversion of golang data
  • gookit/validate Use for data validation and filtering. support Map, Struct, Form data
  • gookit/goutil Some utils for the Go: string, array/slice, map, format, cli, env, filesystem, test and more
  • More, please see https://github.com/gookit

LICENSE

MIT

Documentation

Overview

Package event is lightweight event manager and dispatcher implements by Go.

Index

Constants

View Source
const (
	Wildcard = "*"
	AnyNode  = "*"
	AllNode  = "**"
)

wildcard event name

View Source
const (
	// ModeSimple old mode, simple match group listener.
	//
	//  - "*" only allow one and must at end
	//
	// Support: "user.*" -> match "user.created" "user.updated"
	ModeSimple uint8 = iota

	// ModePath path mode.
	//
	//  - "*" matches any sequence of non . characters (like at path.Match())
	//  - "**" match all characters to end, only allow at start or end on pattern.
	//
	// Support like this:
	// 	"eve.some.*.*"       -> match "eve.some.thing.run" "eve.some.thing.do"
	// 	"eve.some.*.run"     -> match "eve.some.thing.run", but not match "eve.some.thing.do"
	// 	"eve.some.**"        -> match any start with "eve.some.". eg: "eve.some.thing.run" "eve.some.thing.do"
	// 	"**.thing.run"       -> match any ends with ".thing.run". eg: "eve.some.thing.run"
	ModePath
)
View Source
const (
	Min         = -300
	Low         = -200
	BelowNormal = -100
	Normal      = 0
	AboveNormal = 100
	High        = 200
	Max         = 300
)

There are some default priority constants

Variables

This section is empty.

Functions

func AddEvent

func AddEvent(e Event)

AddEvent add a pre-defined event.

func AddEventFc added in v1.1.1

func AddEventFc(name string, fc FactoryFunc)

AddEventFc add a pre-defined event factory func to manager.

func AddSubscriber added in v1.0.5

func AddSubscriber(sbr Subscriber)

AddSubscriber register a listener to the event

func Async added in v1.1.1

func Async(name string, params M)

Async fire event by channel

func AsyncFire added in v1.0.4

func AsyncFire(e Event)

AsyncFire simple async fire event by 'go' keywords

func CloseWait added in v1.1.1

func CloseWait() error

CloseWait close chan and wait for all async events done.

func Config added in v1.1.1

func Config(fn ...OptionFn)

Config set default event manager options

func FireAsync added in v1.1.1

func FireAsync(e Event)

FireAsync fire event by channel

func FireBatch added in v1.0.5

func FireBatch(es ...any) []error

FireBatch fire multi event at once.

func FireEvent

func FireEvent(e Event) error

FireEvent fire listeners by Event instance.

func HasEvent

func HasEvent(name string) bool

HasEvent has event check.

func HasListeners

func HasListeners(name string) bool

HasListeners has listeners for the event name.

func Listen added in v1.0.4

func Listen(name string, listener Listener, priority ...int)

Listen register a listener to the event

func On

func On(name string, listener Listener, priority ...int)

On register a listener to the event. alias of Listen()

func Reset added in v1.0.5

func Reset()

Reset the default event manager

func Subscribe added in v1.0.4

func Subscribe(sbr Subscriber)

Subscribe register a listener to the event

func TriggerEvent added in v1.0.4

func TriggerEvent(e Event) error

TriggerEvent alias of FireEvent

func UsePathMode added in v1.1.0

func UsePathMode(o *Options)

UsePathMode set event name match mode to ModePath

Types

type BasicEvent

type BasicEvent struct {
	// contains filtered or unexported fields
}

BasicEvent a built-in implements Event interface

func New added in v1.1.1

func New(name string, data M) *BasicEvent

New create an event instance

func NewBasic

func NewBasic(name string, data M) *BasicEvent

NewBasic new a basic event instance

func (*BasicEvent) Abort

func (e *BasicEvent) Abort(abort bool)

Abort event loop exec

func (*BasicEvent) Add

func (e *BasicEvent) Add(key string, val any)

Add value by key

func (*BasicEvent) AttachTo

func (e *BasicEvent) AttachTo(em ManagerFace)

AttachTo add current event to the event manager.

func (*BasicEvent) Clone added in v1.1.0

func (e *BasicEvent) Clone() Event

Clone new instance

func (*BasicEvent) Data

func (e *BasicEvent) Data() map[string]any

Data get all data

func (*BasicEvent) Fill

func (e *BasicEvent) Fill(target any, data M) *BasicEvent

Fill event data

func (*BasicEvent) Get

func (e *BasicEvent) Get(key string) any

Get data by index

func (*BasicEvent) IsAborted

func (e *BasicEvent) IsAborted() bool

IsAborted check.

func (*BasicEvent) Name

func (e *BasicEvent) Name() string

Name get event name

func (*BasicEvent) Set

func (e *BasicEvent) Set(key string, val any)

Set value by key

func (*BasicEvent) SetData

func (e *BasicEvent) SetData(data M) Event

SetData set data to the event

func (*BasicEvent) SetName

func (e *BasicEvent) SetName(name string) *BasicEvent

SetName set event name

func (*BasicEvent) SetTarget

func (e *BasicEvent) SetTarget(target any) *BasicEvent

SetTarget set event target

func (*BasicEvent) Target

func (e *BasicEvent) Target() any

Target get target

type ByPriorityItems

type ByPriorityItems []*ListenerItem

ByPriorityItems type. implements the sort.Interface

func (ByPriorityItems) Len

func (ls ByPriorityItems) Len() int

Len get items length

func (ByPriorityItems) Less

func (ls ByPriorityItems) Less(i, j int) bool

Less implements the sort.Interface.Less.

func (ByPriorityItems) Swap

func (ls ByPriorityItems) Swap(i, j int)

Swap implements the sort.Interface.Swap.

type Cloneable added in v1.1.0

type Cloneable interface {
	Event
	Clone() Event
}

Cloneable interface. event can be cloned.

type Event

type Event interface {
	Name() string
	Get(key string) any
	Set(key string, val any)
	Add(key string, val any)
	Data() map[string]any
	SetData(M) Event
	Abort(bool)
	IsAborted() bool
}

Event interface

func Fire

func Fire(name string, params M) (error, Event)

Fire listeners by name.

func GetEvent

func GetEvent(name string) (Event, bool)

GetEvent get event by name.

func MustFire

func MustFire(name string, params M) Event

MustFire fire event by name. will panic on error

func MustTrigger added in v1.0.4

func MustTrigger(name string, params M) Event

MustTrigger alias of MustFire

func Trigger added in v1.0.4

func Trigger(name string, params M) (error, Event)

Trigger alias of Fire

type FactoryFunc added in v1.1.0

type FactoryFunc func() Event

FactoryFunc for create event instance.

type Listener

type Listener interface {
	Handle(e Event) error
}

Listener interface

type ListenerFunc

type ListenerFunc func(e Event) error

ListenerFunc func definition.

func (ListenerFunc) Handle

func (fn ListenerFunc) Handle(e Event) error

Handle event. implements the Listener interface

type ListenerItem

type ListenerItem struct {
	Priority int
	Listener Listener
}

ListenerItem storage a event listener and it's priority value.

type ListenerQueue

type ListenerQueue struct {
	// contains filtered or unexported fields
}

ListenerQueue storage sorted Listener instance.

func (*ListenerQueue) Clear

func (lq *ListenerQueue) Clear()

Clear all listeners

func (*ListenerQueue) IsEmpty

func (lq *ListenerQueue) IsEmpty() bool

IsEmpty get items length == 0

func (*ListenerQueue) Items

func (lq *ListenerQueue) Items() []*ListenerItem

Items get all ListenerItem

func (*ListenerQueue) Len

func (lq *ListenerQueue) Len() int

Len get items length

func (*ListenerQueue) Push

func (lq *ListenerQueue) Push(li *ListenerItem) *ListenerQueue

Push get items length

func (*ListenerQueue) Remove

func (lq *ListenerQueue) Remove(listener Listener)

Remove a listener from the queue

func (*ListenerQueue) Sort

func (lq *ListenerQueue) Sort() *ListenerQueue

Sort the queue items by ListenerItem's priority.

Priority:

High > Low

type M

type M = map[string]any

M is short name for map[string]...

type Manager

type Manager struct {
	Options
	sync.Mutex
	// contains filtered or unexported fields
}

Manager event manager definition. for manage events and listeners

func NewM added in v1.1.1

func NewM(name string, fns ...OptionFn) *Manager

NewM create event manager. alias of the NewManager()

func NewManager

func NewManager(name string, fns ...OptionFn) *Manager

NewManager create event manager

func Std added in v1.1.0

func Std() *Manager

Std get default event manager

func (*Manager) AddEvent

func (em *Manager) AddEvent(e Event)

AddEvent add a pre-defined event instance to manager.

func (*Manager) AddEventFc added in v1.1.0

func (em *Manager) AddEventFc(name string, fc FactoryFunc)

AddEventFc add a pre-defined event factory func to manager.

func (*Manager) AddListener

func (em *Manager) AddListener(name string, listener Listener, priority ...int)

AddListener register a event handler/listener. alias of the method On()

func (*Manager) AddSubscriber

func (em *Manager) AddSubscriber(sbr Subscriber)

AddSubscriber add events by subscriber interface.

you can register multi event listeners in a struct func. more usage please see README or tests.

func (*Manager) Async added in v1.1.0

func (em *Manager) Async(name string, params M)

Async fire event by go channel.

Note: if you want to use this method, you should call the method Close() after all events are fired.

func (*Manager) AsyncFire

func (em *Manager) AsyncFire(e Event)

AsyncFire simple async fire event by 'go' keywords

func (*Manager) AwaitFire

func (em *Manager) AwaitFire(e Event) (err error)

AwaitFire async fire event by 'go' keywords, but will wait return result

func (*Manager) Clear

func (em *Manager) Clear()

Clear alias of the Reset()

func (*Manager) Close added in v1.1.0

func (em *Manager) Close() error

Close event channel, deny to fire new event.

func (*Manager) CloseWait added in v1.1.1

func (em *Manager) CloseWait() error

CloseWait close channel and wait all async event done.

func (*Manager) Fire

func (em *Manager) Fire(name string, params M) (err error, e Event)

Fire trigger event by name. if not found listener, will return (nil, nil)

func (*Manager) FireAsync added in v1.1.0

func (em *Manager) FireAsync(e Event)

FireAsync async fire event by go channel.

Note: if you want to use this method, you should call the method Close() after all events are fired.

Example:

em := NewManager("test")
em.FireAsync("db.user.add", M{"id": 1001})

func (*Manager) FireBatch

func (em *Manager) FireBatch(es ...any) (ers []error)

FireBatch fire multi event at once.

Usage:

FireBatch("name1", "name2", &MyEvent{})

func (*Manager) FireC added in v1.1.0

func (em *Manager) FireC(name string, params M)

FireC async fire event by go channel. alias of the method Async()

Note: if you want to use this method, you should call the method Close() after all events are fired.

func (*Manager) FireEvent

func (em *Manager) FireEvent(e Event) (err error)

FireEvent fire event by given Event instance

func (*Manager) GetEvent

func (em *Manager) GetEvent(name string) (e Event, ok bool)

GetEvent get a pre-defined event instance by name

func (*Manager) HasEvent

func (em *Manager) HasEvent(name string) bool

HasEvent has pre-defined event check

func (*Manager) HasListeners

func (em *Manager) HasListeners(name string) bool

HasListeners check has direct listeners for the event name.

func (*Manager) Listen added in v1.0.4

func (em *Manager) Listen(name string, listener Listener, priority ...int)

Listen register a event handler/listener. alias of the On()

func (*Manager) ListenedNames

func (em *Manager) ListenedNames() map[string]int

ListenedNames get listened event names

func (*Manager) Listeners added in v1.0.1

func (em *Manager) Listeners() map[string]*ListenerQueue

Listeners get all listeners

func (*Manager) ListenersByName added in v1.0.1

func (em *Manager) ListenersByName(name string) *ListenerQueue

ListenersByName get listeners by given event name

func (*Manager) ListenersCount

func (em *Manager) ListenersCount(name string) int

ListenersCount get listeners number for the event name.

func (*Manager) MustFire

func (em *Manager) MustFire(name string, params M) Event

MustFire fire event by name. will panic on error

func (*Manager) MustTrigger added in v1.0.5

func (em *Manager) MustTrigger(name string, params M) Event

MustTrigger alias of the method MustFire()

func (*Manager) On

func (em *Manager) On(name string, listener Listener, priority ...int)

On register a event handler/listener. can setting priority.

Usage:

em.On("evt0", listener)
em.On("evt0", listener, High)

func (*Manager) RemoveEvent

func (em *Manager) RemoveEvent(name string)

RemoveEvent delete pre-define Event by name

func (*Manager) RemoveEvents

func (em *Manager) RemoveEvents()

RemoveEvents remove all registered events

func (*Manager) RemoveListener

func (em *Manager) RemoveListener(name string, listener Listener)

RemoveListener remove a given listener, you can limit event name.

Usage:

RemoveListener("", listener)
RemoveListener("name", listener) // limit event name.

func (*Manager) RemoveListeners

func (em *Manager) RemoveListeners(name string)

RemoveListeners remove listeners by given name

func (*Manager) Reset added in v1.0.5

func (em *Manager) Reset()

Reset the manager, clear all data.

func (*Manager) Subscribe added in v1.0.4

func (em *Manager) Subscribe(sbr Subscriber)

Subscribe add events by subscriber interface. alias of the AddSubscriber()

func (*Manager) Trigger

func (em *Manager) Trigger(name string, params M) (error, Event)

Trigger alias of the method Fire()

func (*Manager) Wait added in v1.1.1

func (em *Manager) Wait() error

Wait wait all async event done.

func (*Manager) WithOptions added in v1.1.0

func (em *Manager) WithOptions(fns ...OptionFn) *Manager

WithOptions create event manager with options

type ManagerFace

type ManagerFace interface {
	// AddEvent events: add event
	AddEvent(Event)
	// On listeners: add listeners
	On(name string, listener Listener, priority ...int)
	// Fire event
	Fire(name string, params M) (error, Event)
}

ManagerFace event manager interface

type OptionFn added in v1.1.0

type OptionFn func(o *Options)

OptionFn event manager config option func

func EnableLock added in v1.1.0

func EnableLock(enable bool) OptionFn

EnableLock enable lock on fire event.

type Options added in v1.1.0

type Options struct {
	// EnableLock enable lock on fire event. default is False.
	EnableLock bool
	// ChannelSize for fire events by goroutine
	ChannelSize int
	ConsumerNum int
	// MatchMode event name match mode. default is ModeSimple
	MatchMode uint8
}

Options event manager config options

type Subscriber

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
}

Subscriber event subscriber interface.

you can register multi event listeners in a struct func.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL