mitto

package module
v0.0.7 Latest Latest
Warning

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

Go to latest
Published: Apr 17, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

README

mitto

mitto provides a simple API around application event handling

Build Status codecov.io Go Report Card Apache V2 License Quality Gate Status PkgGoDev

Summary

mitto (Latin verb meaning "to send") implements a simple way to manage a set of listeners and dispatch application events to those listeners. mitto is primarily intended for code which sends events to clients, where clients supply one or more listeners.

Table of Contents

Usage

Basic

The easiest way to use mitto is to include it in a type that manages events and listeners:

import github.com/xmidt-org/mitto

type Event {
    // stuff
}

type MyListener interface {
    OnEvent(Event)
}

type MyService struct {
    // could also use mitto.Set if concurrency is
    // managed by MyService or some other means.
    listeners mitto.SyncSet[Event]
}

func (s *MyService) Add(l ...MyListener) {
    mitto.Add(&s.listeners, l...)
}

func (s *MyService) Remove(l ...MyListener) {
    mitto.Remove(&s.listeners, l...)
}

func (s *MyService) DoSomething() {
    // time to send an event:
    s.listeners.Send(Event{
        // stuff
    })
}
AsListener

mitto provides AsListener to convert other common types into listeners.

f := func(event Event) { /* ... */ }
ch := make(chan Event, 10)

s.listeners.Add(
    mitto.AsListener[Event](f),
    mitto.AsListener[Event](ch),
)
Important note on channels

A client is responsible for ensuring that a channel is properly managed to reduce or avoid blocking. In addition, a client must remove the channel listener before closing the channel, otherwise Send may panic.

ch := make(chan Event, 10)
l := AsListener[Event](ch)
s.listeners.Add(l)

// remove the listener BEFORE closing the channel
s.listeners.Remove(l)
close(ch)
Adapting custom Listener interfaces

AsListener can also be used to adapt a different listener interface or type.

type DifferentListener interface {
    OnStartEvent(Event)
}

func (s *MyService) AddDifferentListener(l DifferentListener) {
    s.listeners.Add(
        mitto.AsListener[Event](
            l.OnStartEvent,
        ),
    )
}

Code of Conduct

This project and everyone participating in it are governed by the XMiDT Code Of Conduct. By participating, you agree to this Code.

Install

go get github.com/xmidt-org/mitto@latest

Contributing

Refer to CONTRIBUTING.md.

Documentation

Overview

Package mitto offers a simple listener API for application events.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Add added in v0.0.4

func Add[E any, L Listener[E]](d Dispatcher[E], ls ...L)

Add adds custom listeners to a dispatcher. The custom listener type can be anything that implements Listener[E], rather than being exactly Listener[E].

func Remove added in v0.0.4

func Remove[E any, L Listener[E]](d Dispatcher[E], ls ...L)

Remove removes custom listeners from a dispatcher. The custom listener type can be anything that implements Listener[E], rather than being exactly Listener[E].

Types

type Dispatcher

type Dispatcher[E any] interface {
	// Clear removes all listeners from this dispatcher.
	Clear()

	// Add adds listeners to this Dispatcher.
	//
	// A caller must take care to ensure that any added listener that
	// could be removed later should be comparable. In particular, functions
	// in golang are NOT comparable. Thus, a function that implements the
	// Listener[E] interface cannot be passed to Remove.
	Add(...Listener[E])

	// Remove removes listeners from this dispatcher. Only listeners
	// that are comparable may be removed. In particular, closure types which
	// implement Listener[E] cannot be used with this method.
	Remove(...Listener[E])

	// Send dispatches the event to all listeners currently associated
	// with this dispatcher.
	Send(E)
}

Dispatcher is the common interface for anything which can manage a collection of Listeners and dispatch events to them.

A Dispatcher does not guarantee any ordering for listeners. In particular, the order in which listeners were added is not necessarily the order in which they will be called.

A Dispatcher implementation must be safe for concurrent access. Any of the methods on this interface may be called concurrently at any time.

type Listener

type Listener[E any] interface {
	// OnEvent allows this listener to receive the given event.
	// This method must not panic, and it must not call any methods
	// on the containing Dispatcher.
	//
	// This method may be called concurrently from different goroutines.
	OnEvent(E)
}

Listener is a sink for events.

func AsListener

func AsListener[E any, S Sink[E]](sink S) Listener[E]

AsListener converts a Sink into a Listener. If the supplied sink is nil, this function returns nil. The returned Listener is always comparable and can be passed to Dispatcher.Remove.

For channels, the returned listener will block if the underlying channel blocks. Clients must create and manage channels to reduce or avoid blocking. Additionally, if a client wants to close the channel, care must be taken to remove it first to avoid panics.

type Set added in v0.0.4

type Set[E any] struct {
	// contains filtered or unexported fields
}

Set is a Dispatcher backed by a simple slice of Listener. The zero value for this type is ready to use.

A Set is not safe for concurrent use. This type can be used in situations where concurrent safety is guaranteed by containing code or where concurrency isn't an issue.

func (*Set[E]) Add added in v0.0.4

func (s *Set[E]) Add(toAdd ...Listener[E])

Add appends listeners to this set. Any nil listeners are skipped.

AsListener can be used to convert closures and channels into listeners to pass to this method.

Example
var s Set[int] // int is just an example, this could be a struct
s.Add(
	AsListener[int](func(event int) {
		fmt.Println(event)
	}),
)

s.Send(999)
Output:
999

func (*Set[E]) Clear added in v0.0.4

func (s *Set[E]) Clear()

Clear removes all listeners from this set.

func (*Set[E]) Remove added in v0.0.4

func (s *Set[E]) Remove(toRemove ...Listener[E])

Remove deletes the given listeners. Nil listeners and listeners that are not part of this set are ignored.

func (*Set[E]) Send added in v0.0.4

func (s *Set[E]) Send(e E)

Send dispatches an event to all contained listeners. Listener implementations should be prepared to receive events concurrently.

type Sink added in v0.0.3

type Sink[E any] interface {
	~func(E) | ~chan E | ~chan<- E
}

Sink is a constraint for types that can be used as Listeners.

type SyncSet added in v0.0.4

type SyncSet[E any] struct {
	// contains filtered or unexported fields
}

SyncSet is a Dispatcher backed by a slice of Listener and is safe for concurrent access. A SyncSet must not be copied after creation.

The zero value for this type is ready to use.

func (*SyncSet[E]) Add added in v0.0.4

func (ss *SyncSet[E]) Add(toAdd ...Listener[E])

Add adds more listeners. This method ensures that no event can be sent until adding these listeners completes.

Example
var ss SyncSet[int] // int is just an example, this could be a struct
ss.Add(
	AsListener[int](func(event int) {
		fmt.Println(event)
	}),
)

ss.Send(999)
Output:
999

func (*SyncSet[E]) Clear added in v0.0.4

func (ss *SyncSet[E]) Clear()

Clear removes all listeners. Send will block until this method completes.

func (*SyncSet[E]) Remove added in v0.0.4

func (ss *SyncSet[E]) Remove(toRemove ...Listener[E])

Remove removes the given listeners. This method ensures that no event can be sent until removing these listeners completes.

func (*SyncSet[E]) Send added in v0.0.4

func (ss *SyncSet[E]) Send(e E)

Send dispatches the given event to the contained listeners. Multiple goroutines can invoke this method concurrently. While an event is being sent, any method that would alter the set of Listeners is blocked.

Listener implementations must be prepared to receive events concurrently. This method does not make any guarantees about the concurrent safety of the contained Listeners.

Jump to

Keyboard shortcuts

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