Documentation ¶
Overview ¶
Example ¶
package main import ( "context" "fmt" "time" "github.com/RussellLuo/appx" ) // Interface guards var ( _ appx.Initializer = (*A)(nil) _ appx.Cleaner = (*A)(nil) _ appx.StartStopper = (*A)(nil) _ appx.Initializer = (*B)(nil) _ appx.Cleaner = (*B)(nil) _ appx.StartStopper = (*B)(nil) ) type A struct { Name string Value string } func (a *A) Init(ctx appx.Context) error { a.Name = ctx.App.Name a.Value = "value_a" return nil } func (a *A) Clean() error { return nil } func (a *A) Start(ctx context.Context) error { return nil } func (a *A) Stop(ctx context.Context) error { return nil } type B struct { Name string Value string } func (b *B) Init(ctx appx.Context) error { b.Name = ctx.App.Name b.Value = "value_b" a := ctx.MustLoad("a").(*A) fmt.Printf("Loaded required app %q (value: %q)\n", a.Name, a.Value) return nil } func (b *B) Clean() error { return nil } func (b *B) Start(ctx context.Context) error { return nil } func (b *B) Stop(ctx context.Context) error { return nil } func Logger(next appx.Standard) appx.Standard { return &logger{Standard: next} } type logger struct { appx.Standard name string } func (l *logger) Init(ctx appx.Context) error { l.name = ctx.App.Name fmt.Printf("Initializing app %q, which requires %d app(s)\n", l.name, len(ctx.App.Requirements())) return l.Standard.Init(ctx) } func (l *logger) Clean() error { fmt.Printf("Cleaning up app %q\n", l.name) return l.Standard.Clean() } func (l *logger) Start(ctx context.Context) error { fmt.Printf("Starting app %q\n", l.name) return l.Standard.Start(ctx) } func (l *logger) Stop(ctx context.Context) error { fmt.Printf("Stopping app %q\n", l.name) return l.Standard.Stop(ctx) } func main() { r := appx.NewRegistry() // Typically located in `func init()` of package a. r.MustRegister(appx.New("a", new(A))) // Typically located in `func init()` of package b. r.MustRegister(appx.New("b", new(B)).Require("a")) // Typically located in `func main()` of package main. r.Use(Logger) if err := r.Install(context.Background()); err != nil { fmt.Printf("err: %v\n", err) return } defer r.Uninstall() // In a typical scenario, we could just use r.Run() here. Since we // don't want this example to run forever, we'll use the more explicit // Start and Stop. startCtx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() if err := r.Start(startCtx); err != nil { fmt.Printf("err: %v\n", err) return } fmt.Println("Everything is running") stopCtx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() r.Stop(stopCtx) }
Output: Initializing app "a", which requires 0 app(s) Initializing app "b", which requires 1 app(s) Loaded required app "a" (value: "value_a") Starting app "a" Starting app "b" Everything is running Stopping app "b" Stopping app "a" Cleaning up app "b" Cleaning up app "a"
Index ¶
- func Graph() map[string][]string
- func Install(ctx context.Context, names ...string) error
- func MustRegister(app *App)
- func Register(app *App) error
- func Run() (os.Signal, error)
- func SetOptions(opts *Options)
- func Start(ctx context.Context) error
- func Stop(ctx context.Context)
- func Uninstall()
- func Use(middlewares ...func(Standard) Standard)
- type App
- type Cleaner
- type Context
- type Hook
- type Initializer
- type Instance
- type Instancer
- type Lifecycle
- type Options
- type Registry
- func (r *Registry) Graph() map[string][]string
- func (r *Registry) Install(ctx context.Context, names ...string) error
- func (r *Registry) MustRegister(app *App)
- func (r *Registry) Register(app *App) error
- func (r *Registry) Run() (os.Signal, error)
- func (r *Registry) SetOptions(opts *Options)
- func (r *Registry) Start(ctx context.Context) error
- func (r *Registry) Stop(ctx context.Context)
- func (r *Registry) Uninstall()
- func (r *Registry) Use(middlewares ...func(Standard) Standard)
- type Standard
- type StartStopper
- type Validator
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func MustRegister ¶
func MustRegister(app *App)
func SetOptions ¶
func SetOptions(opts *Options)
Types ¶
type App ¶
type App struct { Name string // The application name. Instance Standard // The user-defined application instance, which has been standardized. // contains filtered or unexported fields }
App is a modular application.
func (*App) Require ¶
Require sets the names of the applications that the current application requires.
func (*App) Requirements ¶
Requirements returns the names of the applications that the current application requires.
type Cleaner ¶
type Cleaner interface { // Clean does the cleanup work for an application. It will return // an error if it fails. Clean() error }
type Context ¶
type Context struct { context.Context App *App // The application associated with this context. // contains filtered or unexported fields }
Context is a set of context parameters used to initialize the associated application.
func (Context) Config ¶
func (ctx Context) Config() interface{}
Config returns the configuration of the application associated with this context. It will return nil if there is no configuration.
Note that in the current implementation, in order to get the configuration successfully, Context.Config() must be called after AppConfigs has already been set by calling Registry.SetOptions().
type Hook ¶
A Hook is a pair of start and stop callbacks, either of which can be nil. If a Hook's OnStart callback isn't executed (because a previous OnStart failure short-circuited application startup), its OnStop callback won't be executed.
type Initializer ¶
type Lifecycle ¶
type Lifecycle interface {
Append(Hook)
}
Lifecycle allows application initializers to register callbacks that are executed on application start and stop.
The concept of lifecycle is borrowed from https://github.com/uber-go/fx.
type Options ¶
type Options struct { // The timeout of application startup. Defaults to 15s. StartTimeout time.Duration // The timeout of application shutdown. Defaults to 15s. StopTimeout time.Duration // The handler for errors during the Stop and Uninstall phases. ErrorHandler func(error) // The configurations for all registered applications. AppConfigs map[string]interface{} }
Options is a set of optional configurations for a registry.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
func (*Registry) Graph ¶
Graph generates the dependency graph for all installed applications in map form.
The format of the returned map is as below:
appName -> [dependencyAppName1, dependencyAppName2, ...]
func (*Registry) Install ¶
Install installs the applications specified by names, with the given ctx. If no name is specified, all registered applications will be installed.
Note that applications will be installed in dependency order.
func (*Registry) MustRegister ¶
MustRegister is like Register but panics if there is an error.
func (*Registry) Run ¶
Run starts all long-running applications, blocks on the signal channel, and then gracefully stops the applications. It is designed as a shortcut of calling Start and Stop for typical usage scenarios.
The default timeout for application startup and shutdown is 15s, which can be changed by using SetConfig.
func (*Registry) SetOptions ¶
SetOptions sets the options for the registry.
func (*Registry) Start ¶
Start kicks off all long-running applications, like network servers or message queue consumers. It will returns immediately if it encounters an error.
func (*Registry) Stop ¶
Stop gracefully stops all long-running applications. For best-effort cleanup, It will keep going after encountering errors, and all errors will be passed to the handler specified by ErrorHandler.
type Standard ¶
type Standard interface { Initializer Cleaner StartStopper Validator Instancer }
Standard represents a complete interface, which includes Initializer, Cleaner, StartStopper, Validator and Instancer.
func Standardize ¶
Standardize converts instance to a standard application instance, if it is not a standard one.
type StartStopper ¶
type StartStopper interface { // Start kicks off a long-running application, like network servers or // message queue consumers. It will return an error if it fails. Start(ctx context.Context) error // Stop gracefully stops a long-running application. It will return an // error if it fails. Stop(ctx context.Context) error }