bell

package module
v2.2.0 Latest Latest
Warning

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

Go to latest
Published: May 26, 2022 License: Apache-2.0 Imports: 2 Imported by: 4

README

Bell

GoDoc Release codecov Tests

Bell is the simplest event system written in Go (Golang) which is based on the execution of handlers independent of the main channel.

  • Written in pure go. Has no third-party libraries.
  • Support for custom event data.
  • Internally, it launches each handler in a separate goroutine and passes messages to them through channels, the handlers are executed independently of the main thread.
  • Support for adding multiple handlers to an event.
  • Complete unit testing.

Bull does not contain logic for automatic restarts in case of a crash and does not have a persistent execution state store.

Installation

To install Bell package, you need install Go with modules support and set Go workspace first.

  1. Use the below Go command to install Bell:
go get -u github.com/nuttech/bell/v2
  1. Import package in your code:
import "github.com/nuttech/bell/v2"

Usage

Adding event listener

The handler function accepts the Message type as input

bell.Listen("event_name", func(message bell.Message) {
	// here you must write your handler code
})

bell.Message has interface{} type and can consist any data.

You can add more handlers one event:

bell.Listen("event_name", func(message bell.Message) { 
	// first handler
})
bell.Listen("event_name", func(message bell.Message) {
	// second handler
})

You can add a handler with multiple copies for parallel event processing.

bell.ListenN("event_name", func(msg bell.Message) { fmt.Println(msg) }, 42)
Calling an event

This code call event. Activating handlers, who subscribed on "event_name" event

bell.Ring("event_name", "some data")

bell.Ring("event_name", 1) // int

bell.Ring("event_name", false) // bool

If you passing struct type of data:

type userStruct struct {
	Name string
}
bell.Ring("event_name", userStruct{Name: "Jon"})

Then parsing the data in the handler may look like this:

bell.Listen("event_name", func(message bell.Message) {
	user := message.(userStruct)
	
	fmt.Printf("%#v\n", userStruct{Name: "Jon"})  // main.userStruct{Name:"Jon"}
})
Getting events list

To get a list of events to which handlers are subscribed, call the code:

bell.List()
Checking if exists listeners of event

You can check the existence of subscribers to an event like this:

bell.Has("event_name")
Removing listeners of event (all events)

You can delete all listeners or listeners of only one event.

Removing all listeners on all events
_ = bell.Remove()
Removing listeners of only the event "event_name"
_ = bell.Remove("event_name")
Wait until all events finish their work
bell.Wait()
Change events queue size (apply only for new listeners)
bell.Queue(42)
Usage without global state

You can also use the bell package without using global state. To do this, you need to create a state storage object and use it.

events := bell.New()
events.Listen("event", func(message bell.Message) {})
_ = events.Ring("event", "Hello bell!")

Examples

See full example in example_test.go.

Documentation

Overview

Package bell implements a simple event system (bell ringing and listening)

Several listeners can be added for each ringing (handlerFunc). Listeners are called in a separate goroutine through an established channel. When the bell rings, a message is sequentially transmitted to each listener.

If a channel is closed, the goroutine for that event is terminated.

Example for usage: Listen("event_name", func(message Message) { fmt.PrintLn(message) }) - add listener on bell by name "event_name" Ring("event_name", "some_data") - Ring on bell (call event "event_name")

Example
// Use via global state

event := "event_name"
event2 := "event_name_2"

// add listener on event event_name
bell.Listen(event, func(message bell.Message) {
	// we extend CustomStruct in message
	customStruct := message.(CustomStruct)
	fmt.Println(customStruct)
})
// add listener on event event_name_2
bell.Listen(event2, func(message bell.Message) {})

// get event list
list := bell.List()

// only for test
sort.Strings(list)
fmt.Println(list)

// remove listeners on event_name_2
bell.Remove(event2)

// get event list again
fmt.Println(bell.List())

// check if exists event_name_2 event in storage
fmt.Println(bell.Has(event2))

// call event event_name
_ = bell.Ring(event, CustomStruct{name: "testName", param: 12})

// wait until the event completes its work
bell.Wait()
Output:

[event_name event_name_2]
[event_name]
false
{testName 12}
Example (UsingContext)
// Use bell with context

// create a custom struct for pass a context
type Custom struct {
	ctx   context.Context
	value interface{}
}

// add listener
bell.Listen("event", func(message bell.Message) {
	for iterationsCount := 1; true; iterationsCount++ {
		select {
		case <-message.(*Custom).ctx.Done():
			return
		default:
			fmt.Printf("Iteration #%d\n", iterationsCount)
			time.Sleep(10 * time.Second)
		}
	}
})

// create a global context for all calls
globalCtx, cancelGlobalCtx := context.WithCancel(context.Background())

// create a children context for a call with timeout
ringCtx, ringCancel := context.WithTimeout(globalCtx, time.Minute)
defer ringCancel()

_ = bell.Ring("event", &Custom{ringCtx, "value"})

// wait a second for the handler to perform one iteration
time.Sleep(time.Second)

// interrupt all handlers
cancelGlobalCtx()
Output:

Iteration #1

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Has

func Has(event string) bool

Has Checks if there are listeners for the passed event

func List

func List() []string

List Returns a list of events that listeners are subscribed to

func Listen

func Listen(event string, handlerFunc func(message Message))

Listen Subscribe on event where event - the event name, handlerFunc - handler function

func ListenN added in v2.1.0

func ListenN(event string, handlerFunc func(message Message), copiesCount uint)

ListenN Subscribe on event where event - the event name, handlerFunc - handler function copiesCount - count handlers copies run

func Queue

func Queue(size uint)

Queue set events queue size

func Remove

func Remove(names ...string)

Remove Removes listeners by event name Removing listeners closes channels and stops the goroutine.

If you call the function without the "names" parameter, all listeners of all events will be removed.

func Ring

func Ring(event string, message Message) error

Ring Call event there event - event name message - data that will be passed to the event handler

func Wait

func Wait()

Wait Blocks the thread until all running events are completed

Types

type Events

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

Events thread safe structure stores events, their handlers and functions for management

Example
// Use events object (without global state)

eventName := "event_name"

// make a new events store
events := bell.New()

// add listener on event
events.Listen(eventName, func(msg bell.Message) { fmt.Println(msg) })

// call event event_name
_ = events.Ring(eventName, "Hello bell!")

// wait until the event completes its work
events.Wait()
Output:

Hello bell!

func New

func New() *Events

New constructor for Events

func (*Events) Has

func (e *Events) Has(event string) bool

Has Checks if there are listeners for the passed event

func (*Events) List

func (e *Events) List() []string

List Returns a list of events that listeners are subscribed to

func (*Events) Listen

func (e *Events) Listen(event string, handlerFunc func(message Message))

Listen Subscribe on event where event - the event name, handlerFunc - handler function

func (*Events) ListenN added in v2.1.0

func (e *Events) ListenN(event string, handlerFunc func(message Message), copiesCount uint)

ListenN Subscribe on event where event - the event name, handlerFunc - handler function copiesCount - count handlers copies run

func (*Events) Queue

func (e *Events) Queue(size uint) *Events

Queue set events queue size

func (*Events) Remove

func (e *Events) Remove(names ...string)

Remove Removes listeners by event name Removing listeners closes channels and stops the goroutine.

If you call the function without the "names" parameter, all listeners of all events will be removed.

func (*Events) Ring

func (e *Events) Ring(event string, message Message) error

Ring Call event there event - event name message - data that will be passed to the event handler

func (*Events) Wait

func (e *Events) Wait()

Wait Blocks the thread until all running events are completed

type Message

type Message interface{}

Message The message that is passed to the event handler

Jump to

Keyboard shortcuts

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