# Browser Optimization for PDF Generation

## Overview
Optimized PDF generation by implementing a singleton Chromium browser instance that launches on server startup and is reused across all PDF generation requests.

## Problem Statement
Previously, a new Chromium browser instance was launched for every PDF generation request, which was:
- **Slow**: Browser launch takes 2-5 seconds per request
- **Resource-intensive**: Each browser instance consumes significant memory (~200MB)
- **Inefficient**: Multiple concurrent requests created multiple browser instances

## Solution
Implemented a `BrowserManagerService` that:
- Launches a single Chromium browser instance on server startup
- Reuses the same browser for all PDF generation requests
- Automatically handles browser lifecycle (startup, reconnection, shutdown)
- Closes the browser when the server/pod restarts

## Changes Made

### 1. Created BrowserManagerService
**File**: `src/common/services/browser-manager.service.ts`

Key features:
- Implements `OnModuleInit` to launch browser on server startup
- Implements `OnModuleDestroy` to close browser on server shutdown
- Provides `getBrowser()` method to get/create browser instance
- Includes reconnection logic if browser disconnects
- Logs all browser lifecycle events for monitoring

### 2. Updated PDF Generation Utilities
**File**: `src/common/utils/common.util.ts`

- Modified `generatePDF()` function to accept optional browser instance
- Maintains backward compatibility (launches new browser if none provided)
- Properly closes pages after PDF generation to free resources
- Only closes browser if it was launched locally (not the singleton)

### 3. Updated Invoice Service
**File**: `src/invoice/invoice.service.ts`

- Injected `BrowserManagerService` into constructor
- Updated `generateInvoicePDF()` to use singleton browser instance
- Removed local browser launch code
- Closes pages after use but keeps browser running

### 4. Registered Service Globally
**File**: `src/app.module.ts`

- Added `BrowserManagerService` to global providers
- Exported service for use across all modules

## Benefits

### Performance Improvement
- **First Request**: ~2-5 seconds saved (no browser launch)
- **Subsequent Requests**: ~2-5 seconds saved per request
- **Concurrent Requests**: Can handle multiple requests with single browser

### Resource Optimization
- **Memory**: Single browser instance (~200MB) instead of multiple
- **CPU**: No repeated browser startup overhead
- **Network**: Browser binaries downloaded once on startup

### Reliability
- Automatic browser reconnection on disconnect
- Graceful shutdown on server restart
- Error handling and logging for debugging

## Usage

### For Services (Recommended)
```typescript
@Injectable()
export class YourService {
  constructor(private readonly browserManagerService: BrowserManagerService) {}

  async generatePdf() {
    const browser = await this.browserManagerService.getBrowser();
    const page = await browser.newPage();
    
    // Use the page...
    await page.setContent(html);
    const pdf = await page.pdf({ format: 'A4' });
    
    // Always close the page (but not the browser)
    await page.close();
    
    return pdf;
  }
}
```

### For Utility Functions
```typescript
import { generatePDF } from 'src/common/utils/common.util';

// If you have BrowserManagerService instance
const browser = await browserManagerService.getBrowser();
const result = await generatePDF(data, template, filename, browser);

// Without browser instance (backward compatible - launches new browser)
const result = await generatePDF(data, template, filename);
```

## Monitoring

Browser lifecycle events are logged with the following messages:
- `Initializing Browser Manager Service...` - On server startup
- `Browser launched successfully on startup` - Browser ready
- `Browser disconnected unexpectedly` - Browser crashed/disconnected
- `Browser not available, launching new instance...` - Reconnection attempt
- `Shutting down Browser Manager Service...` - Server shutdown
- `Browser closed successfully` - Clean shutdown

## Rollback

If issues occur, you can temporarily disable by:
1. Not injecting `BrowserManagerService` in services
2. Calling `generatePDF()` without the browser parameter
3. The system will fall back to launching new browsers per request

## Testing

To verify the optimization:
1. Monitor server logs on startup for browser launch message
2. Generate multiple PDFs and observe no additional browser launches
3. Check memory usage - should be stable with single browser instance
4. Restart server/pod and verify browser is properly closed and relaunched

## Future Enhancements

Potential improvements:
- Add browser health checks
- Implement page pooling for concurrent requests
- Add metrics for PDF generation performance
- Configure browser launch options via environment variables
- Add circuit breaker for browser failures
