# @stock-bot/shutdown

Shutdown management library for Node.js applications in the Stock Bot platform.

## Features

- ✅ **Automatic Signal Handling** - SIGTERM, SIGINT, SIGUSR2 (Unix), uncaught exceptions
- ✅ **Platform Support** - Windows and Unix/Linux compatible
- ✅ **Multiple Callbacks** - Register multiple cleanup functions
- ✅ **Timeout Protection** - Configurable shutdown timeout
- ✅ **Error Handling** - Failed callbacks don't block shutdown
- ✅ **TypeScript Support** - Full type definitions
- ✅ **Zero Dependencies** - Lightweight and efficient

## Installation

```bash
bun add @stock-bot/shutdown
```

## Quick Start

```typescript
import { onShutdown, setShutdownTimeout } from '@stock-bot/shutdown';

// Configure shutdown timeout (optional, default: 30 seconds)
setShutdownTimeout(15000); // 15 seconds

// Register cleanup callbacks
onShutdown(async () => {
  console.log('Closing database connections...');
  await database.close();
});

onShutdown(async () => {
  console.log('Stopping background jobs...');
  await jobQueue.stop();
});

onShutdown(() => {
  console.log('Final cleanup...');
  // Synchronous cleanup
});

console.log('Application started. Press Ctrl+C to test graceful shutdown.');
```

## API Reference

### Convenience Functions

#### `onShutdown(callback)`
Register a cleanup callback.

```typescript
onShutdown(async () => {
  await cleanup();
});
```

#### `setShutdownTimeout(timeout)`
Set shutdown timeout in milliseconds.

```typescript
setShutdownTimeout(30000); // 30 seconds
```

#### `initiateShutdown(signal?)`
Manually trigger shutdown.

```typescript
const result = await initiateShutdown('manual');
console.log(result.success); // true/false
```

#### `shutdownAndExit(signal?, exitCode?)`
Trigger shutdown and exit process.

```typescript
await shutdownAndExit('manual', 0);
```

### Advanced Usage

#### Manual Instance Management

```typescript
import { Shutdown } from '@stock-bot/shutdown';

const shutdown = new Shutdown({
  timeout: 20000,
  autoRegister: true
});

shutdown.onShutdown(async () => {
  await cleanup();
});

// Manual shutdown
const result = await shutdown.shutdown('manual');
```

#### Configuration Options

```typescript
interface ShutdownOptions {
  timeout?: number;        // Timeout in ms (default: 30000)
  autoRegister?: boolean;  // Auto-register signals (default: true)
}
```

#### Shutdown Result

```typescript
interface ShutdownResult {
  success: boolean;
  callbacksExecuted: number;
  callbacksFailed: number;
  duration: number;
  error?: string;
}
```

## Examples

### Express Server

```typescript
import express from 'express';
import { onShutdown, setShutdownTimeout } from '@stock-bot/shutdown';

const app = express();
const server = app.listen(3000);

setShutdownTimeout(10000);

onShutdown(async () => {
  console.log('Closing HTTP server...');
  await new Promise(resolve => server.close(resolve));
});

onShutdown(async () => {
  console.log('Closing database...');
  await database.close();
});
```

### Worker Process

```typescript
import { onShutdown } from '@stock-bot/shutdown';

let isRunning = true;

onShutdown(() => {
  console.log('Stopping worker...');
  isRunning = false;
});

// Worker loop
while (isRunning) {
  await processJob();
  await new Promise(resolve => setTimeout(resolve, 1000));
}
```

## Signal Handling

The library automatically handles these signals:

- **SIGTERM** - Termination request
- **SIGINT** - Interrupt (Ctrl+C)
- **SIGUSR2** - User-defined signal (Unix only)
- **uncaughtException** - Unhandled exceptions
- **unhandledRejection** - Unhandled promise rejections

On Windows, only SIGTERM and SIGINT are supported due to platform limitations.

## Best Practices

1. **Register callbacks early** in your application startup
2. **Keep callbacks simple** and focused on cleanup
3. **Use appropriate timeouts** based on your cleanup needs
4. **Handle errors gracefully** in callbacks
5. **Test shutdown behavior** in your CI/CD pipeline

## Testing

```typescript
import { resetShutdown, onShutdown } from '@stock-bot/shutdown';

beforeEach(() => {
  resetShutdown(); // Clear previous state
});

test('should register shutdown callback', () => {
  let cleaned = false;
  onShutdown(() => { cleaned = true; });
  
  // Test shutdown behavior
});
```
