Skip to content

Commit

Permalink
chore: apply Opts pattern to create a sync emitter
Browse files Browse the repository at this point in the history
  • Loading branch information
jferrl committed Dec 27, 2023
1 parent 7e16660 commit 010d6b2
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 3 deletions.
30 changes: 27 additions & 3 deletions event.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,36 @@ type Event string
// Listerner defines the callback function signature.
type Listerner[T any] func(context.Context, T)

// EmitterOption configures the emitter.
type EmitterOption[T any] func(*Emitter[T])

// SyncEmitter configures the emitter to be synchronous.
// It means that listeners are executed sequentially.
// Default: false.
func SyncEmitter[T any](e *Emitter[T]) {
e.sync = true
}

// Emitter emits an event with associated data.
type Emitter[T any] struct {
listeners map[Event][]Listerner[T]
sync bool
}

// NewEmitter creates a new emitter.
func NewEmitter[T any]() *Emitter[T] {
return &Emitter[T]{
// 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 NewEmitter[T any](opts ...EmitterOption[T]) *Emitter[T] {
e := &Emitter[T]{
listeners: make(map[Event][]Listerner[T]),
}

for _, opt := range opts {
opt(e)
}

return e
}

// On registers a callback for an event.
Expand All @@ -32,6 +52,10 @@ func (e *Emitter[T]) On(ev Event, l ...Listerner[T]) *Emitter[T] {
func (e *Emitter[T]) Emit(ctx context.Context, ev Event, data T) {
l := e.listeners[ev]
for _, f := range l {
go f(ctx, data)
if e.sync {
f(ctx, data)
} else {
go f(ctx, data)
}
}
}
16 changes: 16 additions & 0 deletions event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,22 @@ func TestEmitter_Emit(t *testing.T) {
},
eventEmmited: true,
},
{
name: "single event listerner executed synchronously",
e: NewEmitter[*eventPayload](SyncEmitter),

Check failure on line 75 in event_test.go

View workflow job for this annotation

GitHub Actions / lint

cannot use SyncEmitter (value of type func(e *Emitter[*eventPayload])) as []EmitterOption[*eventPayload] value in argument to NewEmitter[*eventPayload] (typecheck)
args: args{
ctx: ctx,
bootstrapEvent: "test",
triggerEvent: "test",
data: &eventPayload{},
},
listeners: []Listerner[*eventPayload]{
func(ctx context.Context, data *eventPayload) {
data.called = true
},
},
eventEmmited: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down

0 comments on commit 010d6b2

Please sign in to comment.