Procyon|Docs
Runtime

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.

main.go
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.

main.go
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:

application.go
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:

  1. Parse command-line arguments.
  2. Prepare the environment with argument and environment property sources.
  3. Print the banner.
  4. Create the runtime context.
  5. Invoke context initializers.
  6. Refresh the context and initialize singleton components.
  7. Invoke command-line runners.
  8. 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.CommandLineRunner components, Procyon runs them after the context is refreshed.
  • If the graph contains a runtime.Server, Procyon keeps the process alive until SIGINT or SIGTERM.

That means a command-line tool and a web service can share the same component, configuration, and lifecycle model.

The application exposes SetBannerPrinter for replacing the default startup banner.

banner.go
type SilentBannerPrinter struct{}

func (p *SilentBannerPrinter) Print(env runtime.Environment, w io.Writer) error {
    return nil
}
main.go
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.