Skip to content

Commit d4d8bbc

Browse files
francislavoiemholt
andauthored
events: Implement event system (#4912)
Co-authored-by: Matt Holt <[email protected]>
1 parent 68d8ac9 commit d4d8bbc

File tree

13 files changed

+569
-34
lines changed

13 files changed

+569
-34
lines changed

context.go

+52-16
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,10 @@ import (
3737
// not actually need to do this).
3838
type Context struct {
3939
context.Context
40-
moduleInstances map[string][]any
40+
moduleInstances map[string][]Module
4141
cfg *Config
4242
cleanupFuncs []func()
43+
ancestry []Module
4344
}
4445

4546
// NewContext provides a new context derived from the given
@@ -51,7 +52,7 @@ type Context struct {
5152
// modules which are loaded will be properly unloaded.
5253
// See standard library context package's documentation.
5354
func NewContext(ctx Context) (Context, context.CancelFunc) {
54-
newCtx := Context{moduleInstances: make(map[string][]any), cfg: ctx.cfg}
55+
newCtx := Context{moduleInstances: make(map[string][]Module), cfg: ctx.cfg}
5556
c, cancel := context.WithCancel(ctx.Context)
5657
wrappedCancel := func() {
5758
cancel()
@@ -90,15 +91,15 @@ func (ctx *Context) OnCancel(f func()) {
9091
// ModuleMap may be used in place of map[string]json.RawMessage. The return value's
9192
// underlying type mirrors the input field's type:
9293
//
93-
// json.RawMessage => any
94-
// []json.RawMessage => []any
95-
// [][]json.RawMessage => [][]any
96-
// map[string]json.RawMessage => map[string]any
97-
// []map[string]json.RawMessage => []map[string]any
94+
// json.RawMessage => any
95+
// []json.RawMessage => []any
96+
// [][]json.RawMessage => [][]any
97+
// map[string]json.RawMessage => map[string]any
98+
// []map[string]json.RawMessage => []map[string]any
9899
//
99100
// The field must have a "caddy" struct tag in this format:
100101
//
101-
// caddy:"key1=val1 key2=val2"
102+
// caddy:"key1=val1 key2=val2"
102103
//
103104
// To load modules, a "namespace" key is required. For example, to load modules
104105
// in the "http.handlers" namespace, you'd put: `namespace=http.handlers` in the
@@ -115,7 +116,7 @@ func (ctx *Context) OnCancel(f func()) {
115116
// meaning the key containing the module's name that is defined inline with the module
116117
// itself. You must specify the inline key in a struct tag, along with the namespace:
117118
//
118-
// caddy:"namespace=http.handlers inline_key=handler"
119+
// caddy:"namespace=http.handlers inline_key=handler"
119120
//
120121
// This will look for a key/value pair like `"handler": "..."` in the json.RawMessage
121122
// in order to know the module name.
@@ -301,17 +302,17 @@ func (ctx Context) loadModuleMap(namespace string, val reflect.Value) (map[strin
301302
// like from embedded scripts, etc.
302303
func (ctx Context) LoadModuleByID(id string, rawMsg json.RawMessage) (any, error) {
303304
modulesMu.RLock()
304-
mod, ok := modules[id]
305+
modInfo, ok := modules[id]
305306
modulesMu.RUnlock()
306307
if !ok {
307308
return nil, fmt.Errorf("unknown module: %s", id)
308309
}
309310

310-
if mod.New == nil {
311-
return nil, fmt.Errorf("module '%s' has no constructor", mod.ID)
311+
if modInfo.New == nil {
312+
return nil, fmt.Errorf("module '%s' has no constructor", modInfo.ID)
312313
}
313314

314-
val := mod.New().(any)
315+
val := modInfo.New()
315316

316317
// value must be a pointer for unmarshaling into concrete type, even if
317318
// the module's concrete type is a slice or map; New() *should* return
@@ -327,7 +328,7 @@ func (ctx Context) LoadModuleByID(id string, rawMsg json.RawMessage) (any, error
327328
if len(rawMsg) > 0 {
328329
err := strictUnmarshalJSON(rawMsg, &val)
329330
if err != nil {
330-
return nil, fmt.Errorf("decoding module config: %s: %v", mod, err)
331+
return nil, fmt.Errorf("decoding module config: %s: %v", modInfo, err)
331332
}
332333
}
333334

@@ -340,6 +341,8 @@ func (ctx Context) LoadModuleByID(id string, rawMsg json.RawMessage) (any, error
340341
return nil, fmt.Errorf("module value cannot be null")
341342
}
342343

344+
ctx.ancestry = append(ctx.ancestry, val)
345+
343346
if prov, ok := val.(Provisioner); ok {
344347
err := prov.Provision(ctx)
345348
if err != nil {
@@ -351,7 +354,7 @@ func (ctx Context) LoadModuleByID(id string, rawMsg json.RawMessage) (any, error
351354
err = fmt.Errorf("%v; additionally, cleanup: %v", err, err2)
352355
}
353356
}
354-
return nil, fmt.Errorf("provision %s: %v", mod, err)
357+
return nil, fmt.Errorf("provision %s: %v", modInfo, err)
355358
}
356359
}
357360

@@ -365,7 +368,7 @@ func (ctx Context) LoadModuleByID(id string, rawMsg json.RawMessage) (any, error
365368
err = fmt.Errorf("%v; additionally, cleanup: %v", err, err2)
366369
}
367370
}
368-
return nil, fmt.Errorf("%s: invalid configuration: %v", mod, err)
371+
return nil, fmt.Errorf("%s: invalid configuration: %v", modInfo, err)
369372
}
370373
}
371374

@@ -439,8 +442,10 @@ func (ctx Context) Storage() certmagic.Storage {
439442
return ctx.cfg.storage
440443
}
441444

445+
// TODO: aw man, can I please change this?
442446
// Logger returns a logger that can be used by mod.
443447
func (ctx Context) Logger(mod Module) *zap.Logger {
448+
// TODO: if mod is nil, use ctx.Module() instead...
444449
if ctx.cfg == nil {
445450
// often the case in tests; just use a dev logger
446451
l, err := zap.NewDevelopment()
@@ -451,3 +456,34 @@ func (ctx Context) Logger(mod Module) *zap.Logger {
451456
}
452457
return ctx.cfg.Logging.Logger(mod)
453458
}
459+
460+
// TODO: use this
461+
// // Logger returns a logger that can be used by the current module.
462+
// func (ctx Context) Log() *zap.Logger {
463+
// if ctx.cfg == nil {
464+
// // often the case in tests; just use a dev logger
465+
// l, err := zap.NewDevelopment()
466+
// if err != nil {
467+
// panic("config missing, unable to create dev logger: " + err.Error())
468+
// }
469+
// return l
470+
// }
471+
// return ctx.cfg.Logging.Logger(ctx.Module())
472+
// }
473+
474+
// Modules returns the lineage of modules that this context provisioned,
475+
// with the most recent/current module being last in the list.
476+
func (ctx Context) Modules() []Module {
477+
mods := make([]Module, len(ctx.ancestry))
478+
copy(mods, ctx.ancestry)
479+
return mods
480+
}
481+
482+
// Module returns the current module, or the most recent one
483+
// provisioned by the context.
484+
func (ctx Context) Module() Module {
485+
if len(ctx.ancestry) == 0 {
486+
return nil
487+
}
488+
return ctx.ancestry[len(ctx.ancestry)-1]
489+
}

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ require (
77
github.com/Masterminds/sprig/v3 v3.2.2
88
github.com/alecthomas/chroma v0.10.0
99
github.com/aryann/difflib v0.0.0-20210328193216-ff5ff6dc229b
10-
github.com/caddyserver/certmagic v0.16.3
10+
github.com/caddyserver/certmagic v0.17.0
1111
github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac
1212
github.com/go-chi/chi v4.1.2+incompatible
1313
github.com/google/cel-go v0.12.4

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
131131
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
132132
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
133133
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
134-
github.com/caddyserver/certmagic v0.16.3 h1:1ZbiU7y5X0MnDjBTXywUbPMs/ScHbgCeeCy/LPh4IZk=
135-
github.com/caddyserver/certmagic v0.16.3/go.mod h1:pSS2aZcdKlrTZrb2DKuRafckx20o5Fz1EdDKEB8KOQM=
134+
github.com/caddyserver/certmagic v0.17.0 h1:AHHvvmv6SNcq0vK5BgCevQqYMV8GNprVk6FWZzx8d+Q=
135+
github.com/caddyserver/certmagic v0.17.0/go.mod h1:pSS2aZcdKlrTZrb2DKuRafckx20o5Fz1EdDKEB8KOQM=
136136
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
137137
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
138138
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=

0 commit comments

Comments
 (0)