# Lifecycle & Graceful Shutdown

# Lifecycle & Graceful Shutdown

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [src/lifecycle/__tests__/graceful-shutdown.test.ts](src/lifecycle/__tests__/graceful-shutdown.test.ts)
- [src/lifecycle/graceful-shutdown.ts](src/lifecycle/graceful-shutdown.ts)

</details>



The `lifecycle` module provides a centralized mechanism for managing the termination phase of a microservice. It ensures that when a process receives a termination signal or encounters an unrecoverable error, it performs all necessary cleanup tasks—such as closing database connections or disconnecting from NATS—before exiting with the appropriate status code.

## The GracefulShutdown Class

The core of this module is the `GracefulShutdown` class [src/lifecycle/graceful-shutdown.ts:16-59](). It acts as a registry for cleanup logic and a manager for process-level events.

### Key Components

| Component | Description |
| :--- | :--- |
| `shuttingDown` | A boolean re-entrancy guard to ensure shutdown logic only runs once [src/lifecycle/graceful-shutdown.ts:17](). |
| `cleanups` | An array of `CleanupFn` (asynchronous functions) to be executed during termination [src/lifecycle/graceful-shutdown.ts:18](). |
| `serviceName` | A string identifier used for logging shutdown events [src/lifecycle/graceful-shutdown.ts:19](). |

### Registration and Execution Flow

The following diagram illustrates how cleanup functions are registered and subsequently executed when a signal is received.

**Lifecycle Management Flow**
```mermaid
sequenceDiagram
    participant App as "Consumer Application"
    participant GS as "GracefulShutdown Instance"
    participant Proc as "Node.js process"

    App->>GS: new GracefulShutdown("my-service")
    App->>GS: addCleanup(nats.close)
    App->>GS: addCleanup(db.close)
    App->>GS: install()
    GS->>Proc: on("SIGTERM", handler)
    GS->>Proc: on("uncaughtException", handler)

    Note over Proc: External SIGTERM received
    Proc->>GS: Trigger handler
    GS->>GS: Set shuttingDown = true
    par Parallel Cleanup
        GS->>App: 执行 nats.close()
        GS->>App: 执行 db.close()
    end
    GS->>Proc: exit(code)
```
Sources: [src/lifecycle/graceful-shutdown.ts:16-59](), [src/lifecycle/__tests__/graceful-shutdown.test.ts:22-32]()

## Signal Handling and Installation

The `install()` method [src/lifecycle/graceful-shutdown.ts:31-47]() configures the Node.js process to listen for specific termination signals and runtime errors.

### Handled Events

1.  **Standard Signals**: `SIGTERM`, `SIGINT`, and `SIGHUP` [src/lifecycle/graceful-shutdown.ts:32]().
    *   The exit code is calculated as `128 + signal_constant` (e.g., `SIGTERM` usually results in `143`) [src/lifecycle/graceful-shutdown.ts:35]().
2.  **Uncaught Errors**: `uncaughtException` and `unhandledRejection` [src/lifecycle/graceful-shutdown.ts:39-46]().
    *   These events log the error/reason to `stderr` and trigger a shutdown with exit code `1` [src/lifecycle/graceful-shutdown.ts:41,45]().

**Signal to Code Mapping**
```mermaid
graph TD
    subgraph "Process Events"
        SIG["SIGTERM / SIGINT / SIGHUP"]
        ERR["uncaughtException / unhandledRejection"]
    end

    subgraph "GracefulShutdown.install()"
        Handler["shutdown(reason, code)"]
    end

    SIG -->| "code = 128 + signal" | Handler
    ERR -->| "code = 1" | Handler
    Handler -->| "Promise.allSettled" | Cleanup["cleanups[]"]
    Cleanup --> Exit["process.exit(code)"]
```
Sources: [src/lifecycle/graceful-shutdown.ts:31-47](), [src/lifecycle/graceful-shutdown.ts:49-58]()

## Implementation Details

### Re-entrancy Guard
To prevent race conditions where multiple signals (e.g., a user hitting `Ctrl+C` twice) trigger multiple cleanup cycles, the `shutdown` method checks the `shuttingDown` flag [src/lifecycle/graceful-shutdown.ts:50-51](). If a shutdown is already in progress, subsequent calls return immediately.

### Parallel Cleanup
Cleanup functions are executed in parallel using `Promise.allSettled` [src/lifecycle/graceful-shutdown.ts:54](). This ensures that:
1.  The shutdown process is as fast as possible.
2.  A failure in one cleanup function (e.g., a database connection timeout) does not prevent other cleanup functions from running.

### Explicit Exit
The class always calls `process.exit(code)` within a `finally` block [src/lifecycle/graceful-shutdown.ts:55-57](). This ensures that even if the cleanup logic throws an error, the process will terminate with the intended status code.

## Usage Example

Consumers typically initialize the lifecycle manager during the bootstrap phase of the application.

```typescript
import { GracefulShutdown } from '@primebrick/sdk';

const lifecycle = new GracefulShutdown("order-service");

// Register cleanup tasks
lifecycle.addCleanup(async () => {
  await natsClient.close();
});

// Install handlers
lifecycle.install();
```
Sources: [src/lifecycle/graceful-shutdown.ts:16-59](), [src/lifecycle/__tests__/graceful-shutdown.test.ts:47-56]()

---
