← 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