mint

package module
v0.4.3 Latest Latest
Warning

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

Go to latest
Published: Jan 11, 2024 License: MIT Imports: 2 Imported by: 4

README

Mint 🍃

Tiny generic event emitter.

  • Very simple: mint has 3 exported functions and 1 type
  • Type safe: built on generics
  • Fast: does not use reflection
  • Independant: has no external dependencies
Get
go get github.com/btvoidx/mint
Use
// Create an emitter
e := new(mint.Emitter) // or &mint.Emmiter{}

// Create a consumer
func OnMyEvent(MyEvent) {
	// do stuff with the value
}

// Subscribe
off := mint.On(e, OnMyEvent)
defer off() // don't forget to unsubsribe later!

// ...

// In some other place
mint.Emit(e, MyEvent{Msg: "Hi", FromID: 1})
mint.Emit(e, MyEvent{Msg: "Hello indeed", FromID: 2})

By importing the package as "github.com/btvoidx/mint/context" you can access contextful api.

import "github.com/btvoidx/mint/context"

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()

// Not all consumers may receive the message due to timeout,
// but Emit does wait for the active consumer to finish.
err := mint.Emit(e, ctx, MyEvent{Msg: "A message"})

// err is always ctx.Err()
if err != ctx.Err() {	/* unreachable code */ }

Both versions can operate on the same mint.Emitter instance, as contextless api just wraps the contextful one with context.Background().

// MyEvent consumers will receive both events.
mintctx.Emit(e, ctx, MyEvent{Msg: "A message"})
mint.Emit(e, MyEvent{Msg: "A message"}) // uses context.Background()

If you prefer channel-based consumers you can create a wrapper for mint.On so that it forwards all data to a channel.

func MyOn[T any](e *mint.Emitter) (<-ch T, off func()) {
	ch := make(chan T)
	off := mint.On(e, func(v T) {
		go func() { ch <- v }
	})

	return ch, func() {
		off()
		// drain channel so pending emits don't panic
		for {
			select {
			case <-ch:
			default:
				close(ch)
				return
			}
		}
	}
}

// Use it like so
ch, off := MyOn[MyEvent](e)
defer off()

for event := range ch {
	// deal with incoming data
}

For additional examples see mint_test.go.

Reporting issues

If you have questions or problems just open a new issue.

Contributing

This project uses lowercase commit messages. Pull requests containing commits starting with capital letters must be rebased to change commit messages.

Documentation

Overview

Package mint provides a tiny generic event emitter. Version under mint/context exposes context api.

e := new(mint.Emitter) // create an emitter
mint.On(e, func(MyEvent)) // subscribe to MyEvent
mint.Emit(e, MyEvent{ ... }) // emit values to consumers

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Emit

func Emit[T any](e *Emitter, v T)

Emit Sequentially pushes value v to all consumers of type T. Receive order is indetermenistic.

func On

func On[T any](e *Emitter, fn func(T)) (off func() <-chan struct{})

On Registers a new consumer that receives all values which were emitted as T. So that On(e, func(any)) will receive all values emitted with Emit[any](e, ...)

Call to off schedules consumer to stop once all concurrent Emits stop and returns a <-chan which will get closed once it is done. It is possible for consumer to receive values after a call to stop if other concurrent emits are ongoing.

func Use

func Use(e *Emitter, plugin func(any) func())

Use allows to hook into event emitting process. Plugins are called sequentially in order they were added to Emitter. Plugin is a function that takes Emitted values and returns nil or a function that will be called after all consumers got the Emitted value. Returned functions are called in reverse order via `defer` statement.

Types

type Emitter

type Emitter = cm.Emitter

Emitter holds all active consumers and Emit hooks.

Directories

Path Synopsis
Package mint provides a tiny generic event emitter.
Package mint provides a tiny generic event emitter.

Jump to

Keyboard shortcuts

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