mirror of
https://github.com/caddyserver/caddy.git
synced 2025-05-28 14:45:49 +08:00
events: Refactor; move Event into core, so core can emit events (#6930)
Some checks failed
Tests / test (./cmd/caddy/caddy, ~1.24.1, macos-14, 0, 1.24, mac) (push) Has been cancelled
Tests / test (./cmd/caddy/caddy, ~1.24.1, ubuntu-latest, 0, 1.24, linux) (push) Has been cancelled
Tests / test (./cmd/caddy/caddy.exe, ~1.24.1, windows-latest, True, 1.24, windows) (push) Has been cancelled
Lint / lint (macos-14, mac) (push) Has been cancelled
Lint / lint (ubuntu-latest, linux) (push) Has been cancelled
Lint / lint (windows-latest, windows) (push) Has been cancelled
Lint / govulncheck (push) Has been cancelled
Tests / test (s390x on IBM Z) (push) Has been cancelled
Tests / goreleaser-check (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, aix) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, darwin) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, dragonfly) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, freebsd) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, illumos) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, linux) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, netbsd) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, openbsd) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, solaris) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, windows) (push) Has been cancelled
Some checks failed
Tests / test (./cmd/caddy/caddy, ~1.24.1, macos-14, 0, 1.24, mac) (push) Has been cancelled
Tests / test (./cmd/caddy/caddy, ~1.24.1, ubuntu-latest, 0, 1.24, linux) (push) Has been cancelled
Tests / test (./cmd/caddy/caddy.exe, ~1.24.1, windows-latest, True, 1.24, windows) (push) Has been cancelled
Lint / lint (macos-14, mac) (push) Has been cancelled
Lint / lint (ubuntu-latest, linux) (push) Has been cancelled
Lint / lint (windows-latest, windows) (push) Has been cancelled
Lint / govulncheck (push) Has been cancelled
Tests / test (s390x on IBM Z) (push) Has been cancelled
Tests / goreleaser-check (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, aix) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, darwin) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, dragonfly) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, freebsd) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, illumos) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, linux) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, netbsd) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, openbsd) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, solaris) (push) Has been cancelled
Cross-Build / build (~1.24.1, 1.24, windows) (push) Has been cancelled
* events: Refactor; move Event into core, so core can emit events Requires some slight trickery to invert dependencies. We can't have the caddy package import the caddyevents package, because caddyevents imports caddy. Interface to the rescue! Also add two new events, experimentally: started, and stopping. At the request of a sponsor. Also rename "Filesystems" to "FileSystems" to match Go convention (unrelated to events, was just bugging me when I noticed it). * Coupla bug fixes * lol whoops
This commit is contained in:
104
caddy.go
104
caddy.go
@ -81,13 +81,14 @@ type Config struct {
|
||||
// associated value.
|
||||
AppsRaw ModuleMap `json:"apps,omitempty" caddy:"namespace="`
|
||||
|
||||
apps map[string]App
|
||||
storage certmagic.Storage
|
||||
apps map[string]App
|
||||
storage certmagic.Storage
|
||||
eventEmitter eventEmitter
|
||||
|
||||
cancelFunc context.CancelFunc
|
||||
|
||||
// filesystems is a dict of filesystems that will later be loaded from and added to.
|
||||
filesystems FileSystems
|
||||
// fileSystems is a dict of fileSystems that will later be loaded from and added to.
|
||||
fileSystems FileSystems
|
||||
}
|
||||
|
||||
// App is a thing that Caddy runs.
|
||||
@ -442,6 +443,10 @@ func run(newCfg *Config, start bool) (Context, error) {
|
||||
}
|
||||
globalMetrics.configSuccess.Set(1)
|
||||
globalMetrics.configSuccessTime.SetToCurrentTime()
|
||||
|
||||
// TODO: This event is experimental and subject to change.
|
||||
ctx.emitEvent("started", nil)
|
||||
|
||||
// now that the user's config is running, finish setting up anything else,
|
||||
// such as remote admin endpoint, config loader, etc.
|
||||
return ctx, finishSettingUp(ctx, ctx.cfg)
|
||||
@ -509,7 +514,7 @@ func provisionContext(newCfg *Config, replaceAdminServer bool) (Context, error)
|
||||
}
|
||||
|
||||
// create the new filesystem map
|
||||
newCfg.filesystems = &filesystems.FilesystemMap{}
|
||||
newCfg.fileSystems = &filesystems.FileSystemMap{}
|
||||
|
||||
// prepare the new config for use
|
||||
newCfg.apps = make(map[string]App)
|
||||
@ -696,6 +701,9 @@ func unsyncedStop(ctx Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: This event is experimental and subject to change.
|
||||
ctx.emitEvent("stopping", nil)
|
||||
|
||||
// stop each app
|
||||
for name, a := range ctx.cfg.apps {
|
||||
err := a.Stop()
|
||||
@ -1038,6 +1046,92 @@ func Version() (simple, full string) {
|
||||
return
|
||||
}
|
||||
|
||||
// Event represents something that has happened or is happening.
|
||||
// An Event value is not synchronized, so it should be copied if
|
||||
// being used in goroutines.
|
||||
//
|
||||
// EXPERIMENTAL: Events are subject to change.
|
||||
type Event struct {
|
||||
// If non-nil, the event has been aborted, meaning
|
||||
// propagation has stopped to other handlers and
|
||||
// the code should stop what it was doing. Emitters
|
||||
// may choose to use this as a signal to adjust their
|
||||
// code path appropriately.
|
||||
Aborted error
|
||||
|
||||
// The data associated with the event. Usually the
|
||||
// original emitter will be the only one to set or
|
||||
// change these values, but the field is exported
|
||||
// so handlers can have full access if needed.
|
||||
// However, this map is not synchronized, so
|
||||
// handlers must not use this map directly in new
|
||||
// goroutines; instead, copy the map to use it in a
|
||||
// goroutine. Data may be nil.
|
||||
Data map[string]any
|
||||
|
||||
id uuid.UUID
|
||||
ts time.Time
|
||||
name string
|
||||
origin Module
|
||||
}
|
||||
|
||||
// NewEvent creates a new event, but does not emit the event. To emit an
|
||||
// event, call Emit() on the current instance of the caddyevents app insteaad.
|
||||
//
|
||||
// EXPERIMENTAL: Subject to change.
|
||||
func NewEvent(ctx Context, name string, data map[string]any) (Event, error) {
|
||||
id, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
return Event{}, fmt.Errorf("generating new event ID: %v", err)
|
||||
}
|
||||
name = strings.ToLower(name)
|
||||
return Event{
|
||||
Data: data,
|
||||
id: id,
|
||||
ts: time.Now(),
|
||||
name: name,
|
||||
origin: ctx.Module(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (e Event) ID() uuid.UUID { return e.id }
|
||||
func (e Event) Timestamp() time.Time { return e.ts }
|
||||
func (e Event) Name() string { return e.name }
|
||||
func (e Event) Origin() Module { return e.origin } // Returns the module that originated the event. May be nil, usually if caddy core emits the event.
|
||||
|
||||
// CloudEvent exports event e as a structure that, when
|
||||
// serialized as JSON, is compatible with the
|
||||
// CloudEvents spec.
|
||||
func (e Event) CloudEvent() CloudEvent {
|
||||
dataJSON, _ := json.Marshal(e.Data)
|
||||
return CloudEvent{
|
||||
ID: e.id.String(),
|
||||
Source: e.origin.CaddyModule().String(),
|
||||
SpecVersion: "1.0",
|
||||
Type: e.name,
|
||||
Time: e.ts,
|
||||
DataContentType: "application/json",
|
||||
Data: dataJSON,
|
||||
}
|
||||
}
|
||||
|
||||
// CloudEvent is a JSON-serializable structure that
|
||||
// is compatible with the CloudEvents specification.
|
||||
// See https://cloudevents.io.
|
||||
// EXPERIMENTAL: Subject to change.
|
||||
type CloudEvent struct {
|
||||
ID string `json:"id"`
|
||||
Source string `json:"source"`
|
||||
SpecVersion string `json:"specversion"`
|
||||
Type string `json:"type"`
|
||||
Time time.Time `json:"time"`
|
||||
DataContentType string `json:"datacontenttype,omitempty"`
|
||||
Data json.RawMessage `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
// ErrEventAborted cancels an event.
|
||||
var ErrEventAborted = errors.New("event aborted")
|
||||
|
||||
// ActiveContext returns the currently-active context.
|
||||
// This function is experimental and might be changed
|
||||
// or removed in the future.
|
||||
|
Reference in New Issue
Block a user