@@ -12,40 +12,48 @@ import (
12
12
"github.com/modernice/goes/internal/concurrent"
13
13
)
14
14
15
- // ErrRunning is returned when trying to run a *Handler that is already running.
15
+ // ErrRunning is the error returned when trying to run an event handler that is
16
+ // already running.
16
17
var ErrRunning = errors .New ("event handler is already running" )
17
18
18
- // A Handler asynchronously handles published events.
19
- //
20
- // var bus event.Bus
21
- // h := handler.New(bus)
22
- // event.HandleWith(h, func(evt event.Of[FooData]) {...}, "foo")
23
- // event.HandleWith(h, func(evt event.Of[BarData]) {...}, "bar")
24
- //
25
- // errs, err := h.Run(context.TODO())
19
+ // Handler is responsible for managing the registration and execution of event
20
+ // handlers in response to incoming events. It maintains a map of registered
21
+ // event handlers and listens to an event bus for events that match registered
22
+ // handler names. When such an event occurs, the corresponding handler function
23
+ // is invoked. Handler also provides support for querying stored events from an
24
+ // event store, and it can run concurrently, with its execution state being
25
+ // controlled through a provided context.
26
26
type Handler struct {
27
27
bus event.Bus
28
- store event.Store // optional
28
+ store event.Store
29
29
30
30
mux sync.RWMutex
31
31
handlers map [string ]func (event.Event )
32
32
eventNames map [string ]struct {}
33
33
ctx context.Context
34
34
}
35
35
36
- // Option is a handler option.
36
+ // Option is a function that modifies the configuration of a [Handler]. It
37
+ // provides a way to set optional parameters when creating a new [Handler]. This
38
+ // approach is used to avoid constructor cluttering when there are many
39
+ // configurations possible for a [Handler].
37
40
type Option func (* Handler )
38
41
39
- // WithStore returns an Option that makes a Handler query the registered events
40
- // from the provided store on startup and handle them as if they were published
41
- // over the underlying event bus. This allows to handle "past" events on startup .
42
+ // WithStore is a function that returns an Option which, when applied to a
43
+ // Handler, sets the event.Store of that Handler. This is used to configure
44
+ // where the Handler stores events.
42
45
func WithStore (store event.Store ) Option {
43
46
return func (h * Handler ) {
44
47
h .store = store
45
48
}
46
49
}
47
50
48
- // New returns an event handler for published events.
51
+ // New creates a new Handler with the provided event bus and applies the given
52
+ // options. The bus parameter is used to subscribe to events and distribute them
53
+ // to registered event handlers. Options can be used to configure the Handler,
54
+ // for example to specify an event store where past events are queried from on
55
+ // startup. The returned Handler is not running and must be started with the Run
56
+ // method.
49
57
func New (bus event.Bus , opts ... Option ) * Handler {
50
58
h := & Handler {
51
59
bus : bus ,
@@ -58,40 +66,53 @@ func New(bus event.Bus, opts ...Option) *Handler {
58
66
return h
59
67
}
60
68
61
- // RegisterEventHandler registers the handler for the given event.
62
- // Events must be registered before h.Run() is called. Events that are
63
- // registered after h.Run() has been called, won't be handled.
69
+ // RegisterEventHandler registers an event handler function for the given event
70
+ // name. The event handler function, which takes an [event.Event] as a
71
+ // parameter, will be called whenever an event with the registered name occurs.
72
+ // The function is thread-safe and can be called concurrently.
64
73
func (h * Handler ) RegisterEventHandler (name string , fn func (event.Event )) {
65
74
h .mux .Lock ()
66
75
defer h .mux .Unlock ()
67
76
h .handlers [name ] = fn
68
77
h .eventNames [name ] = struct {}{}
69
78
}
70
79
71
- // EventHandler returns the event handler for the given event name.
80
+ // EventHandler retrieves the event handling function associated with the
81
+ // provided name. The function returned is responsible for processing an event
82
+ // of that name. If no handler is found for the given name, a nil function and
83
+ // false are returned.
72
84
func (h * Handler ) EventHandler (name string ) (func (event.Event ), bool ) {
73
85
h .mux .RLock ()
74
86
defer h .mux .RUnlock ()
75
87
fn , ok := h .handlers [name ]
76
88
return fn , ok
77
89
}
78
90
79
- // Context returns the context that was passed to h.Run(). If h.Run() has not
80
- // been called yet, nil is returned.
91
+ // Context returns the context of the Handler. This context is set when the Run
92
+ // method is called and is used to control the lifecycle of the Handler. It's
93
+ // protected by a read-write lock, ensuring safe concurrent access.
81
94
func (h * Handler ) Context () context.Context {
82
95
h .mux .RLock ()
83
96
defer h .mux .RUnlock ()
84
97
return h .ctx
85
98
}
86
99
87
- // Running returns whether the handler is currently running.
100
+ // Running checks if the Handler is currently running. It returns true if the
101
+ // Handler has been started and not yet stopped, otherwise it returns false. The
102
+ // context of the Handler is used to determine its state. If the context is not
103
+ // nil, it indicates that the Handler is running.
88
104
func (h * Handler ) Running () bool {
89
105
h .mux .RLock ()
90
106
defer h .mux .RUnlock ()
91
107
return h .ctx != nil
92
108
}
93
109
94
- // Run runs the handler until ctx is canceled.
110
+ // Run starts the event handler with the provided context. It subscribes to all
111
+ // registered events on the event bus and begins handling incoming events. If
112
+ // the event handler has an event store, it also handles all stored events. If
113
+ // the handler is already running, it returns an error. The function returns a
114
+ // channel for errors that may occur during event handling and an error if there
115
+ // was an issue starting the handler.
95
116
func (h * Handler ) Run (ctx context.Context ) (<- chan error , error ) {
96
117
h .mux .Lock ()
97
118
defer h .mux .Unlock ()
0 commit comments