emitter

package module
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 19, 2022 License: MIT Imports: 3 Imported by: 2

README

Emitter godoc

The emitter package implements a channel-based pubsub pattern. The design goals are to use Golang concurrency model instead of flat callbacks and to design a very simple API that is easy to consume.

This was a fork of https://github.com/olebedev/emitter but code heavily changed to implement listener handler pattern, give ability to set any type of event and finally allow generics usage. Groups have been removed as they are not used in this project.

What it does?

Brief example

package main

import (
 "fmt"
 "github.com/ArthurHlt/emitter"
)

func main(){
	e := emitter.New(10)
    
	// simple
    e.On("change_any", emitter.ListenerFunc(func(event emitter.Event) {
        fmt.Println(event.Topic())
        fmt.Println(event.Subject())
    }))
    <-e.Emit(emitter.NewEvent("change_any", 2)) // wait for the event sent successfully
    <-e.Emit(emitter.NewEvent("change_any", 37))
	
	// with generics
	e.On("change_any", emitter.ListenerFuncOf[string](func(event *emitter.EventOf[string]) {
        fmt.Println(event.Topic())
        fmt.Println(event.TypedSubject())
    }))
	
    e.Off("*") // unsubscribe any listeners
    // listener channel was closed
}

Constructor

emitter.New takes a uint as the first argument to indicate what buffer size should be used for listeners. It is also possible to change the buffer capacity during runtime using the following code: e.Cap = 10.

Wildcard

The package allows publications and subscriptions with wildcard. This feature is based on path.Match function.

Example:

e.Once("*", emitter.ListenerFunc(func(event emitter.Event) {
    fmt.Println(event.Topic())
    fmt.Println(event.Subject()) // show 42 and after 37
}))
e.Emit(emitter.NewEvent("something:special", 42))
e.Emit(emitter.NewEvent("*", 37))

Note that the wildcard uses path.Match, but the lib does not return errors related to parsing for this is not the main feature. Please check the topic specifically via emitter.Test() function.

Middlewares

An important part of pubsub package is the predicates. It should be allowed to skip some events. Middlewares address this problem. The middleware is a function that takes a pointer to the Event as its first argument. A middleware is capable of doing the following items:

  1. It allows you to modify an event.
  2. It allows skipping the event emitting if needed.
  3. It also allows modification of the event's arguments.
  4. It allows you to specify the mode to describe how exactly an event should be emitted(see below).

There are two ways to add middleware into the event emitting flow:

  • via .On("event", listener, middlewares...)
  • via .Use("event", middlewares...)

The first one add middlewares only for a particular listener, while the second one adds middlewares for all events with a given topic.

For example:

// use synchronous mode for all events, it also depends
// on the emitter capacity(buffered/unbuffered channels)
e.Use("*", emitter.Void)

e.Once("*", emitter.ListenerFunc(func(event emitter.Event) {
	// nothing will never printed
    fmt.Println(event.Topic())
    fmt.Println(event.Subject())
}))
e.Emit(emitter.NewEvent("something:special", 42))

Flags

Flags needs to describe how exactly the event should be emitted. The available options are listed here.

Every event(emitter.Event) has a field called.Flags that contains flags as a binary mask. Flags can be set only via middlewares(see above).

There are several predefined middlewares to set needed flags:

You can chain the above flags as shown below:

e.Use("*", emitter.Void) // skip sending for any events

event := <-e.On("*", emitter.ListenerFunc(func(event emitter.Event) {
            // nothing will never printed
            fmt.Println(event.Topic())
            fmt.Println(event.Subject())
        }),
        emitter.Once) // set custom flags for this listener

e.Emit(emitter.NewEvent("surprise", 65536))

Event

Event is an interface used to pass events to listeners.

It contains the following methods:

type Event interface {
	// Topic returns the topic of the event.
	Topic() string
	// Flag returns the flag of the event.
	Flag() Flag
	// SetFlag sets the flag of the event.
	SetFlag(Flag)
	// Subject returns the subject of the event.
	Subject() any
	// Clone returns a copy of the event.
	Clone() Event
}

You can provide your own event implementation by implementing the Event interface.

By default you have 2 implementations:

  • emitter.BasicEvent - a simple event implementation created with emitter.NewEvent
  • emitter.EventOf - a generic event implementation created with emitter.NewEventOf

Documentation

Overview

Package emitter implements channel based pubsub pattern. The design goals are:

  • fully functional and safety
  • simple to understand and use
  • make the code readable, maintainable and minimalistic

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Once

func Once(e Event)

Once middleware sets FlagOnce flag for an event

func Skip

func Skip(e Event)

Skip middleware sets FlagSkip flag for an event

func Test

func Test(pattern string) bool

Test returns boolean value to indicate that given pattern is valid.

What is it for? Internally `emitter` uses `path.Match` function to find matching. But as this functionality is optional `Emitter` don't indicate that the pattern is invalid. You should check it separately explicitly via `Test` function.

func Void

func Void(e Event)

Void middleware sets FlagVoid flag for an event

Types

type BasicEvent

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

func NewEvent

func NewEvent(topic string, subject any) *BasicEvent

func (*BasicEvent) Clone

func (e *BasicEvent) Clone() Event

func (*BasicEvent) Flag

func (e *BasicEvent) Flag() Flag

func (*BasicEvent) SetFlag

func (e *BasicEvent) SetFlag(flag Flag)

func (*BasicEvent) Subject

func (e *BasicEvent) Subject() any

func (*BasicEvent) Topic

func (e *BasicEvent) Topic() string

type Emitter

type Emitter struct {
	Cap uint
	// contains filtered or unexported fields
}

Emitter is a struct that allows to emit, receive event, close receiver channel, get info about topics and listMans

func New

func New(capacity uint) *Emitter

New returns just created Emitter struct. Capacity argument will be used to create channels with given capacity

func (*Emitter) Emit

func (e *Emitter) Emit(event Event) chan struct{}

Emit emits an event with the rest arguments to all listMans which were covered by topic(it can be pattern).

func (*Emitter) Listeners

func (e *Emitter) Listeners(topic string) []Listener

Listeners returns slice of listMans which were covered by topic(it can be pattern) and error if pattern is invalid.

func (*Emitter) Off

func (e *Emitter) Off(topic string, listeners ...Listener)

Off unsubscribes all listMans which were covered by topic, it can be pattern as well.

func (*Emitter) On

func (e *Emitter) On(topic string, listener Listener, middlewares ...func(Event))

On returns a channel that will receive events. As optional second argument it takes middlewares.

func (*Emitter) Once

func (e *Emitter) Once(topic string, listener Listener, middlewares ...func(Event))

Once works exactly like On(see above) but with `Once` as the first middleware.

func (*Emitter) Topics

func (e *Emitter) Topics() []string

Topics returns all existing topics.

func (*Emitter) Use

func (e *Emitter) Use(pattern string, middlewares ...func(Event))

Use registers middlewares for the pattern.

type Event

type Event interface {
	// Topic returns the topic of the event.
	Topic() string
	// Flag returns the flag of the event.
	Flag() Flag
	// SetFlag sets the flag of the event.
	SetFlag(Flag)
	// Subject returns the subject of the event.
	Subject() any
	// Clone returns a copy of the event.
	Clone() Event
}

Event is an interface used to pass events to listeners.

type EventOf

type EventOf[T any] struct {
	// contains filtered or unexported fields
}

func NewEventOf

func NewEventOf[T any](topic string, subject T) *EventOf[T]

func (*EventOf[T]) Clone

func (e *EventOf[T]) Clone() Event

func (*EventOf[T]) Flag

func (e *EventOf[T]) Flag() Flag

func (*EventOf[T]) SetFlag

func (e *EventOf[T]) SetFlag(flag Flag)

func (*EventOf[T]) Subject

func (e *EventOf[T]) Subject() any

func (*EventOf[T]) Topic

func (e *EventOf[T]) Topic() string

func (*EventOf[T]) TypedSubject

func (e *EventOf[T]) TypedSubject() T

type Flag

type Flag int

Flag used to describe what behavior do you expect.

const (
	// FlagOnce indicates to remove the listener after first sending.
	FlagOnce Flag = 1 << iota
	// FlagVoid indicates to skip sending.
	FlagVoid
	// FlagSkip indicates to skip sending if channel is blocked.
	FlagSkip
)

type Listener

type Listener interface {
	Observe(Event)
}

type ListenerFunc

type ListenerFunc func(Event)

func (ListenerFunc) Observe added in v1.1.0

func (fn ListenerFunc) Observe(e Event)

type ListenerFuncOf

type ListenerFuncOf[T any] func(*EventOf[T])

func (ListenerFuncOf[T]) Observe added in v1.1.0

func (fn ListenerFuncOf[T]) Observe(e Event)

Jump to

Keyboard shortcuts

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