- App-owned festival bus with Fire, Collect and UntilHandled - Recover listener panics with owner plugin IDs; isolate buses per app - towel context accessors and hello command demo of all three modes
75 lines
1.5 KiB
Go
75 lines
1.5 KiB
Go
package backpack
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
|
|
"git.golem15.com/golem15/summercms/compass"
|
|
"git.golem15.com/golem15/summercms/festival"
|
|
)
|
|
|
|
// App is the per-instance application container. It must not import party.
|
|
type App struct {
|
|
Config *compass.Config
|
|
Services *Registry
|
|
Events *festival.Bus
|
|
|
|
mu sync.RWMutex
|
|
plugins map[string]struct{}
|
|
}
|
|
|
|
// New returns an App that owns cfg.
|
|
func New(cfg *compass.Config) *App {
|
|
return &App{
|
|
Config: cfg,
|
|
Services: NewRegistry(),
|
|
Events: festival.New(),
|
|
plugins: make(map[string]struct{}),
|
|
}
|
|
}
|
|
|
|
// SetPlugins records the complete activated plugin set. HasPlugin uses this
|
|
// list, including plugins that have not yet Booted.
|
|
func (a *App) SetPlugins(ids []string) {
|
|
if a == nil {
|
|
return
|
|
}
|
|
next := make(map[string]struct{}, len(ids))
|
|
for _, id := range ids {
|
|
if id != "" {
|
|
next[id] = struct{}{}
|
|
}
|
|
}
|
|
a.mu.Lock()
|
|
a.plugins = next
|
|
a.mu.Unlock()
|
|
}
|
|
|
|
// HasPlugin reports whether id is in the complete registered set.
|
|
func (a *App) HasPlugin(id string) bool {
|
|
if a == nil {
|
|
return false
|
|
}
|
|
a.mu.RLock()
|
|
defer a.mu.RUnlock()
|
|
_, ok := a.plugins[id]
|
|
return ok
|
|
}
|
|
|
|
// Publish stores an app-scoped service under T.
|
|
func (a *App) Publish[T any](value T) error {
|
|
if a == nil || a.Services == nil {
|
|
return fmt.Errorf("backpack: app has no service registry")
|
|
}
|
|
return a.Services.Publish(value)
|
|
}
|
|
|
|
// Lookup returns the app-scoped service published under T.
|
|
func (a *App) Lookup[T any]() (T, bool) {
|
|
var zero T
|
|
if a == nil || a.Services == nil {
|
|
return zero, false
|
|
}
|
|
return a.Services.Lookup[T]()
|
|
}
|