# Operation Manager Migration Guide

This guide shows how to migrate from provider-specific operation tracking to the unified operation management system.

## Overview

The new operation management system provides a unified way to track operations across all data providers (QM, CEO, IB, etc.) while maintaining provider-specific flexibility.

## Migration Steps for QM

### 1. Update Handler Constructor

**Before:**
```typescript
export class QMHandler extends BaseHandler<DataIngestionServices> {
  constructor(services: any) {
    super(services);
    initializeQMOperations(this.mongodb, this.logger).catch(error => {
      this.logger.error('Failed to initialize QM operations', { error });
    });
  }
}
```

**After:**
```typescript
import { OperationRegistry } from '../../shared/operation-manager';
import { QMOperationProvider } from './shared/operation-provider';

export class QMHandler extends BaseHandler<DataIngestionServices> {
  public operationRegistry: OperationRegistry;

  constructor(services: any) {
    super(services);
    
    // Initialize operation registry
    this.operationRegistry = new OperationRegistry({
      mongodb: this.mongodb,
      logger: this.logger
    });
    
    // Register QM provider
    const qmProvider = new QMOperationProvider({
      mongodb: this.mongodb,
      logger: this.logger
    });
    
    this.operationRegistry.registerProvider(qmProvider).catch(error => {
      this.logger.error('Failed to initialize QM operations', { error });
    });
  }
}
```

### 2. Update Actions

**Before:**
```typescript
// In action file
const tracker = await getOperationTracker(this);
await tracker.updateSymbolOperation(qmSearchCode, 'price_update', {
  status: 'success',
  lastRecordDate: latestDate,
  recordCount: priceData.length
});
```

**After (Option 1 - Direct Registry Access):**
```typescript
// Access registry from handler
await this.operationRegistry.updateOperation('qm', qmSearchCode, 'price_update', {
  status: 'success',
  lastRecordDate: latestDate,
  recordCount: priceData.length
});
```

**After (Option 2 - Using Helper Function):**
```typescript
// Create a helper function
async function updateQMOperation(
  handler: QMHandler,
  symbol: string,
  operation: string,
  data: OperationUpdate
) {
  await handler.operationRegistry.updateOperation('qm', symbol, operation, data);
}

// Use in action
await updateQMOperation(this, qmSearchCode, 'price_update', {
  status: 'success',
  lastRecordDate: latestDate,
  recordCount: priceData.length
});
```

### 3. Update Scheduling Functions

**Before:**
```typescript
const tracker = await getOperationTracker(this);
const staleSymbols = await tracker.getStaleSymbols('price_update', {
  minHoursSinceRun: forceUpdate ? 0 : 24,
  limit
});
```

**After:**
```typescript
const staleSymbols = await this.operationRegistry.getStaleSymbols('qm', 'price_update', {
  minHoursSinceRun: forceUpdate ? 0 : 24,
  limit
});
```

### 4. Backward Compatibility

During migration, you can maintain both systems:

```typescript
// In handler constructor
constructor(services: any) {
  super(services);
  
  // New system
  this.operationRegistry = new OperationRegistry({
    mongodb: this.mongodb,
    logger: this.logger
  });
  
  // Keep old system for gradual migration
  initializeQMOperations(this.mongodb, this.logger).catch(error => {
    this.logger.error('Failed to initialize legacy QM operations', { error });
  });
}
```

## Benefits

1. **Unified Interface**: Same API for all providers
2. **Better Type Safety**: Strong typing throughout
3. **Provider Isolation**: Each provider manages its own operations
4. **Extensibility**: Easy to add new providers
5. **Performance**: Optimized queries and bulk operations
6. **Monitoring**: Unified stats across all providers

## Example: Adding a New Provider (CEO)

```typescript
// handlers/ceo/shared/operation-provider.ts
export class CEOOperationProvider extends BaseOperationProvider {
  getProviderConfig(): ProviderConfig {
    return {
      name: 'ceo',
      collectionName: 'ceoSymbols',
      symbolField: 'symbol',
      description: 'CEO.CA data provider'
    };
  }

  getOperations(): OperationConfig[] {
    return [
      {
        name: 'posts_update',
        type: 'incremental',
        description: 'Update CEO posts',
        defaultStaleHours: 6
      },
      {
        name: 'shorts_update',
        type: 'incremental',
        description: 'Update short interest data',
        defaultStaleHours: 12
      }
    ];
  }
}

// In CEO handler
constructor(services: any) {
  super(services);
  
  this.operationRegistry = new OperationRegistry({
    mongodb: this.mongodb,
    logger: this.logger
  });
  
  const ceoProvider = new CEOOperationProvider({
    mongodb: this.mongodb,
    logger: this.logger
  });
  
  this.operationRegistry.registerProvider(ceoProvider);
}
```

## Global Statistics

```typescript
// Get stats for all providers
const globalStats = await operationRegistry.getGlobalStats();

// Get stats for specific provider
const qmStats = await operationRegistry.getProviderStats('qm');

// Find all crawl operations
const crawlOps = operationRegistry.findOperationsByType('crawl');
```