Application
Understand the startup path behind Procyon's application runner.
procyon.Run() is the small entrypoint most applications need. It hides the
manual startup ceremony but still gives the framework a predictable place to
prepare configuration, load components, start resources, and run work.
func main() {
if err := procyon.Run(); err != nil {
os.Exit(1)
}
}Creating an application
Use procyon.New() when you need to configure the application before running
it.
func main() {
app := procyon.New()
if err := app.Run(os.Args[1:]...); err != nil {
os.Exit(1)
}
}The object returned by procyon.New() implements runtime.Application:
type Application interface {
// SetBannerPrinter replaces the startup banner output.
// Use it when an application wants custom or silent startup output.
SetBannerPrinter(printer BannerPrinter)
// ResourceResolver returns the resolver used by the runtime to find resources.
// Configuration loaders and extensions can use the same lookup behavior.
ResourceResolver() io.ResourceResolver
// Run starts the application with explicit command-line arguments.
// It prepares environment, context, components, runners, servers, and cleanup.
Run(args ...string) error
}This interface is intentionally small. It gives startup code a place to replace the banner printer, share the runtime resource resolver, and run the application with explicit command-line arguments.
SetBannerPrinter is for startup presentation only. It lets an application or
extension replace the banner without changing the rest of the boot flow.
ResourceResolver exposes the same resource lookup used by the runtime. Use it
when an extension needs to find files in the same way configuration loading
does.
Run is the handoff from your main() function to the framework. After this
method starts, Procyon owns the startup order: environment preparation, context
creation, component initialization, runner execution, server waiting, and
shutdown cleanup.
What Run does
The application coordinates startup in a fixed order:
- Parse command-line arguments.
- Prepare the environment with argument and environment property sources.
- Print the banner.
- Create the runtime context.
- Invoke context initializers.
- Refresh the context and initialize singleton components.
- Invoke command-line runners.
- Wait for shutdown signals when a server component exists.
This keeps setup code out of main() and gives each extension point a clear
place in startup.
Application exists before the runtime context and component container are
ready. Use it for startup configuration. Put application behavior in components,
runners, servers, handlers, and lifecycle objects.
CLI app or server app
The same runner supports both shapes:
- If the component graph contains
runtime.CommandLineRunnercomponents, Procyon runs them after the context is refreshed. - If the graph contains a
runtime.Server, Procyon keeps the process alive untilSIGINTorSIGTERM.
That means a command-line tool and a web service can share the same component, configuration, and lifecycle model.
Banner printer
The application exposes SetBannerPrinter for replacing the default startup
banner.
type SilentBannerPrinter struct{}
func (p *SilentBannerPrinter) Print(env runtime.Environment, w io.Writer) error {
return nil
}app := procyon.New()
app.SetBannerPrinter(&SilentBannerPrinter{})
if err := app.Run(os.Args[1:]...); err != nil {
os.Exit(1)
}Resource resolver
ResourceResolver() exposes the resolver used by the application to locate
runtime resources, including configuration files. Use it from framework
extensions when they need to read files through the same resolution model as
the rest of the runtime.
Failure and cleanup
Startup errors are returned from Run. If startup panics or fails after the
context has started, Procyon closes the runtime context, stops lifecycle
components, and destroys initialized singletons before returning the error.
