mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-26 13:43:47 +03:00
Improve godoc for contexts
This commit is contained in:
parent
1f0c061ce3
commit
1a20fe330e
2 changed files with 58 additions and 12 deletions
39
context.go
39
context.go
|
@ -10,12 +10,30 @@ import (
|
||||||
"github.com/mholt/certmagic"
|
"github.com/mholt/certmagic"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Context is a type which defines the lifetime of modules that
|
||||||
|
// are loaded and provides access to the parent configuration
|
||||||
|
// that spawned the modules which are loaded. It should be used
|
||||||
|
// with care and only wrapped with derivation functions from
|
||||||
|
// the standard context package if you don't need the Caddy
|
||||||
|
// specific features. These contexts are cancelled when the
|
||||||
|
// lifetime of the modules loaded from it are over.
|
||||||
|
//
|
||||||
|
// Use NewContext() to get a valid value (but most modules will
|
||||||
|
// not actually need to do this).
|
||||||
type Context struct {
|
type Context struct {
|
||||||
context.Context
|
context.Context
|
||||||
moduleInstances map[string][]interface{}
|
moduleInstances map[string][]interface{}
|
||||||
cfg *Config
|
cfg *Config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewContext provides a new context derived from the given
|
||||||
|
// context ctx. Normally, you will not need to call this
|
||||||
|
// function unless you are loading modules which have a
|
||||||
|
// different lifespan than the ones for the context the
|
||||||
|
// module was provisioned with. Be sure to call the cancel
|
||||||
|
// func when the context is to be cleaned up so that
|
||||||
|
// modules which are loaded will be properly unloaded.
|
||||||
|
// See standard library context package's documentation.
|
||||||
func NewContext(ctx Context) (Context, context.CancelFunc) {
|
func NewContext(ctx Context) (Context, context.CancelFunc) {
|
||||||
newCtx := Context{moduleInstances: make(map[string][]interface{}), cfg: ctx.cfg}
|
newCtx := Context{moduleInstances: make(map[string][]interface{}), cfg: ctx.cfg}
|
||||||
c, cancel := context.WithCancel(ctx.Context)
|
c, cancel := context.WithCancel(ctx.Context)
|
||||||
|
@ -36,6 +54,14 @@ func NewContext(ctx Context) (Context, context.CancelFunc) {
|
||||||
return newCtx, wrappedCancel
|
return newCtx, wrappedCancel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadModule decodes rawMsg into a new instance of mod and
|
||||||
|
// returns the value. If mod.New() does not return a pointer
|
||||||
|
// value, it is converted to one so that it is unmarshaled
|
||||||
|
// into the underlying concrete type. If mod.New is nil, an
|
||||||
|
// error is returned. If the module implements Validator or
|
||||||
|
// Provisioner interfaces, those methods are invoked to
|
||||||
|
// ensure the module is fully configured and valid before
|
||||||
|
// being used.
|
||||||
func (ctx Context) LoadModule(name string, rawMsg json.RawMessage) (interface{}, error) {
|
func (ctx Context) LoadModule(name string, rawMsg json.RawMessage) (interface{}, error) {
|
||||||
modulesMu.Lock()
|
modulesMu.Lock()
|
||||||
mod, ok := modules[name]
|
mod, ok := modules[name]
|
||||||
|
@ -74,7 +100,7 @@ func (ctx Context) LoadModule(name string, rawMsg json.RawMessage) (interface{},
|
||||||
}
|
}
|
||||||
|
|
||||||
if validator, ok := val.(Validator); ok {
|
if validator, ok := val.(Validator); ok {
|
||||||
err := validator.Validate(ctx)
|
err := validator.Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if cleanerUpper, ok := val.(CleanerUpper); ok {
|
if cleanerUpper, ok := val.(CleanerUpper); ok {
|
||||||
err2 := cleanerUpper.Cleanup()
|
err2 := cleanerUpper.Cleanup()
|
||||||
|
@ -91,6 +117,17 @@ func (ctx Context) LoadModule(name string, rawMsg json.RawMessage) (interface{},
|
||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadModuleInline loads a module from a JSON raw message which decodes
|
||||||
|
// to a map[string]interface{}, where one of the keys is moduleNameKey
|
||||||
|
// and the corresponding value is the module name as a string, which
|
||||||
|
// can be found in the given scope.
|
||||||
|
//
|
||||||
|
// This allows modules to be decoded into their concrete types and
|
||||||
|
// used when their names cannot be the unique key in a map, such as
|
||||||
|
// when there are multiple instances in the map or it appears in an
|
||||||
|
// array (where there are no custom keys). In other words, the key
|
||||||
|
// containing the module name is treated special/separate from all
|
||||||
|
// the other keys.
|
||||||
func (ctx Context) LoadModuleInline(moduleNameKey, moduleScope string, raw json.RawMessage) (interface{}, error) {
|
func (ctx Context) LoadModuleInline(moduleNameKey, moduleScope string, raw json.RawMessage) (interface{}, error) {
|
||||||
moduleName, err := getModuleNameInline(moduleNameKey, raw)
|
moduleName, err := getModuleNameInline(moduleNameKey, raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
31
modules.go
31
modules.go
|
@ -136,23 +136,32 @@ func getModuleNameInline(moduleNameKey string, raw json.RawMessage) (string, err
|
||||||
return moduleName, nil
|
return moduleName, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validator is implemented by modules which can verify that their
|
|
||||||
// configurations are valid. This method will be called after New()
|
|
||||||
// instantiations of modules (if implemented). Validation should
|
|
||||||
// always be fast (imperceptible running time) and an error should
|
|
||||||
// be returned only if the value's configuration is invalid.
|
|
||||||
type Validator interface {
|
|
||||||
Validate(Context) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Provisioner is implemented by modules which may need to perform
|
// Provisioner is implemented by modules which may need to perform
|
||||||
// some additional "setup" steps immediately after being loaded.
|
// some additional "setup" steps immediately after being loaded.
|
||||||
// This method will be called after Validate() (if implemented).
|
// Provisioning should be fast (imperceptible running time). If
|
||||||
|
// any side-effects result in the execution of this function (e.g.
|
||||||
|
// creating global state, any other allocations which require
|
||||||
|
// garbage collection, opening files, starting goroutines etc.),
|
||||||
|
// be sure to clean up properly by implementing the CleanerUpper
|
||||||
|
// interface to avoid leaking resources.
|
||||||
type Provisioner interface {
|
type Provisioner interface {
|
||||||
Provision(Context) error
|
Provision(Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: different name...
|
// Validator is implemented by modules which can verify that their
|
||||||
|
// configurations are valid. This method will be called after
|
||||||
|
// Provision() (if implemented). Validation should always be fast
|
||||||
|
// (imperceptible running time) and an error should be returned only
|
||||||
|
// if the value's configuration is invalid.
|
||||||
|
type Validator interface {
|
||||||
|
Validate() error
|
||||||
|
}
|
||||||
|
|
||||||
|
// CleanerUpper is implemented by modules which may have side-effects
|
||||||
|
// such as opened files, spawned goroutines, or allocated some sort
|
||||||
|
// of non-local state when they were provisioned. This method should
|
||||||
|
// deallocate/cleanup those resources to prevent memory leaks. Cleanup
|
||||||
|
// should be fast and efficient.
|
||||||
type CleanerUpper interface {
|
type CleanerUpper interface {
|
||||||
Cleanup() error
|
Cleanup() error
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue