🏗️ Architecture

CQRS Pattern

Command Query Responsibility Segregation in Gauzy.

Overview

CQRS separates read and write operations into different models. Gauzy uses NestJS's @nestjs/cqrs module for complex domain operations.

Architecture

Diagram; its source is available below
Diagram source
graph LR
    Client --> Controller

    subgraph Write Side
        Controller -->|Command| CH[Command Handler]
        CH --> Service[Domain Service]
        Service --> DB[(Database)]
    end

    subgraph Read Side
        Controller -->|Query| QH[Query Handler]
        QH --> ReadModel[Read Model]
        ReadModel --> DB
    end

    CH -->|Event| EB[Event Bus]
    EB --> EH1[Event Handler 1]
    EB --> EH2[Event Handler 2]

Commands

// Command definition
export class CreateTimerCommand {
  constructor(
    public readonly input: ITimerToggleInput,
    public readonly requestContext: RequestContext,
  ) {}
}

// Command handler
@CommandHandler(CreateTimerCommand)
export class CreateTimerHandler implements ICommandHandler<CreateTimerCommand> {
  async execute(command: CreateTimerCommand): Promise<ITimeLog> {
    const { input, requestContext } = command;
    // Business logic here
    return this.timeLogService.create(input);
  }
}

Queries

// Query definition
export class GetTimerStatusQuery {
  constructor(public readonly employeeId: string) {}
}

// Query handler
@QueryHandler(GetTimerStatusQuery)
export class GetTimerStatusHandler implements IQueryHandler<GetTimerStatusQuery> {
  async execute(query: GetTimerStatusQuery): Promise<ITimerStatus> {
    return this.timerService.getStatus(query.employeeId);
  }
}

Events

// Event
export class TimerStartedEvent {
  constructor(public readonly timeLog: ITimeLog) {}
}

// Event handler
@EventsHandler(TimerStartedEvent)
export class TimerStartedHandler implements IEventHandler<TimerStartedEvent> {
  handle(event: TimerStartedEvent) {
    // Side effects: notifications, activity log, WebSocket broadcast
    this.notificationService.notify(event.timeLog.employeeId, "Timer started");
    this.wsGateway.emit("timer:started", event.timeLog);
  }
}

When to Use CQRS

Use CQRSUse Simple CRUD
Complex business logicSimple data operations
Multiple side effectsNo side effects
Event-driven workflowsBasic CRUD
Audit trail requiredLow complexity

Edit this page

Copyright © 2023-Present Ever Co. LTD.Docs by Sourcey