EventDispatcher.ts•5.05 kB
import { EventBus } from './EventBus.js';
import { EventTypes } from './EventTypes.js';
import { Logger } from '../../core/logger.js';
import { QueryExecutedEvent } from '../../domain/query/events/QueryExecutedEvent.js';
import { SchemaChangedEvent } from '../../domain/query/events/SchemaChangedEvent.js';
import { PerformanceAlertTriggeredEvent } from '../../domain/performance/events/PerformanceAlertTriggeredEvent.js';
import { QueryPerformancePolicy } from '../../domain/query/policies/QueryPerformancePolicy.js';
import { ConnectionPoolPolicy } from '../../domain/performance/policies/ConnectionPoolPolicy.js';
/**
 * EventDispatcher
 *
 * Centralizes event handling logic and connects events to policies.
 * Implements the Observer pattern for domain events.
 */
export class EventDispatcher {
  private static instance: EventDispatcher;
  private eventBus: EventBus;
  private queryPerformancePolicy: QueryPerformancePolicy;
  private connectionPoolPolicy: ConnectionPoolPolicy;
  private constructor(private readonly logger: Logger) {
    this.eventBus = EventBus.getInstance();
    this.queryPerformancePolicy = new QueryPerformancePolicy();
    this.connectionPoolPolicy = new ConnectionPoolPolicy();
    this.registerEventHandlers();
  }
  /**
   * Gets the singleton instance of EventDispatcher.
   * @param logger Logger instance
   * @returns EventDispatcher instance
   */
  public static getInstance(logger: Logger): EventDispatcher {
    if (!EventDispatcher.instance) {
      EventDispatcher.instance = new EventDispatcher(logger);
    }
    return EventDispatcher.instance;
  }
  /**
   * Registers all event handlers with the event bus.
   */
  private registerEventHandlers(): void {
    // Query events
    this.eventBus.subscribe(EventTypes.QUERY_EXECUTED, this.handleQueryExecuted.bind(this));
    this.eventBus.subscribe(EventTypes.QUERY_FAILED, this.handleQueryFailed.bind(this));
    this.eventBus.subscribe(EventTypes.QUERY_SLOW, this.handleSlowQuery.bind(this));
    // Schema events
    this.eventBus.subscribe(EventTypes.SCHEMA_CHANGED, this.handleSchemaChanged.bind(this));
    // Performance events
    this.eventBus.subscribe(
      EventTypes.PERFORMANCE_ALERT_TRIGGERED,
      this.handlePerformanceAlert.bind(this)
    );
  }
  /**
   * Handles query executed events.
   * @param event The query executed event
   */
  private handleQueryExecuted(event: QueryExecutedEvent): void {
    this.logger.debug('Query executed event received', {
      queryId: event.queryId,
      executionTime: event.executionTime,
      rowCount: event.rowCount,
    });
    // Apply query performance policy
    if (this.queryPerformancePolicy.evaluate(event)) {
      const severity = this.queryPerformancePolicy.getSeverity(event);
      const recommendations = this.queryPerformancePolicy.getRecommendations(event);
      this.logger.info(`Query performance issue detected (${severity})`, {
        queryId: event.queryId,
        executionTime: event.executionTime,
        recommendations,
      });
      // Trigger performance alert if critical
      if (severity === 'critical') {
        const alertEvent = new PerformanceAlertTriggeredEvent(
          `query-${event.queryId}`,
          'QUERY_PERFORMANCE',
          'CRITICAL',
          `Slow query detected (${event.executionTime}ms)`,
          { executionTime: event.executionTime },
          event.timestamp
        );
        this.eventBus.publish(EventTypes.PERFORMANCE_ALERT_TRIGGERED, alertEvent);
      }
    }
  }
  /**
   * Handles query failed events.
   * @param event The query failed event
   */
  private handleQueryFailed(event: QueryExecutedEvent): void {
    this.logger.error('Query failed event received', {
      queryId: event.queryId,
      error: event.errorMessage,
    });
  }
  /**
   * Handles slow query events.
   * @param event The slow query event
   */
  private handleSlowQuery(event: QueryExecutedEvent): void {
    this.logger.warn('Slow query detected', {
      queryId: event.queryId,
      executionTime: event.executionTime,
      sql: event.sql.substring(0, 100) + (event.sql.length > 100 ? '...' : ''),
    });
  }
  /**
   * Handles schema changed events.
   * @param event The schema changed event
   */
  private handleSchemaChanged(event: SchemaChangedEvent): void {
    this.logger.info('Schema changed event received', {
      changeType: event.changeType,
      objectType: event.objectType,
      objectName: event.objectName,
    });
  }
  /**
   * Handles performance alert events.
   * @param event The performance alert event
   */
  private handlePerformanceAlert(event: PerformanceAlertTriggeredEvent): void {
    this.logger.warn(`Performance alert: ${event.getSummary()}`, {
      alertType: event.alertType,
      severity: event.severity,
      measurements: event.measurements,
    });
    // Log recommendations
    const recommendation = event.getRecommendation();
    this.logger.info(`Performance recommendation: ${recommendation}`, {
      alertId: event.alertId,
    });
  }
}