← Back to Documentation

Application Lifecycle

ARO applications have a well-defined lifecycle from startup to shutdown. This chapter explains how to manage your application's lifecycle.

Lifecycle Overview

1. Load all .aro files
2. Compile and validate
3. Register feature sets with event bus
4. Execute Application-Start
5. Enter event loop
   ↓
   Handle Events (HTTP, Files, Sockets, Domain Events)
   ↓ (shutdown signal)
6. Stop accepting new events
7. Wait for pending events
8. Execute Application-End
9. Stop services
10. Exit

Application-Start

The entry point for every ARO application.

Requirements

Basic Example

(Application-Start: My Application) {
    <Log> "Starting application..." to the <console>.
    <Return> an <OK: status> for the <startup>.
}

Full Example

(Application-Start: E-Commerce Platform) {
    <Log> "Starting E-Commerce Platform..." to the <console>.

    (* Load configuration *)
    <Read> the <config: JSON> from the <file: "./config.json">.
    <Publish> as <app-config> <config>.

    (* Start HTTP server *)
    <Start> the <http-server> on port <config: server port>.

    (* Start file watcher for uploads *)
    <Watch> the <directory: "./uploads"> as <upload-watcher>.

    (* Keep the application running *)
    <Keepalive> the <application> for the <events>.

    <Log> "Platform ready" to the <console>.
    <Return> an <OK: status> for the <startup>.
}

Application-End

Exit handlers for cleanup when the application stops.

Success Handler

Called on graceful shutdown (SIGTERM, SIGINT, or programmatic stop):

(Application-End: Success) {
    <Log> "Shutting down gracefully..." to the <console>.

    (* Stop accepting new requests *)
    <Stop> the <http-server>.

    <Log> "Shutdown complete. Goodbye!" to the <console>.
    <Return> an <OK: status> for the <shutdown>.
}

Error Handler

Called when the application crashes or encounters a fatal error:

(Application-End: Error) {
    <Extract> the <error> from the <shutdown: error>.
    <Extract> the <reason> from the <shutdown: reason>.

    <Log> "FATAL ERROR: ${reason}" to the <console>.

    <Return> an <OK: status> for the <error-handling>.
}

Shutdown Context

Available variables in Application-End handlers:

VariableDescriptionAvailable In
<shutdown: reason>Human-readable reasonBoth
<shutdown: code>Exit code (0 = success)Both
<shutdown: signal>Signal name (SIGTERM, etc.)Success
<shutdown: error>Error objectError only

Rules

Keeping Applications Alive

For servers that should run indefinitely, use the <Keepalive> action:

(Application-Start: My Server) {
    <Start> the <http-server> on port 8080.
    <Keepalive> the <application> for the <events>.
    <Return> an <OK: status> for the <startup>.
}

The <Keepalive> action blocks until interrupted (Ctrl+C or kill signal).

Service Initialization

HTTP Server

(Application-Start: Web Server) {
    <Start> the <http-server> on port 8080.
    <Keepalive> the <application> for the <events>.
    <Return> an <OK: status> for the <startup>.
}

(Application-End: Success) {
    <Stop> the <http-server>.
    <Return> an <OK: status> for the <shutdown>.
}

File Watcher

(Application-Start: File Processor) {
    <Watch> the <directory: "./inbox"> as <file-watcher>.
    <Keepalive> the <application> for the <events>.
    <Return> an <OK: status> for the <startup>.
}

Socket Server

(Application-Start: Socket Server) {
    <Listen> on port 9000 as <socket-server>.
    <Keepalive> the <application> for the <events>.
    <Return> an <OK: status> for the <startup>.
}

Multiple Services

(Application-Start: Full Stack) {
    (* HTTP API *)
    <Start> the <http-server> on port 8080.

    (* WebSocket server *)
    <Listen> on port 8081 as <websocket-server>.

    (* File watcher *)
    <Watch> the <directory: "./uploads"> as <upload-watcher>.

    (* Keep the application running *)
    <Keepalive> the <application> for the <events>.

    <Return> an <OK: status> for the <startup>.
}

(Application-End: Success) {
    (* Stop in reverse order *)
    <Stop> the <upload-watcher>.
    <Close> the <websocket-server>.
    <Stop> the <http-server>.

    <Return> an <OK: status> for the <shutdown>.
}

Best Practices

Initialize Early, Fail Fast

(Application-Start: Fail Fast) {
    (* Check critical config first *)
    <Read> the <config> from the <file: "./config.json">.

    when <config: database> is empty {
        <Log> "Missing database configuration" to the <console>.
        <Throw> a <ConfigurationError> for the <missing: database>.
    }

    (* Then initialize services *)
    <Start> the <http-server> on port <config: port>.

    <Return> an <OK: status> for the <startup>.
}

Log Lifecycle Events

(Application-Start: Observable App) {
    <Log> "APPLICATION_STARTING" to the <console>.

    <Start> the <http-server> on port 8080.

    <Log> "APPLICATION_READY" to the <console>.
    <Return> an <OK: status> for the <startup>.
}

(Application-End: Success) {
    <Log> "APPLICATION_STOPPING" to the <console>.

    <Stop> the <http-server>.

    <Log> "APPLICATION_STOPPED" to the <console>.
    <Return> an <OK: status> for the <shutdown>.
}

Next Steps

HTTP Services - HTTP server and client
Sockets - TCP communication
Events - Event-driven architecture