Skip to content

BaseSocketEventService

Tổng quan

BaseSocketEventService là lớp cơ sở dùng chung cho các service WebSocket event trên tất cả các gói backend BANA. Nó kế thừa BaseService của IGNIS và cung cấp API thống nhất để broadcast thông điệp và gửi đến các room cụ thể thông qua WebSocketEmitter của IGNIS.

Mỗi gói downstream tạo lớp con cụ thể riêng (ví dụ: SaleSocketEventService, IdentitySocketEventService) bổ sung các phương thức thông báo theo từng miền nghiệp vụ.

Thuộc tínhGiá trị
Nguồnpackages/core/src/base/service/base-socket-event.service.ts
Kế thừaBaseService (từ @venizia/ignis)
Phụ thuộcBaseApplication, WebSocketEmitter

Định nghĩa Lớp

typescript
import { BaseApplication, BaseService, WebSocketDefaults, WebSocketEmitter } from '@venizia/ignis';

export class BaseSocketEventService extends BaseService {
  private _emitter: WebSocketEmitter | null = null;
  private _emitterBindingKey: string;

  constructor(
    protected application: BaseApplication,
    opts: { scope: string; emitterBindingKey: string },
  ) {
    super({ scope: opts.scope });
    this._emitterBindingKey = opts.emitterBindingKey;
  }

  get emitter(): WebSocketEmitter { /* lazy lookup from DI container */ }

  isReady(): boolean;
  async broadcast<PayloadType>(opts: { topic: string; data: PayloadType }): Promise<void>;
  async sendToRoom<PayloadType>(opts: { room: string; topic: string; data: PayloadType }): Promise<void>;
}

Tham số Constructor

Tham sốKiểuMô tả
applicationBaseApplicationInstance ứng dụng IGNIS (được inject qua CoreBindings.APPLICATION_INSTANCE)
opts.scopestringTên scope logger, thường là ClassName.name
opts.emitterBindingKeystringKhóa binding DI nơi WebSocketEmitter được đăng ký

Mẫu Emitter Lazy

WebSocketEmitter không khả dụng tại thời điểm khởi tạo vì các thành phần WebSocket bind nó trong pha binding(), chạy sau khi service được tạo. Getter sử dụng mẫu tra cứu lazy:

Mẫu này đảm bảo service hoạt động chính xác bất kể thứ tự binding DI.

API

isReady()

Kiểm tra xem WebSocketEmitter đã được bind trong DI container chưa. Sử dụng trước khi gọi broadcast() hoặc sendToRoom() để bỏ qua thông báo một cách nhẹ nhàng khi hạ tầng WebSocket không khả dụng.

typescript
isReady(): boolean

Trả về: true nếu emitter đã được bind và có thể truy xuất, false trong trường hợp ngược lại.

broadcast()

Gửi thông điệp đến tất cả client WebSocket đã kết nối bằng cách xuất bản đến room mặc định (WebSocketDefaults.ROOM).

typescript
async broadcast<PayloadType = unknown>(opts: {
  topic: string;
  data: PayloadType;
}): Promise<void>
Tham sốKiểuMô tả
topicstringTên sự kiện mà client sẽ nhận được
dataPayloadTypeDữ liệu payload cần gửi

sendToRoom()

Gửi thông điệp đến tất cả client WebSocket trong một room cụ thể.

typescript
async sendToRoom<PayloadType = unknown>(opts: {
  room: string;
  topic: string;
  data: PayloadType;
}): Promise<void>
Tham sốKiểuMô tả
roomstringTên room đích
topicstringTên sự kiện mà client sẽ nhận được
dataPayloadTypeDữ liệu payload cần gửi

Sử dụng Downstream

Sáu gói kế thừa BaseSocketEventService:

GóiLớp Cụ thểKhóa Binding
@nx/saleSaleSocketEventServiceSaleWebSocketBindingKeys.WEBSOCKET_EMITTER
@nx/identityIdentitySocketEventServiceKhóa riêng của Identity
@nx/commerceCommerceSocketEventServiceKhóa riêng của Commerce
@nx/inventoryInventorySocketEventServiceKhóa riêng của Inventory
@nx/financeFinanceSocketEventServiceKhóa riêng của Finance
@nx/paymentPaymentSocketEventServiceKhóa riêng của Payment

Ví dụ: SaleSocketEventService

typescript
import { BaseSocketEventService, TSaleOrder } from '@nx/core';
import { SaleWebSocketRooms, SaleWebSocketTopics } from '@/common';
import { BaseApplication, CoreBindings, inject } from '@venizia/ignis';
import { SaleWebSocketBindingKeys } from './keys';

export class SaleSocketEventService extends BaseSocketEventService {
  constructor(
    @inject({ key: CoreBindings.APPLICATION_INSTANCE })
    application: BaseApplication,
  ) {
    super(application, {
      scope: SaleSocketEventService.name,
      emitterBindingKey: SaleWebSocketBindingKeys.WEBSOCKET_EMITTER,
    });
  }

  notifyOrderUpdate(opts: { order: TSaleOrder }): void {
    const { order } = opts;

    if (!this.isReady()) {
      this.logger.warn('Socket event service not ready | SKIP notify order WS');
      return;
    }

    const rooms = SaleWebSocketRooms.getSaleOrderRooms({
      saleOrderId: order.id,
      merchantId: order.merchantId,
    });

    Promise.allSettled(
      rooms.map(room =>
        this.sendToRoom({
          room,
          topic: SaleWebSocketTopics.ORDER,
          data: order,
        }),
      ),
    );
  }
}

Mẫu Đăng ký

Mỗi gói đăng ký socket event service bên trong một WebSocketComponent:

typescript
export class ApplicationWebSocketComponent extends BaseComponent {
  override async binding(): Promise<void> {
    const redis = RedisConnectionFactory.create({ /* ... */ });
    const emitter = new WebSocketEmitter({
      identifier: 'my-ws-emitter',
      redisConnection: redis,
    });

    this.application.bind({ key: MyBindingKeys.WEBSOCKET_EMITTER }).toValue(emitter);
    this.application.service(MySocketEventService);
  }
}

Sơ đồ Kiến trúc

Tài liệu Liên quan

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.