Skip to content

IdGenerator

Tong quan

Tien ich IdGenerator la singleton bao boc SnowflakeUidHelper cua IGNIS Framework. No cung cap cac ID phan tan duy nhat toan cau, sap xep theo thoi gian ma khong can phoi hop trung tam. Moi dich vu trong BANA deu su dung IdGenerator de tao khoa chinh.

Nguon: packages/core/src/utilities/id-generator.utility.ts (81 dong)

Cau truc Snowflake ID

┌──────────────────────────────────────────────────────────────────────┐
│                         70-bit Snowflake ID                          │
├──────────────────────────────┬──────────────┬────────────────────────┤
│          Timestamp           │  Worker ID   │        Sequence        │
│          (48 bits)           │  (10 bits)   │       (12 bits)        │
├──────────────────────────────┼──────────────┼────────────────────────┤
│       ~8,919 years range     │   0 - 1023   │       0 - 4095         │
└──────────────────────────────┴──────────────┴────────────────────────┘
Thanh phanBitPham viMo ta
Timestamp48~8,919 namMili giay ke tu epoch
Worker ID100--1023Dinh danh instance duy nhat
Sequence120--4095Bo dem moi mili giay

Dau ra la chuoi ma hoa Base62 nho gon (10--12 ky tu), phu hop lam khoa chinh co so du lieu va dinh danh an toan URL.

Dinh nghia Lop

typescript
import { SnowflakeUidHelper } from '@venizia/ignis';

export class IdGenerator {
  private static instance: SnowflakeUidHelper;

  // Get or create the singleton instance
  static getInstance(opts?: {
    workerId?: number;
    epoch?: bigint;
  }): SnowflakeUidHelper;

  // Reset instance (for testing only)
  static resetInstance(): void;
}

Re-export tu IGNIS

Module re-export cac kieu sau tu @venizia/ignis de tien loi:

ExportKieuMo ta
SnowflakeUidHelperClassTrinh tao ID co so
SnowflakeConfigConstantsDo rong bit, gia tri toi da, epoch mac dinh
IIdGeneratorOptionsInterfaceTuy chon constructor (workerId, epoch)
ISnowflakeParsedIdInterfaceCau truc ID da phan tich (raw, timestamp, workerId, sequence)

Cau hinh

Bien Moi truong

BienBat buocMac dinhMo ta
APP_ENV_SNOWFLAKE_WORKER_IDCo--Worker ID (0--1023), phai duy nhat cho moi instance dich vu
APP_ENV_SNOWFLAKE_EPOCH_CHECKPOINTKhong1735689600000 (2025-01-01 UTC)Dau thoi gian epoch tuy chinh tinh bang mili giay

Gan Worker ID

Moi instance dich vu phai co Worker ID duy nhat de tranh xung dot ID:

bash
# Development
APP_ENV_SNOWFLAKE_WORKER_ID=1

# Production (per instance)
# Instance 1: APP_ENV_SNOWFLAKE_WORKER_ID=1
# Instance 2: APP_ENV_SNOWFLAKE_WORKER_ID=2
# Instance 3: APP_ENV_SNOWFLAKE_WORKER_ID=3
yaml
# docker-compose.yml
services:
  api-1:
    environment:
      - APP_ENV_SNOWFLAKE_WORKER_ID=1
  api-2:
    environment:
      - APP_ENV_SNOWFLAKE_WORKER_ID=2

Cach Su dung

Import

typescript
import { IdGenerator } from '@nx/core';
// or
import { IdGenerator } from '@nx/core/utilities';

Tao ID

typescript
const generator = IdGenerator.getInstance();

// Generate a Base62-encoded ID (recommended)
const id = generator.nextId();
// "9du1sJXO88"

// Generate a raw Snowflake bigint
const snowflakeId = generator.nextSnowflake();
// 130546360012247045n

// Generate multiple IDs
const ids = Array.from({ length: 10 }, () => generator.nextId());

Phan tich ID

Trich xuat timestamp, worker ID, va sequence nhung trong ID hien co:

typescript
const parsed = generator.parseId('9du1sJXO88');
// {
//   raw: 130546360012247045n,
//   timestamp: Date,        // Date object
//   workerId: 1,
//   sequence: 0
// }

Trich xuat Tung Thanh phan

typescript
const snowflakeId = generator.nextSnowflake();

// Extract timestamp
const timestamp = generator.extractTimestamp(snowflakeId);
// Date object

// Extract worker ID
const workerId = generator.extractWorkerId(snowflakeId);
// 1

// Extract sequence
const sequence = generator.extractSequence(snowflakeId);
// 0-4095

// Get current instance's worker ID
const currentWorkerId = generator.getWorkerId();
// 1

Ma hoa va Giai ma Base62

typescript
// Encode any bigint to Base62
const encoded = generator.encodeBase62(130546360012247045n);
// "9du1sJXO88"

// Decode Base62 back to bigint
const decoded = generator.decodeBase62('9du1sJXO88');
// 130546360012247045n

Cau hinh Tuy chinh

typescript
// First call initializes with config
const generator = IdGenerator.getInstance({
  workerId: 100,
  epoch: BigInt(1609459200000), // Custom epoch: 2021-01-01
});

// Subsequent calls return the same instance (options are ignored)
const sameGenerator = IdGenerator.getInstance();

Tom tat API

Phuong thucChu kyMo ta
nextId(): stringTao Snowflake ID ma hoa Base62 (10--12 ky tu)
nextSnowflake(): bigintTao Snowflake ID 70-bit nguyen goc
parseId(base62Id: string): ISnowflakeParsedIdPhan tich ID Base62 thanh cac thanh phan
encodeBase62(num: bigint): stringMa hoa bigint thanh chuoi Base62
decodeBase62(str: string): bigintGiai ma chuoi Base62 thanh bigint
extractTimestamp(id: bigint): DateTrich xuat timestamp tu Snowflake ID nguyen goc
extractWorkerId(id: bigint): numberTrich xuat worker ID tu Snowflake ID nguyen goc
extractSequence(id: bigint): numberTrich xuat so sequence tu Snowflake ID nguyen goc
getWorkerId(): numberLay worker ID cua instance hien tai

Luong Tao ID Phan tan

Tao Khoi luong Lon

Tich hop voi Model

Schema Drizzle

typescript
import { pgTable, text } from 'drizzle-orm/pg-core';
import { IdGenerator } from '@nx/core';

export const User = pgTable('User', {
  id: text('id')
    .primaryKey()
    .$defaultFn(() => IdGenerator.getInstance().nextId()),
  // ... other columns
});

Su dung Repository

typescript
@repository({ dataSource: PostgresCoreDataSource, model: User })
export class UserRepository extends SoftDeletableRepository<TUserSchema, TUser> {
  async createUser(data: TUserCreate): Promise<TUser> {
    const id = IdGenerator.getInstance().nextId();

    return this.create({
      data: {
        id,
        ...data,
        createdAt: new Date(),
      },
    });
  }
}

Xu ly Loi

Thieu Worker ID

typescript
// APP_ENV_SNOWFLAKE_WORKER_ID is not set
try {
  IdGenerator.getInstance();
} catch (error) {
  // [IdGenerator][getWorkerIdFromEnv] Missing required environment variable
  // APP_ENV_SNOWFLAKE_WORKER_ID | hint: Set APP_ENV_SNOWFLAKE_WORKER_ID
  // in between 0 and 1023 for each service instance
}

Worker ID Khong hop le

typescript
// APP_ENV_SNOWFLAKE_WORKER_ID="abc"
try {
  IdGenerator.getInstance();
} catch (error) {
  // [IdGenerator][getWorkerIdFromEnv] Invalid APP_ENV_SNOWFLAKE_WORKER_ID value
  // received: abc | expected: number between 0 and 1023
}

Epoch Khong hop le

typescript
// APP_ENV_SNOWFLAKE_EPOCH_CHECKPOINT="not-a-number"
try {
  IdGenerator.getInstance();
} catch (error) {
  // [IdGenerator][getEpochFromEnv] Invalid APP_ENV_SNOWFLAKE_EPOCH_CHECKPOINT value
  // received: not-a-number | expected: timestamp in milliseconds
}

Kiem thu

Dat lai de Co Trang thai Sach

typescript
describe('UserService', () => {
  beforeEach(() => {
    // Reset singleton for clean state
    IdGenerator.resetInstance();

    // Set test worker ID
    process.env.APP_ENV_SNOWFLAKE_WORKER_ID = '999';
  });

  it('generates user with Snowflake ID', async () => {
    const user = await userService.create({ name: 'Test' });
    expect(user.id).toBeTruthy();
  });
});

Mock Trinh tao

typescript
jest.mock('@nx/core/utilities', () => ({
  IdGenerator: {
    getInstance: () => ({
      nextId: jest.fn().mockReturnValue('mockId123'),
    }),
  },
}));

WARNING

Khong bao gio goi IdGenerator.resetInstance() trong production. No duoc thiet ke chi danh rieng cho viec co lap test.

Tham chieu IGNIS Framework

IdGenerator bao boc SnowflakeUidHelper cua IGNIS. De xem day du API, bao gom xu ly troi dong ho, hanh vi canh sequence, va tat ca hang so cau hinh, xem tham chieu IGNIS UID Helper:

Tai lieu Lien quan

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