Перейти к содержанию

Events Catalog

Полный каталог всех доменных событий в системе EFKO Kernel.

Обзор

Система использует событийную архитектуру для асинхронной коммуникации между сервисами. События публикуются в RabbitMQ exchanges и потребляются downstream сервисами.

Exchanges событий

  • efko.auth.events — события auth-service
  • efko.personnel.events — события personnel-service
  • efko.production.events — события production-service
  • efko.etl.events — события etl-service

Envelope Event

Все события в системе упаковываются в Envelope Event — стандартизированную обертку, которая обеспечивает единый формат для всех доменных событий. Это позволяет downstream сервисам корректно обрабатывать события независимо от их типа.

Структура Envelope Event

{
  event_id: string;        // UUID события (генерируется при публикации)
  event_type: string;      // Тип события (например, "auth.user.created.event")
  timestamp: string;       // Время публикации события (ISO datetime)
  source_service: string;  // Сервис-источник события (например, "auth-service")
  correlation_id: string;  // ID для трассировки запроса
  version: string;         // Версия схемы события (например, "1.0.0")
  payload: unknown;        // Payload доменного события (специфичен для типа)
}

Пример Envelope Event

{
  "event_id": "evt-123e4567-e89b-12d3-a456-426614174000",
  "event_type": "auth.user.created.event",
  "timestamp": "2025-01-15T10:30:00Z",
  "source_service": "auth-service",
  "correlation_id": "req-abc123",
  "version": "1.0.0",
  "payload": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "email": "ivan@example.com",
    "fullName": "Иванов Иван",
    "role": "admin",
    "isActive": true,
    "employeeId": null
  }
}

Поля Envelope

Поле Тип Описание
event_id string Уникальный идентификатор события (UUID v4)
event_type string Тип события (соответствует routing key)
timestamp string Время публикации события в формате ISO 8601
source_service string Сервис, который опубликовал событие
correlation_id string ID для трассировки распределенных запросов
version string Версия схемы события (например, "1.0.0")
payload unknown Payload доменного события (структура зависит от типа)

Использование в коде

// Публикация события с envelope
await this.eventEmitter.emit('auth.user.created.event', {
  event_id: randomUUID(),
  event_type: 'auth.user.created.event',
  timestamp: new Date().toISOString(),
  source_service: 'auth-service',
  correlation_id: correlationId,
  version: '1.0.0',
  payload: userCreatedEventPayload,
});

// Потребление события
@RabbitSubscribe({
  exchange: 'efko.auth.events',
  routingKey: 'auth.user.created.event',
  queue: 'auth.user.created',
})
async handleUserCreated(envelope: IRabbitEvent<AuthUserCreatedEvent>) {
  const { event_id, event_type, timestamp, source_service, correlation_id, payload } = envelope;
  // Обработка события
}

Best Practices для Envelope

  1. Всегда используйте envelope — не публикуйте "сырые" события напрямую
  2. Генерируйте event_id — используйте UUID v4 для уникальности
  3. Указывайте timestamp — время публикации, а не время доменного события
  4. Используйте correlation_id — для трассировки распределенных запросов
  5. Указывайте version — для управления версионностью схемы события
  6. Валидируйте envelope — downstream сервисы должны проверять структуру envelope перед обработкой payload

Публикация событий

События публикуются двумя способами:

  1. Transactional Outbox — для personnel и production сервисов
  2. Событие записывается в таблицу outbox_messages в той же транзакции с доменными данными
  3. Периодический publisher (OutboxPeriodicPublisher) читает PENDING события и публикует в RabbitMQ
  4. Статус обновляется на SENT при успешной публикации
  5. Повторная публикация при ошибках (retry)

  6. Direct Publish — для auth-service и некоторых сценариев

  7. Событие публикуется сразу через RmqEventEmitterService
  8. Используется для критически важных событий, требующих немедленной доставки

Потребление событий

Downstream сервисы подписываются на соответствующие exchanges и обрабатывают события: - Для синхронизации данных - Для триггера бизнес-процессов - Для уведомлений и аналитики


Auth Events

События аутентификации и управления пользователями.

AuthUserCreatedEvent

Публикуется при регистрации нового пользователя.

Exchange: efko.auth.events
Routing Key: auth.user.created.event
Когда публикуется: После успешной регистрации пользователя в RegisterUserUseCase

Payload

{
  userId: string;       // UUID пользователя
  email: string;        // Email пользователя
  fullName: string;     // Полное имя
  role: UserRole;       // Роль пользователя
  isActive: boolean;    // Статус активности
  employeeId: string | null; // ID сотрудника (если привязан)
  createdAt: Date;      // Дата создания
  updatedAt: Date;      // Дата обновления
}

Пример

{
  "userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "email": "ivan@example.com",
  "fullName": "Иванов Иван",
  "role": "admin",
  "isActive": true,
  "employeeId": null,
  "createdAt": "2025-01-15T10:30:00.000Z",
  "updatedAt": "2025-01-15T10:30:00.000Z"
}

Кто может потреблять

  • Personnel Service — для синхронизации с кадровыми данными
  • Analytics Service — для аналитики по пользователям

AuthUserDeactivatedEvent

Публикуется при деактивации пользователя.

Exchange: efko.auth.events
Routing Key: auth.user.deactivated.event
Когда публикуется: После успешной деактивации в DeactivateUserUseCase

Payload

{
  userId: string; // UUID пользователя
}

Пример

{
  "userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Кто может потреблять

  • Personnel Service — для увольнения сотрудника
  • Production Service — для отзыва прав доступа
  • Gateway — для инвалидации сессий в кэше

Personnel Events

События кадрового домена: подразделения, должности, сотрудники, смены.

PersonnelEmployeeCreatedEvent

Публикуется при приеме сотрудника на работу.

Exchange: efko.personnel.events
Routing Key: personnel.employee.created.event
Когда публикуется: После успешного создания в CreateEmployeeUseCase

Payload

{
  id: string;              // UUID сотрудника
  personnelNumber: string; // Табельный номер
  fullName: string;        // Полное имя
  departmentId: string;    // UUID подразделения
  positionId: string;      // UUID должности
  status: EmployeeStatus;  // Статус сотрудника
}

Пример

{
  "id": "d4e5f6a7-b8c9-0123-defa-234567890123",
  "personnelNumber": "EMP-0001",
  "fullName": "Иванов Иван Иванович",
  "departmentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "positionId": "c3d4e5f6-a7b8-9012-cdef-123456789012",
  "status": "active"
}

Кто может потреблять

  • Auth Service — для создания учетной записи сотрудника
  • Access Control Service — для выдачи прав доступа

PersonnelEmployeeUpdatedEvent

Публикуется при обновлении данных сотрудника.

Exchange: efko.personnel.events
Routing Key: personnel.employee.updated.event
Когда публикуется: После успешного обновления в UpdateEmployeeUseCase

Payload

{
  id: string;              // UUID сотрудника
  fullName: string;        // Полное имя
  departmentId: string;    // UUID подразделения
  positionId: string;      // UUID должности
  employmentType: EmploymentType; // Тип занятости
  status: EmployeeStatus;  // Статус сотрудника
}

Пример

{
  "id": "d4e5f6a7-b8c9-0123-defa-234567890123",
  "fullName": "Иванов Иван Петрович",
  "departmentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "positionId": "c3d4e5f6-a7b8-9012-cdef-123456789012",
  "employmentType": "main",
  "status": "active"
}

Кто может потреблять

  • Auth Service — для обновления профиля пользователя
  • Access Control Service — для обновления прав доступа

PersonnelEmployeeTerminatedEvent

Публикуется при увольнении сотрудника.

Exchange: efko.personnel.events
Routing Key: personnel.employee.terminated.event
Когда публикуется: После успешного увольнения в TerminateEmployeeUseCase

Payload

{
  id: string;               // UUID сотрудника
  terminationDate: string;  // Дата увольнения (ISO date)
  status: EmployeeStatus;    // Статус (TERMINATED)
}

Пример

{
  "id": "d4e5f6a7-b8c9-0123-defa-234567890123",
  "terminationDate": "2025-06-30",
  "status": "terminated"
}

Кто может потреблять

  • Auth Service — для деактивации учетной записи
  • Production Service — для отзыва прав доступа
  • Access Control Service — для отзыва всех разрешений

PersonnelDepartmentCreatedEvent

Публикуется при создании подразделения.

Exchange: efko.personnel.events
Routing Key: personnel.department.created.event
Когда публикуется: После успешного создания в CreateDepartmentUseCase

Payload

{
  id: string;           // UUID подразделения
  name: string;         // Название подразделения
  code: string;         // Код подразделения
  type: DepartmentType; // Тип подразделения
  parentId: string | null | undefined; // UUID родительского подразделения
}

Пример

{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "name": "Производственный цех №1",
  "code": "PROD-001",
  "type": "division",
  "parentId": null
}

Кто может потреблять

  • Analytics Service — для аналитики по оргструктуре
  • Reporting Service — для отчетов по подразделениям

PersonnelDepartmentUpdatedEvent

Публикуется при обновлении подразделения.

Exchange: efko.personnel.events
Routing Key: personnel.department.updated.event
Когда публикуется: После успешного обновления в UpdateDepartmentUseCase

Payload

{
  id: string;           // UUID подразделения
  name: string;         // Название подразделения
  code: string;         // Код подразделения
  type: DepartmentType; // Тип подразделения
  headEmployeeId: string | null | undefined; // UUID руководителя
}

Пример

{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "name": "Производственный цех №2",
  "code": "PROD-001",
  "type": "division",
  "headEmployeeId": "d4e5f6a7-b8c9-0123-defa-234567890123"
}

Кто может потреблять

  • Analytics Service — для обновления аналитики
  • Reporting Service — для обновления отчетов

PersonnelPositionCreatedEvent

Публикуется при создании должности.

Exchange: efko.personnel.events
Routing Key: personnel.position.created.event
Когда публикуется: После успешного создания в CreatePositionUseCase

Payload

{
  id: string;           // UUID должности
  title: string;        // Название должности
  code: string;         // Код должности
  departmentId: string; // UUID подразделения
}

Пример

{
  "id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
  "title": "Оператор станка",
  "code": "OP-001",
  "departmentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Кто может потреблять

  • Analytics Service — для аналитики по должностям
  • Access Control Service — для создания ролей по должностям

PersonnelPositionUpdatedEvent

Публикуется при обновлении должности.

Exchange: efko.personnel.events
Routing Key: personnel.position.updated.event
Когда публикуется: После успешного обновления в UpdatePositionUseCase

Payload

{
  id: string;           // UUID должности
  title: string;        // Название должности
  code: string;         // Код должности
  departmentId: string; // UUID подразделения
}

Пример

{
  "id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
  "title": "Старший оператор станка",
  "code": "OP-001",
  "departmentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Кто может потреблять

  • Analytics Service — для обновления аналитики
  • Access Control Service — для обновления ролей

PersonnelShiftTemplateCreatedEvent

Публикуется при создании шаблона смены.

Exchange: efko.personnel.events
Routing Key: personnel.shift-template.created.event
Когда публикуется: После успешного создания в CreateShiftTemplateUseCase

Payload

{
  id: string;              // UUID шаблона
  name: string;            // Название шаблона
  shiftType: ShiftType;    // Тип смены
  startTime: string;       // Время начала (HH:MM)
  endTime: string;         // Время окончания (HH:MM)
  workDaysPattern: string; // Паттерн рабочих дней (бинарная строка)
}

Пример

{
  "id": "e5f6a7b8-c9d0-1234-efab-345678901234",
  "name": "Дневная смена",
  "shiftType": "day_shift",
  "startTime": "08:00",
  "endTime": "20:00",
  "workDaysPattern": "1111100"
}

Кто может потреблять

  • Shift Service — для создания графиков смен
  • Production Service — для планирования производства

PersonnelShiftTemplateUpdatedEvent

Публикуется при обновлении шаблона смены.

Exchange: efko.personnel.events
Routing Key: personnel.shift-template.updated.event
Когда публикуется: После успешного обновления в UpdateShiftTemplateUseCase

Payload

{
  id: string;              // UUID шаблона
  name: string;            // Название шаблона
  shiftType: ShiftType;    // Тип смены
  startTime: string;       // Время начала (HH:MM)
  endTime: string;         // Время окончания (HH:MM)
  workDaysPattern: string; // Паттерн рабочих дней
}

Пример

{
  "id": "e5f6a7b8-c9d0-1234-efab-345678901234",
  "name": "Ночная смена",
  "shiftType": "night_shift",
  "startTime": "20:00",
  "endTime": "08:00",
  "workDaysPattern": "1111100"
}

Кто может потреблять

  • Shift Service — для обновления графиков смен
  • Production Service — для обновления планирования

PersonnelShiftAssignedEvent

Публикуется при назначении сотрудника на смену.

Exchange: efko.personnel.events
Routing Key: personnel.shift.assigned.event
Когда публикуется: При назначении сотрудника на конкретную смену

Payload

{
  assignmentId: string;      // UUID назначения
  employeeId: string;        // UUID сотрудника
  personnelNumber: string;    // Табельный номер
  shiftTemplateId: string;   // UUID шаблона смены
  shiftType: ShiftType;       // Тип смены
  shiftDate: string;          // Дата смены (ISO date)
  startTime: string;           // Время начала (ISO datetime)
  endTime: string;            // Время окончания (ISO datetime)
  assignedAt: string;         // Время назначения (ISO datetime)
  assignedByUserId?: string;  // UUID пользователя, назначившего смену
}

Пример

{
  "assignmentId": "f6a7b8c9-d0e1-2345-fabc-456789012345",
  "employeeId": "d4e5f6a7-b8c9-0123-defa-234567890123",
  "personnelNumber": "EMP-0001",
  "shiftTemplateId": "e5f6a7b8-c9d0-1234-efab-345678901234",
  "shiftType": "day_shift",
  "shiftDate": "2025-01-20",
  "startTime": "2025-01-20T08:00:00Z",
  "endTime": "2025-01-20T20:00:00Z",
  "assignedAt": "2025-01-15T10:00:00Z",
  "assignedByUserId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Кто может потреблять

  • Access Service — для выдачи пропусков в определенные периоды
  • Production Service — для планирования персонала на линиях

Production Events

События производственного домена: продукты, заказы, выпуск, качество, датчики.

ProductionProductCreatedEvent

Публикуется при создании продукта.

Exchange: efko.production.events
Routing Key: production.product.created.event
Когда публикуется: После успешного создания в CreateProductUseCase

Payload

{
  id: string;              // UUID продукта
  code: string;            // Код продукта
  name: string;            // Название продукта
  category: ProductCategory; // Категория продукта
}

Пример

{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "code": "PROD-001",
  "name": "Творог 5%",
  "category": "finished_product"
}

Кто может потреблять

  • ETL Service — для синхронизации с внешними системами
  • Analytics Service — для аналитики по продуктам

ProductionProductUpdatedEvent

Публикуется при обновлении продукта.

Exchange: efko.production.events
Routing Key: production.product.updated.event
Когда публикуется: После успешного обновления продукта

Payload

{
  id: string;              // UUID продукта
  code: string;            // Код продукта
  name: string;            // Название продукта
  category: ProductCategory; // Категория продукта
}

Пример

{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "code": "PROD-001",
  "name": "Творог 5% (обновленный)",
  "category": "finished_product"
}

Кто может потреблять

  • ETL Service — для синхронизации с внешними системами
  • Analytics Service — для обновления аналитики

ProductionOrderCreatedEvent

Публикуется при создании производственного заказа.

Exchange: efko.production.events
Routing Key: production.order.created.event
Когда публикуется: После успешного создания в CreateOrderUseCase

Payload

{
  id: string;              // UUID заказа
  externalOrderId: string;  // Внешний номер заказа
  productId: string;       // UUID продукта
  status: OrderStatus;     // Статус заказа
}

Пример

{
  "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "externalOrderId": "EXT-ORDER-001",
  "productId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "planned"
}

Кто может потреблять

  • Personnel Service — для планирования персонала
  • Analytics Service — для аналитики по заказам

ProductionOrderStatusUpdatedEvent

Публикуется при обновлении статуса заказа.

Exchange: efko.production.events
Routing Key: production.order.status-updated.event
Когда публикуется: После успешного обновления статуса в UpdateOrderStatusUseCase

Payload

{
  id: string;              // UUID заказа
  status: OrderStatus;     // Новый статус
  actualQuantity: number | null; // Фактическое количество
  actualStart: string | null; // Фактическое начало (ISO datetime)
  actualEnd: string | null;   // Фактическое окончание (ISO datetime)
}

Пример

{
  "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "status": "completed",
  "actualQuantity": 950,
  "actualStart": "2025-01-02T06:00:00Z",
  "actualEnd": "2025-01-09T18:00:00Z"
}

Кто может потреблять

  • Personnel Service — для освобождения/назначения персонала
  • Analytics Service — для аналитики выполнения заказов
  • Inventory Service — для обновления остатков

ProductionOutputRecordedEvent

Публикуется при регистрации выпуска продукции.

Exchange: efko.production.events
Routing Key: production.output.recorded.event
Когда публикуется: После успешной записи в RecordOutputUseCase

Payload

{
  id: string;         // UUID выпуска
  orderId: string;    // UUID заказа
  lotNumber: string;  // Номер партии
  quantity: number;   // Количество
}

Пример

{
  "id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
  "orderId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "lotNumber": "LOT-2025-001",
  "quantity": 500
}

Кто может потреблять

  • Quality Service — для инициирования контроля качества
  • Inventory Service — для обновления остатков
  • Analytics Service — для аналитики выпуска

ProductionSaleRecordedEvent

Публикуется при регистрации продажи.

Exchange: efko.production.events
Routing Key: production.sale.recorded.event
Когда публикуется: После успешной записи в RecordSaleUseCase

Payload

{
  id: string;         // UUID продажи
  externalId: string; // Внешний ID продажи
  productId: string;  // UUID продукта
  amount: number;     // Сумма продажи
  channel: SaleChannel; // Канал продаж
}

Пример

{
  "id": "d4e5f6a7-b8c9-0123-defa-234567890123",
  "externalId": "SALE-001",
  "productId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "amount": 50000,
  "channel": "retail"
}

Кто может потреблять

  • Inventory Service — для обновления остатков
  • Analytics Service — для аналитики продаж
  • Finance Service — для финансового учета

ProductionInventoryUpdatedEvent

Публикуется при обновлении остатков на складе.

Exchange: efko.production.events
Routing Key: production.inventory.updated.event
Когда публикуется: После успешного upsert в UpsertInventoryUseCase

Payload

{
  id: string;           // UUID остатка
  productId: string;    // UUID продукта
  warehouseCode: string; // Код склада
  quantity: number;     // Количество
}

Пример

{
  "id": "e5f6a7b8-c9d0-1234-efab-345678901234",
  "productId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "warehouseCode": "WH-01",
  "quantity": 200
}

Кто может потреблять

  • Analytics Service — для аналитики остатков
  • Alert Service — для уведомлений о низких остатках

ProductionQualityResultRecordedEvent

Публикуется при регистрации результата контроля качества.

Exchange: efko.production.events
Routing Key: production.quality-result.recorded.event
Когда публикуется: После успешной записи в RecordQualityResultUseCase

Payload

{
  id: string;         // UUID результата
  lotNumber: string;  // Номер партии
  productId: string;  // UUID продукта
  inSpec: boolean;    // Соответствует норме
  decision: QualityDecision; // Решение
}

Пример

{
  "id": "f6a7b8c9-d0e1-2345-fabc-456789012345",
  "lotNumber": "LOT-2025-001",
  "productId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "inSpec": true,
  "decision": "approved"
}

Кто может потреблять

  • Analytics Service — для аналитики качества
  • Alert Service — для уведомлений о браке
  • Production Service — для блокировки выпуска бракованной продукции

ProductionSensorReadingRecordedEvent

Публикуется при записи показания датчика.

Exchange: efko.production.events
Routing Key: production.sensor-reading.recorded.event
Когда публикуется: После успешной записи в RecordSensorReadingUseCase

Payload

{
  id: string;              // UUID показания
  deviceId: string;         // ID устройства
  productionLine: string;  // Производственная линия
  parameterName: string;   // Название параметра
  quality: SensorQuality;  // Качество сигнала
}

Пример

{
  "id": "a7b8c9d0-e1f2-3456-abcd-567890123456",
  "deviceId": "SENSOR-01",
  "productionLine": "Line-1",
  "parameterName": "temperature",
  "quality": "good"
}

Кто может потреблять

  • Analytics Service — для аналитики показаний
  • Alert Service — для уведомлений об отклонениях

ProductionSensorAnomalyDetectedEvent

Публикуется при обнаружении аномалии в показаниях датчика.

Exchange: efko.production.events
Routing Key: production.sensor.anomaly.event
Когда публикуется: При детекции аномалии в SensorAnomalyDetector

Payload

{
  readingId: string;          // UUID показания
  deviceId: string;            // ID устройства
  productionLine: string;      // Производственная линия
  parameterName: string;       // Название параметра
  value: number;               // Значение
  unit: string;                // Единица измерения
  quality: SensorQuality;      // Качество сигнала
  anomalyType: SensorAnomalyType; // Тип аномалии
  severity: SensorAnomalySeverity; // Тяжесть аномалии
  reason: string;              // Причина
  lowerLimit?: number;         // Нижний предел
  upperLimit?: number;         // Верхний предел
  detectedAt: string;          // Время обнаружения (ISO datetime)
}

Пример

{
  "readingId": "a7b8c9d0-e1f2-3456-abcd-567890123456",
  "deviceId": "SENSOR-01",
  "productionLine": "Line-1",
  "parameterName": "temperature",
  "value": 95.5,
  "unit": "°C",
  "quality": "good",
  "anomalyType": "VALUE_OUT_OF_RANGE",
  "severity": "HIGH",
  "reason": "Temperature exceeds upper limit of 85°C",
  "lowerLimit": 60,
  "upperLimit": 85,
  "detectedAt": "2025-01-05T10:30:00Z"
}

Кто может потреблять

  • Alert Service — для немедленных уведомлений
  • Analytics Service — для анализа аномалий
  • Production Service — для автоматической остановки линии

SensorAnomalyType

  • VALUE_OUT_OF_RANGE — Значение вне допустимого диапазона
  • BAD_QUALITY — Плохое качество сигнала
  • MISSING_DATA — Отсутствующие данные
  • DEVIATION_SPIKE — Резкое отклонение

SensorAnomalySeverity

  • LOW — Низкая
  • MEDIUM — Средняя
  • HIGH — Высокая
  • CRITICAL — Критическая

ETL Events

События интеграции с внешними системами.

EtlImportCompletedEvent

Публикуется при успешном завершении импорта.

Exchange: efko.etl.events
Routing Key: etl.import.completed.event
Когда публикуется: После успешного завершения ETL pipeline

Payload

{
  importId: string;      // ID импорта (MongoDB ObjectId)
  sourceSystem: string;  // Источник системы
  importType: string;    // Тип импорта
  status: string;        // Статус (completed)
  recordsCount: number; // Количество записей
  successCount: number; // Количество успешных
  errorCount: number;    // Количество ошибок
  timestamp: string;     // Время завершения (ISO datetime)
}

Пример

{
  "importId": "507f1f77bcf86cd799439011",
  "sourceSystem": "1c_zup",
  "importType": "employees",
  "status": "completed",
  "recordsCount": 150,
  "successCount": 145,
  "errorCount": 5,
  "timestamp": "2025-01-15T14:30:00Z"
}

Кто может потреблять

  • Analytics Service — для аналитики импортов
  • Notification Service — для уведомлений об успешном импорте

EtlImportFailedEvent

Публикуется при неудачном завершении импорта.

Exchange: efko.etl.events
Routing Key: etl.import.failed.event
Когда публикуется: После неудачного завершения ETL pipeline

Payload

{
  importId: string;      // ID импорта (MongoDB ObjectId)
  sourceSystem: string;  // Источник системы
  importType: string;    // Тип импорта
  errorMessage: string;  // Сообщение об ошибке
  timestamp: string;     // Время неудачи (ISO datetime)
}

Пример

{
  "importId": "507f1f77bcf86cd799439011",
  "sourceSystem": "1c_zup",
  "importType": "employees",
  "errorMessage": "Failed to dispatch to personnel-service: timeout",
  "timestamp": "2025-01-15T14:30:00Z"
}

Кто может потреблять

  • Alert Service — для немедленных уведомлений
  • Analytics Service — для анализа проблем импорта
  • Notification Service — для уведомлений об ошибке

Потребление событий

Подписка на события

Для потребления событий из RabbitMQ:

@RabbitSubscribe({
  exchange: 'efko.personnel.events',
  routingKey: 'personnel.employee.created.event',
  queue: 'my-service.personnel.events.queue',
})
async handleEmployeeCreatedEvent(payload: PersonnelEmployeeCreatedEvent) {
  // Обработка события
}

Обработка ошибок

При ошибке обработки события: - Сообщение возвращается в очередь с reject(false) для повторной попытки - После N неудачных попыток сообщение перемещается в DLQ - Статус outbox записи обновляется на FAILED

Корреляция

Все события содержат метаданные для корреляции: - correlationId — связывает с исходным запросом - timestamp — время публикации - sourceService — сервис-источник


Мониторинг событий

RabbitMQ Management UI

Отслеживайте события через RabbitMQ Management UI: - Проверьте наличие сообщений в очередях - Мониторьте rate публикации - Проверьте DLQ (Dead Letter Queue) для неудачных сообщений

Outbox таблица

Мониторинг через SQL:

SELECT * FROM outbox_messages 
WHERE status = 'FAILED' 
ORDER BY created_at DESC 
LIMIT 100;

Логи

ETL и domain сервисы логируют: - Публикацию событий - Ошибки публикации - Retry попытки