event

package module
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Dec 30, 2023 License: MIT Imports: 1 Imported by: 0

README

go-event

GoDoc Test Status codecov Go Report Card

Go simple (zero deps) library for event handling. The main goal of this library is to provide a simple and easy to use event handling system with a minimal footprint within a Go application. This library is inspired by Node.js EventEmitter.

Usage

go-event is compatible with modern Go releases. This pkg use Go generics, so you need to use Go 1.18 or later.

Take into account that each event listener is executed in a goroutine, so you need to take care with race conditions.

package main

import (
 "context"
 "log"
 "os"
 "time"

 "github.com/jferrl/go-event"
)

const (
 // UserCreated .
 UserCreated event.Event = "user.created"
 // UserDeleted .
 UserDeleted event.Event = "user.deleted"
 // UserUpdated .
 UserUpdated event.Event = "user.updated"
)

// UserEvent .
type UserEvent struct {
 ID string
}

func main() {
 logger := log.New(os.Stdout, "go-event: ", log.LstdFlags)

 ctx := context.Background()

 emitter := event.NewEmitter[UserEvent]()

 emitter.
  On(UserCreated, func(ctx context.Context, data UserEvent) {
   // handle user created event
   logger.Printf("user created: %s", data.ID)
  }).
  On(UserDeleted, func(ctx context.Context, data UserEvent) {
   // handle user deleted event
   logger.Printf("user deleted: %s", data.ID)
  }).
  On(UserUpdated,
   func(ctx context.Context, data UserEvent) {
    // handle user updated event
    logger.Printf("user updated: %s", data.ID)
   },
   func(ctx context.Context, data UserEvent) {
    // other event listener for the same event.
    logger.Printf("making some actions with user: %s", data.ID)
   },
  )

 emitter.Emit(ctx, UserCreated, UserEvent{ID: "1"})
 emitter.Emit(ctx, UserDeleted, UserEvent{ID: "2"})
 emitter.Emit(ctx, UserUpdated, UserEvent{ID: "3"})

 time.Sleep(1 * time.Second)
}

If you need to execute the event listeners synchronously, you can set SyncEmitter option.

package main

import "github.com/jferrl/go-event"

// UserEvent .
type UserEvent struct {
 ID string
}

func main() {
 emitter := event.NewEmitter[UserEvent](event.SyncEmitter[UserEvent])
}

Bootstrap complex event listeners

In some scenarios, you may need to bootstrap complex event listeners. For example, the listerner has several dependencies, like a logger, a database connection, etc. In this case, you can use a function to bootstrap the event listener and pass the dependencies to it.

package main

import (
 "context"
 "log"
 "os"
 "time"

 "github.com/jferrl/go-event"
)

// UserCreated .
const UserCreated event.Event = "user.created"

// UserEvent .
type UserEvent struct {
 ID string
}

// EmailClient handles the email scheduling.
type EmailClient struct{}

// Schedule schedules an email to be sent to the user.
func (e *EmailClient) Schedule(_ context.Context, _ string) error {
 return nil
}

// EmailScheduler handles the email scheduling.
type EmailScheduler interface {
 Schedule(ctx context.Context, userID string) error
}

// Logger handles the logging.
type Logger interface {
 Printf(format string, v ...interface{})
}

// BootstrapEmailSheduleHandler bootstraps the email scheduler handler
// Handler will be called when user created event is emitted.
// It will schedule an email to be sent to the user.
func BootstrapEmailSheduleHandler(logger Logger, s EmailScheduler) event.Listerner[UserEvent] {
 return func(ctx context.Context, data UserEvent) {
  // handle user created event
  logger.Printf("user created: %s", data.ID)

  // schedule email
  if err := s.Schedule(ctx, data.ID); err != nil {
   logger.Printf("failed to schedule email: %v", err)
  }
 }
}

func main() {
 logger := log.New(os.Stdout, "go-event: ", log.LstdFlags)
 e := &EmailClient{}

 ctx := context.Background()

 emitter := event.NewEmitter[UserEvent]()

 emitter.On(UserCreated, BootstrapEmailSheduleHandler(logger, e))

 emitter.Emit(ctx, UserCreated, UserEvent{ID: "1"})

 time.Sleep(1 * time.Second)
}

License

This library is distributed under the MIT license found in the LICENSE

Documentation

Overview

Package event .

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SyncEmitter added in v1.0.1

func SyncEmitter[T any](e *Emitter[T])

SyncEmitter configures the emitter to be synchronous. It means that listeners are executed sequentially. Default: false.

Types

type Emitter

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

Emitter emits an event with associated data.

func NewEmitter

func NewEmitter[T any](opts ...EmitterOption[T]) *Emitter[T]

NewEmitter creates a new emitter. It accepts a list of options to configure the emitter. By default, the emitter is asynchronous. It means that each listener is executed in a separate goroutine.

func (*Emitter[T]) Emit

func (e *Emitter[T]) Emit(ctx context.Context, ev Event, data T)

Emit emits an event with associated data. It does not block the caller.

func (*Emitter[T]) On

func (e *Emitter[T]) On(ev Event, l ...Listerner[T]) *Emitter[T]

On registers a callback for an event. It returns the emitter to allow chaining.

type EmitterOption added in v1.0.1

type EmitterOption[T any] func(*Emitter[T])

EmitterOption configures the emitter.

type Event

type Event string

Event defines the event type.

type Listerner

type Listerner[T any] func(context.Context, T)

Listerner defines the callback function signature.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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