@marcel91200 / caddy Mirror · read-only / commits / 0950ba4f
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 13, 11:45 UTC

events: Make event data exported

This could lead to bugs if handlers are not careful, but it is surely useful. We'll see how it goes, what the feedback is like, etc.

Matthew Holt committed Sep 19, 2022 at 16:20 UTC 0950ba4f0b77f2a9134188386345fccdfddb80ad
1 file changed +28 -11
modules/caddyevents/app.go
+28 -11
@@ -201,6 +201,9 @@ func (app *App) On(eventName string, handler Handler) error {
201 // Emit creates and dispatches an event named eventName to all relevant handlers with
202 // the metadata data. Events are emitted and propagated synchronously. The returned Event
203 // value will have any additional information from the invoked handlers.
204 +//
205 +// Note that the data map is not copied, for efficiency. After Emit() is called, the
206 +// data passed in should not be changed in other goroutines.
207 func (app *App) Emit(ctx caddy.Context, eventName string, data map[string]any) Event {
208 logger := app.logger.With(zap.String("name", eventName))
209
@@ -212,11 +215,11 @@ func (app *App) Emit(ctx caddy.Context, eventName string, data map[string]any) E
215 eventName = strings.ToLower(eventName)
216
217 e := Event{
218 + Data: data,
219 id: id,
220 ts: time.Now(),
221 name: eventName,
222 origin: ctx.Module(),
219 - data: data,
223 }
224
225 logger = logger.With(
@@ -244,12 +247,12 @@ func (app *App) Emit(ctx caddy.Context, eventName string, data map[string]any) E
247 case "event.module":
248 return e.origin.CaddyModule().ID, true
249 case "event.data":
247 - return e.data, true
250 + return e.Data, true
251 }
252
253 if strings.HasPrefix(key, "event.data.") {
254 key = strings.TrimPrefix(key, "event.data.")
252 - if val, ok := data[key]; ok {
255 + if val, ok := e.Data[key]; ok {
256 return val, true
257 }
258 }
@@ -257,7 +260,7 @@ func (app *App) Emit(ctx caddy.Context, eventName string, data map[string]any) E
260 return nil, false
261 })
262
260 - logger.Debug("event", zap.Any("data", e.data))
263 + logger.Debug("event", zap.Any("data", e.Data))
264
265 // invoke handlers bound to the event by name and also all events; this for loop
266 // iterates twice at most: once for the event name, once for "" (all events)
@@ -314,26 +317,40 @@ func (app *App) Emit(ctx caddy.Context, eventName string, data map[string]any) E
317 }
318
319 // Event represents something that has happened or is happening.
320 +// An Event value is not synchronized, so it should be copied if
321 +// being used in goroutines.
322 +//
323 +// EXPERIMENTAL: As with the rest of this package, events are
324 +// subject to change.
325 type Event struct {
318 - id uuid.UUID
319 - ts time.Time
320 - name string
321 - origin caddy.Module
322 - data map[string]any
323 -
326 // If non-nil, the event has been aborted, meaning
327 // propagation has stopped to other handlers and
328 // the code should stop what it was doing. Emitters
329 // may choose to use this as a signal to adjust their
330 // code path appropriately.
331 Aborted error
332 +
333 + // The data associated with the event. Usually the
334 + // original emitter will be the only one to set or
335 + // change these values, but the field is exported
336 + // so handlers can have full access if needed.
337 + // However, this map is not synchronized, so
338 + // handlers must not use this map directly in new
339 + // goroutines; instead, copy the map to use it in a
340 + // goroutine.
341 + Data map[string]any
342 +
343 + id uuid.UUID
344 + ts time.Time
345 + name string
346 + origin caddy.Module
347 }
348
349 // CloudEvent exports event e as a structure that, when
350 // serialized as JSON, is compatible with the
351 // CloudEvents spec.
352 func (e Event) CloudEvent() CloudEvent {
336 - dataJSON, _ := json.Marshal(e.data)
353 + dataJSON, _ := json.Marshal(e.Data)
354 return CloudEvent{
355 ID: e.id.String(),
356 Source: e.origin.CaddyModule().String(),