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 phan | Bit | Pham vi | Mo ta |
|---|---|---|---|
| Timestamp | 48 | ~8,919 nam | Mili giay ke tu epoch |
| Worker ID | 10 | 0--1023 | Dinh danh instance duy nhat |
| Sequence | 12 | 0--4095 | Bo 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
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:
| Export | Kieu | Mo ta |
|---|---|---|
SnowflakeUidHelper | Class | Trinh tao ID co so |
SnowflakeConfig | Constants | Do rong bit, gia tri toi da, epoch mac dinh |
IIdGeneratorOptions | Interface | Tuy chon constructor (workerId, epoch) |
ISnowflakeParsedId | Interface | Cau truc ID da phan tich (raw, timestamp, workerId, sequence) |
Cau hinh
Bien Moi truong
| Bien | Bat buoc | Mac dinh | Mo ta |
|---|---|---|---|
APP_ENV_SNOWFLAKE_WORKER_ID | Co | -- | Worker ID (0--1023), phai duy nhat cho moi instance dich vu |
APP_ENV_SNOWFLAKE_EPOCH_CHECKPOINT | Khong | 1735689600000 (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:
# 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# docker-compose.yml
services:
api-1:
environment:
- APP_ENV_SNOWFLAKE_WORKER_ID=1
api-2:
environment:
- APP_ENV_SNOWFLAKE_WORKER_ID=2Cach Su dung
Import
import { IdGenerator } from '@nx/core';
// or
import { IdGenerator } from '@nx/core/utilities';Tao ID
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:
const parsed = generator.parseId('9du1sJXO88');
// {
// raw: 130546360012247045n,
// timestamp: Date, // Date object
// workerId: 1,
// sequence: 0
// }Trich xuat Tung Thanh phan
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();
// 1Ma hoa va Giai ma Base62
// Encode any bigint to Base62
const encoded = generator.encodeBase62(130546360012247045n);
// "9du1sJXO88"
// Decode Base62 back to bigint
const decoded = generator.decodeBase62('9du1sJXO88');
// 130546360012247045nCau hinh Tuy chinh
// 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 thuc | Chu ky | Mo ta |
|---|---|---|
nextId | (): string | Tao Snowflake ID ma hoa Base62 (10--12 ky tu) |
nextSnowflake | (): bigint | Tao Snowflake ID 70-bit nguyen goc |
parseId | (base62Id: string): ISnowflakeParsedId | Phan tich ID Base62 thanh cac thanh phan |
encodeBase62 | (num: bigint): string | Ma hoa bigint thanh chuoi Base62 |
decodeBase62 | (str: string): bigint | Giai ma chuoi Base62 thanh bigint |
extractTimestamp | (id: bigint): Date | Trich xuat timestamp tu Snowflake ID nguyen goc |
extractWorkerId | (id: bigint): number | Trich xuat worker ID tu Snowflake ID nguyen goc |
extractSequence | (id: bigint): number | Trich xuat so sequence tu Snowflake ID nguyen goc |
getWorkerId | (): number | Lay worker ID cua instance hien tai |
Luong Tao ID Phan tan
Tao Khoi luong Lon
Tich hop voi Model
Schema Drizzle
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
@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
// 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
// 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
// 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
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
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: