File

apps/recallassess/recallassess-api/src/api/client/participant/listeners/participant-count.listener.ts

Description

Event Listener for Participant Count Updates Subscribes to participant events and updates Company count fields accordingly

This decouples count management from participant operations:

  • Participant service emits events (doesn't know about counts)
  • This listener reacts to events (updates counts)
  • Clean separation of concerns

Index

Properties
Methods

Constructor

constructor(countService: CLParticipantCountService)
Parameters :
Name Type Optional
countService CLParticipantCountService No

Methods

Async handleParticipantCreated
handleParticipantCreated(event: ParticipantCreatedEvent)
Decorators :
@OnEvent(PARTICIPANT_EVENTS.CREATED)

Handle participant creation event Increments appropriate counts when a participant is added

Parameters :
Name Type Optional
event ParticipantCreatedEvent No
Returns : any
Async handleParticipantDeleted
handleParticipantDeleted(event: ParticipantDeletedEvent)
Decorators :
@OnEvent(PARTICIPANT_EVENTS.DELETED)

Handle participant deletion event Decrements appropriate counts when a participant is deleted

Parameters :
Name Type Optional
event ParticipantDeletedEvent No
Returns : any
Async handleParticipantStatusUpdated
handleParticipantStatusUpdated(event: ParticipantStatusUpdatedEvent)
Decorators :
@OnEvent(PARTICIPANT_EVENTS.STATUS_UPDATED)

Handle participant status update event Adjusts counts when a participant's status changes

Parameters :
Name Type Optional
event ParticipantStatusUpdatedEvent No
Returns : any

Properties

Private Readonly logger
Type : unknown
Default value : new Logger(ParticipantCountListener.name)
import { Injectable, Logger } from "@nestjs/common";
import { OnEvent } from "@nestjs/event-emitter";
import {
  PARTICIPANT_EVENTS,
  ParticipantCreatedEvent,
  ParticipantDeletedEvent,
  ParticipantStatusUpdatedEvent,
} from "../events/participant.events";
import { CLParticipantCountService } from "../participant-count.service";

/**
 * Event Listener for Participant Count Updates
 * Subscribes to participant events and updates Company count fields accordingly
 *
 * This decouples count management from participant operations:
 * - Participant service emits events (doesn't know about counts)
 * - This listener reacts to events (updates counts)
 * - Clean separation of concerns
 */
@Injectable()
export class ParticipantCountListener {
  private readonly logger = new Logger(ParticipantCountListener.name);

  constructor(private readonly countService: CLParticipantCountService) {}

  /**
   * Handle participant creation event
   * Increments appropriate counts when a participant is added
   */
  @OnEvent(PARTICIPANT_EVENTS.CREATED)
  async handleParticipantCreated(event: ParticipantCreatedEvent) {
    try {
      this.logger.log(
        `Participant created: ${event.participantId}, Company: ${event.companyId}, Active: ${event.isActive}`,
      );

      await this.countService.incrementCounts(event.companyId, event.isActive, event.isReplaced);

      this.logger.log(`Successfully updated counts for company ${event.companyId}`);
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      const errorStack = error instanceof Error ? error.stack : undefined;
      this.logger.error(`Failed to update counts after participant creation: ${errorMessage}`, errorStack);
      // Don't throw - count updates should not fail the main operation
    }
  }

  /**
   * Handle participant status update event
   * Adjusts counts when a participant's status changes
   */
  @OnEvent(PARTICIPANT_EVENTS.STATUS_UPDATED)
  async handleParticipantStatusUpdated(event: ParticipantStatusUpdatedEvent) {
    try {
      this.logger.log(
        `Participant ${event.participantId} status updated: Active ${event.oldIsActive}->${event.newIsActive}, Replaced ${event.oldIsReplaced}->${event.newIsReplaced}`,
      );

      await this.countService.updateCountsOnStatusChange(
        event.companyId,
        event.oldIsActive,
        event.newIsActive,
        event.oldIsReplaced,
        event.newIsReplaced,
      );

      this.logger.log(`Successfully updated counts for company ${event.companyId}`);
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      const errorStack = error instanceof Error ? error.stack : undefined;
      this.logger.error(`Failed to update counts after status change: ${errorMessage}`, errorStack);
      // Don't throw - count updates should not fail the main operation
    }
  }

  /**
   * Handle participant deletion event
   * Decrements appropriate counts when a participant is deleted
   */
  @OnEvent(PARTICIPANT_EVENTS.DELETED)
  async handleParticipantDeleted(event: ParticipantDeletedEvent) {
    try {
      this.logger.log(
        `Participant deleted: ${event.participantId}, Company: ${event.companyId}, Active: ${event.isActive}`,
      );

      await this.countService.decrementCounts(event.companyId, event.isActive, event.isReplaced);

      this.logger.log(`Successfully updated counts for company ${event.companyId}`);
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      const errorStack = error instanceof Error ? error.stack : undefined;
      this.logger.error(`Failed to update counts after participant deletion: ${errorMessage}`, errorStack);
      // Don't throw - count updates should not fail the main operation
    }
  }
}

results matching ""

    No results matching ""