distid
Version:
Distributed ID generator for large-scale systems
72 lines (71 loc) • 2.76 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DistIdGenerator = void 0;
const utils_1 = require("./utils");
const logger_1 = require("./logger");
class DistIdGenerator {
constructor(config) {
this.counter = 0;
this.lastTimestamp = 0;
(0, utils_1.validateNodeId)(config.nodeId, DistIdGenerator.usedNodeIds);
this.nodeId = config.nodeId & 0x3ff; // 10 bit
DistIdGenerator.usedNodeIds.add(this.nodeId);
this.epoch = config.epoch || new Date('2020-01-01').getTime();
this.counterBits = config.counterBits || 12;
if (this.counterBits < 8 || this.counterBits > 20) {
throw new Error('Counter bits must be between 8 and 20');
}
this.logger = config.logger || logger_1.defaultLogger;
this.logger(`Initialized DistIdGenerator with nodeId: ${this.nodeId}`);
}
getTimestamp() {
return Date.now() - this.epoch;
}
incrementCounter(timestamp) {
if (timestamp !== this.lastTimestamp) {
this.counter = 0;
this.lastTimestamp = timestamp;
}
const maxCounter = (1 << this.counterBits) - 1;
if (this.counter > maxCounter) {
this.logger('Counter overflow, waiting for next millisecond');
while (this.getTimestamp() === this.lastTimestamp) {
// Wait for the next millisecond
}
return this.incrementCounter(this.getTimestamp());
}
return this.counter++;
}
/**
* Generates a distributed ID for large-scale systems.
* @param format - The output format of the ID ('number', 'hex', 'base36', 'base62').
* @returns A unique ID in the specified format.
* @example
* const gen = new DistIdGenerator({ nodeId: 5 });
* console.log(gen.generate('hex')); // e.g., "13a8f5c00050007b"
*/
generate(format = 'number') {
const timestamp = this.getTimestamp();
const counter = this.incrementCounter(timestamp);
const id = (BigInt(timestamp) << BigInt(23)) |
(BigInt(this.nodeId) << BigInt(this.counterBits)) |
BigInt(counter);
this.logger(`Generated ID: ${id} (format: ${format})`);
switch (format) {
case 'hex':
return id.toString(16).padStart(16, '0');
case 'base36':
return id.toString(36);
case 'base62':
return (0, utils_1.toBase62)(id);
case 'number':
default:
return id;
}
}
static resetNodeIds() {
DistIdGenerator.usedNodeIds.clear();
}
}
exports.DistIdGenerator = DistIdGenerator;
DistIdGenerator.usedNodeIds = new Set();