@cdlab996/genid 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +141 -244
- package/dist/index.cjs +85 -237
- package/dist/index.d.cts +71 -238
- package/dist/index.d.mts +71 -238
- package/dist/index.mjs +83 -235
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -1,29 +1,55 @@
|
|
|
1
|
-
//#region src/types
|
|
2
|
-
/**
|
|
3
|
-
* ID 生成算法类型
|
|
4
|
-
*/
|
|
1
|
+
//#region src/types.ts
|
|
2
|
+
/** ID 生成算法类型 */
|
|
5
3
|
let GenidMethod = /* @__PURE__ */ function(GenidMethod) {
|
|
6
|
-
/**
|
|
4
|
+
/** 漂移算法(推荐,高并发下可突破每毫秒序列号上限) */
|
|
7
5
|
GenidMethod[GenidMethod["DRIFT"] = 1] = "DRIFT";
|
|
8
|
-
/**
|
|
6
|
+
/** 传统算法(序列号耗尽时等待下一毫秒) */
|
|
9
7
|
GenidMethod[GenidMethod["TRADITIONAL"] = 2] = "TRADITIONAL";
|
|
10
8
|
return GenidMethod;
|
|
11
9
|
}({});
|
|
12
|
-
|
|
13
10
|
//#endregion
|
|
14
|
-
//#region src/
|
|
11
|
+
//#region src/config.ts
|
|
12
|
+
/** 将用户配置与默认值合并,返回完整内部配置 */
|
|
13
|
+
function initConfig(options) {
|
|
14
|
+
const config = {
|
|
15
|
+
workerId: options.workerId,
|
|
16
|
+
method: options.method === GenidMethod.TRADITIONAL ? GenidMethod.TRADITIONAL : GenidMethod.DRIFT,
|
|
17
|
+
baseTime: options.baseTime && options.baseTime > 0 ? options.baseTime : (/* @__PURE__ */ new Date("2020-01-01")).valueOf(),
|
|
18
|
+
workerIdBitLength: options.workerIdBitLength && options.workerIdBitLength > 0 ? options.workerIdBitLength : 6,
|
|
19
|
+
seqBitLength: options.seqBitLength && options.seqBitLength > 0 ? options.seqBitLength : 6,
|
|
20
|
+
maxSeqNumber: 0,
|
|
21
|
+
minSeqNumber: 0,
|
|
22
|
+
topOverCostCount: 0
|
|
23
|
+
};
|
|
24
|
+
config.maxSeqNumber = options.maxSeqNumber && options.maxSeqNumber > 0 ? options.maxSeqNumber : (1 << config.seqBitLength) - 1;
|
|
25
|
+
config.minSeqNumber = options.minSeqNumber && options.minSeqNumber > 0 ? options.minSeqNumber : 5;
|
|
26
|
+
config.topOverCostCount = options.topOverCostCount && options.topOverCostCount > 0 ? options.topOverCostCount : 2e3;
|
|
27
|
+
return config;
|
|
28
|
+
}
|
|
29
|
+
/** 校验配置合法性,不合法则抛出 Error */
|
|
30
|
+
function validateConfig(config) {
|
|
31
|
+
const { workerId, baseTime, workerIdBitLength, seqBitLength, minSeqNumber, maxSeqNumber } = config;
|
|
32
|
+
if (baseTime > Date.now()) throw new Error("[GenidOptimized] baseTime 不能大于当前时间");
|
|
33
|
+
if (workerIdBitLength < 1 || workerIdBitLength > 15) throw new Error("[GenidOptimized] workerIdBitLength 必须在 1 到 15 之间");
|
|
34
|
+
if (seqBitLength < 3 || seqBitLength > 21) throw new Error("[GenidOptimized] seqBitLength 必须在 3 到 21 之间");
|
|
35
|
+
if (workerIdBitLength + seqBitLength > 22) throw new Error("[GenidOptimized] workerIdBitLength + seqBitLength 不能超过 22");
|
|
36
|
+
const maxWorkerId = (1 << workerIdBitLength) - 1;
|
|
37
|
+
if (workerId < 0 || workerId > maxWorkerId) throw new Error(`[GenidOptimized] workerId 必须在 0 到 ${maxWorkerId} 之间`);
|
|
38
|
+
if (minSeqNumber < 5) throw new Error("[GenidOptimized] minSeqNumber 必须至少为 5(0-4 保留)");
|
|
39
|
+
if (maxSeqNumber < minSeqNumber) throw new Error("[GenidOptimized] maxSeqNumber 必须大于或等于 minSeqNumber");
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/genid.ts
|
|
15
43
|
/**
|
|
16
|
-
*
|
|
44
|
+
* 基于 Snowflake 算法的分布式唯一 ID 生成器
|
|
17
45
|
*
|
|
18
|
-
*
|
|
46
|
+
* - 漂移算法:高并发下借用未来时间戳,突破每毫秒序列号上限
|
|
47
|
+
* - 时钟回拨:使用保留序列号(0-4)优雅降级,不阻塞生成
|
|
48
|
+
* - 非线程安全,每个 Worker/进程应使用独立实例和不同 workerId
|
|
19
49
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* - 可配置的位长度,灵活性高
|
|
24
|
-
* - 支持传统和漂移两种生成方法
|
|
25
|
-
*
|
|
26
|
-
* ⚠️ 注意:此实例不是线程安全的,每个 Worker/进程应该创建独立的实例并使用不同的 workerId
|
|
50
|
+
* @example
|
|
51
|
+
* const genid = new GenidOptimized({ workerId: 1 });
|
|
52
|
+
* const id = genid.nextId();
|
|
27
53
|
*/
|
|
28
54
|
var GenidOptimized = class {
|
|
29
55
|
method;
|
|
@@ -42,29 +68,10 @@ var GenidOptimized = class {
|
|
|
42
68
|
_isOverCost;
|
|
43
69
|
_overCostCountInOneTerm;
|
|
44
70
|
_stats;
|
|
45
|
-
/**
|
|
46
|
-
* 构造函数,初始化 ID 生成器
|
|
47
|
-
*
|
|
48
|
-
* @param {Object} options - 配置选项
|
|
49
|
-
* @param {number} options.workerId - 工作节点/机器 ID(必须,范围 0 到 2^workerIdBitLength-1)
|
|
50
|
-
* @param {GenidMethod} [options.method=GenidMethod.DRIFT] - 算法类型
|
|
51
|
-
* @param {number} [options.baseTime=1577836800000] - 起始时间戳(毫秒,默认:2020-01-01)
|
|
52
|
-
* @param {number} [options.workerIdBitLength=6] - 工作节点 ID 的位数(1-15,默认:6)
|
|
53
|
-
* @param {number} [options.seqBitLength=6] - 序列号的位数(3-21,默认:6)
|
|
54
|
-
* @param {number} [options.maxSeqNumber] - 最大序列号(默认:2^seqBitLength-1)
|
|
55
|
-
* @param {number} [options.minSeqNumber=5] - 最小序列号(默认:5,0-4 保留)
|
|
56
|
-
* @param {number} [options.topOverCostCount=2000] - 最大漂移次数(默认:2000)
|
|
57
|
-
*
|
|
58
|
-
* @throws {Error} 如果缺少 workerId 或配置无效
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* const genid = new GenidOptimized({ workerId: 1 });
|
|
62
|
-
* const id = genid.nextId();
|
|
63
|
-
*/
|
|
64
71
|
constructor(options) {
|
|
65
72
|
if (options.workerId === void 0 || options.workerId === null) throw new Error("[GenidOptimized] workerId 是必须参数");
|
|
66
|
-
const config =
|
|
67
|
-
|
|
73
|
+
const config = initConfig(options);
|
|
74
|
+
validateConfig(config);
|
|
68
75
|
this._initVariables(config);
|
|
69
76
|
this._stats = {
|
|
70
77
|
totalGenerated: 0n,
|
|
@@ -73,49 +80,6 @@ var GenidOptimized = class {
|
|
|
73
80
|
startTime: Date.now()
|
|
74
81
|
};
|
|
75
82
|
}
|
|
76
|
-
/**
|
|
77
|
-
* 初始化配置,设置默认值
|
|
78
|
-
* @private
|
|
79
|
-
* @param {Object} options - 用户提供的配置
|
|
80
|
-
* @returns {Object} 合并后的配置对象
|
|
81
|
-
*/
|
|
82
|
-
_initConfig(options) {
|
|
83
|
-
const config = {
|
|
84
|
-
workerId: options.workerId,
|
|
85
|
-
method: options.method === GenidMethod.TRADITIONAL ? GenidMethod.TRADITIONAL : GenidMethod.DRIFT,
|
|
86
|
-
baseTime: options.baseTime && options.baseTime > 0 ? options.baseTime : (/* @__PURE__ */ new Date("2020-01-01")).valueOf(),
|
|
87
|
-
workerIdBitLength: options.workerIdBitLength && options.workerIdBitLength > 0 ? options.workerIdBitLength : 6,
|
|
88
|
-
seqBitLength: options.seqBitLength && options.seqBitLength > 0 ? options.seqBitLength : 6,
|
|
89
|
-
maxSeqNumber: 0,
|
|
90
|
-
minSeqNumber: 0,
|
|
91
|
-
topOverCostCount: 0
|
|
92
|
-
};
|
|
93
|
-
config.maxSeqNumber = options.maxSeqNumber && options.maxSeqNumber > 0 ? options.maxSeqNumber : (1 << config.seqBitLength) - 1;
|
|
94
|
-
config.minSeqNumber = options.minSeqNumber && options.minSeqNumber > 0 ? options.minSeqNumber : 5;
|
|
95
|
-
config.topOverCostCount = options.topOverCostCount && options.topOverCostCount > 0 ? options.topOverCostCount : 2e3;
|
|
96
|
-
return config;
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* 验证配置参数的有效性
|
|
100
|
-
* @private
|
|
101
|
-
* @param {Object} config - 配置对象
|
|
102
|
-
* @throws {Error} 如果配置无效
|
|
103
|
-
*/
|
|
104
|
-
_validateConfig(config) {
|
|
105
|
-
const { workerId, workerIdBitLength, seqBitLength, minSeqNumber, maxSeqNumber } = config;
|
|
106
|
-
if (workerIdBitLength < 1 || workerIdBitLength > 15) throw new Error("[GenidOptimized] workerIdBitLength 必须在 1 到 15 之间");
|
|
107
|
-
if (seqBitLength < 3 || seqBitLength > 21) throw new Error("[GenidOptimized] seqBitLength 必须在 3 到 21 之间");
|
|
108
|
-
if (workerIdBitLength + seqBitLength > 22) throw new Error("[GenidOptimized] workerIdBitLength + seqBitLength 不能超过 22");
|
|
109
|
-
const maxWorkerId = (1 << workerIdBitLength) - 1;
|
|
110
|
-
if (workerId < 0 || workerId > maxWorkerId) throw new Error(`[GenidOptimized] workerId 必须在 0 到 ${maxWorkerId} 之间`);
|
|
111
|
-
if (minSeqNumber < 5) throw new Error("[GenidOptimized] minSeqNumber 必须至少为 5(0-4 保留)");
|
|
112
|
-
if (maxSeqNumber < minSeqNumber) throw new Error("[GenidOptimized] maxSeqNumber 必须大于或等于 minSeqNumber");
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* 初始化实例变量
|
|
116
|
-
* @private
|
|
117
|
-
* @param {Object} config - 配置对象
|
|
118
|
-
*/
|
|
119
83
|
_initVariables(config) {
|
|
120
84
|
this.method = BigInt(config.method);
|
|
121
85
|
this.baseTime = BigInt(config.baseTime);
|
|
@@ -133,64 +97,37 @@ var GenidOptimized = class {
|
|
|
133
97
|
this._isOverCost = false;
|
|
134
98
|
this._overCostCountInOneTerm = 0n;
|
|
135
99
|
}
|
|
136
|
-
/**
|
|
137
|
-
* 获取当前时间戳(相对于 baseTime 的毫秒数)
|
|
138
|
-
* @private
|
|
139
|
-
* @returns {bigint} 当前时间戳
|
|
140
|
-
*/
|
|
100
|
+
/** 获取相对于 baseTime 的当前时间戳 */
|
|
141
101
|
_getCurrentTimeTick() {
|
|
142
102
|
return BigInt(Date.now()) - this.baseTime;
|
|
143
103
|
}
|
|
144
|
-
/**
|
|
145
|
-
* 等待下一毫秒
|
|
146
|
-
* @private
|
|
147
|
-
* @returns {bigint} 下一毫秒时间戳
|
|
148
|
-
*/
|
|
104
|
+
/** 自旋等待直到时间前进到下一毫秒 */
|
|
149
105
|
_getNextTimeTick() {
|
|
150
106
|
let timeTick = this._getCurrentTimeTick();
|
|
151
107
|
let spinCount = 0;
|
|
152
108
|
const maxSpinCount = 1e6;
|
|
153
109
|
while (timeTick <= this._lastTimeTick) {
|
|
154
110
|
spinCount++;
|
|
155
|
-
if (spinCount > maxSpinCount)
|
|
156
|
-
/**
|
|
157
|
-
* 如果自旋太多次,强制返回当前时间 + 1
|
|
158
|
-
* 这种情况理论上不应该发生,除非系统时间出现严重问题
|
|
159
|
-
*/
|
|
160
|
-
return this._lastTimeTick + 1n;
|
|
111
|
+
if (spinCount > maxSpinCount) return this._lastTimeTick + 1n;
|
|
161
112
|
timeTick = this._getCurrentTimeTick();
|
|
162
113
|
}
|
|
163
114
|
return timeTick;
|
|
164
115
|
}
|
|
165
|
-
/**
|
|
166
|
-
* 根据组件计算 ID
|
|
167
|
-
* @private
|
|
168
|
-
* @param {bigint} useTimeTick - 使用的时间戳
|
|
169
|
-
* @returns {bigint} 计算得到的 ID
|
|
170
|
-
*/
|
|
116
|
+
/** 组装 ID:timestamp | workerId | sequence,并自增序列号 */
|
|
171
117
|
_calcId(useTimeTick) {
|
|
172
118
|
const result = (BigInt(useTimeTick) << this._timestampShift) + (this.workerId << this.seqBitLength) + this._currentSeqNumber;
|
|
173
119
|
this._currentSeqNumber++;
|
|
174
120
|
this._stats.totalGenerated++;
|
|
175
121
|
return result;
|
|
176
122
|
}
|
|
177
|
-
/**
|
|
178
|
-
* 计算时钟回拨时的 ID
|
|
179
|
-
* @private
|
|
180
|
-
* @param {bigint} useTimeTick - 使用的时间戳
|
|
181
|
-
* @returns {bigint} 计算得到的 ID
|
|
182
|
-
*/
|
|
123
|
+
/** 时钟回拨时组装 ID,使用保留序列号(0-4)避免冲突 */
|
|
183
124
|
_calcTurnBackId(useTimeTick) {
|
|
184
125
|
const result = (BigInt(useTimeTick) << this._timestampShift) + (this.workerId << this.seqBitLength) + BigInt(this._turnBackIndex);
|
|
185
126
|
this._turnBackTimeTick++;
|
|
186
127
|
this._stats.totalGenerated++;
|
|
187
128
|
return result;
|
|
188
129
|
}
|
|
189
|
-
/**
|
|
190
|
-
* 处理漂移情况(漂移算法)
|
|
191
|
-
* @private
|
|
192
|
-
* @returns {bigint} 生成的 ID
|
|
193
|
-
*/
|
|
130
|
+
/** 漂移状态下生成 ID */
|
|
194
131
|
_nextOverCostId() {
|
|
195
132
|
const currentTimeTick = this._getCurrentTimeTick();
|
|
196
133
|
if (currentTimeTick > this._lastTimeTick) {
|
|
@@ -226,11 +163,7 @@ var GenidOptimized = class {
|
|
|
226
163
|
}
|
|
227
164
|
return this._calcId(this._lastTimeTick);
|
|
228
165
|
}
|
|
229
|
-
/**
|
|
230
|
-
* 正常生成 ID
|
|
231
|
-
* @private
|
|
232
|
-
* @returns {bigint} 生成的 ID
|
|
233
|
-
*/
|
|
166
|
+
/** 正常状态下生成 ID */
|
|
234
167
|
_nextNormalId() {
|
|
235
168
|
const currentTimeTick = this._getCurrentTimeTick();
|
|
236
169
|
if (currentTimeTick < this._lastTimeTick) {
|
|
@@ -247,6 +180,13 @@ var GenidOptimized = class {
|
|
|
247
180
|
this._beginTurnBackAction(this._turnBackTimeTick);
|
|
248
181
|
this._stats.turnBackCount++;
|
|
249
182
|
}
|
|
183
|
+
if (this._turnBackTimeTick >= this._lastTimeTick) {
|
|
184
|
+
this._turnBackTimeTick = 0n;
|
|
185
|
+
this._turnBackIndex = 0;
|
|
186
|
+
this._lastTimeTick = this._getNextTimeTick();
|
|
187
|
+
this._currentSeqNumber = this.minSeqNumber;
|
|
188
|
+
return this._calcId(this._lastTimeTick);
|
|
189
|
+
}
|
|
250
190
|
return this._calcTurnBackId(this._turnBackTimeTick);
|
|
251
191
|
}
|
|
252
192
|
if (this._turnBackTimeTick > 0) {
|
|
@@ -260,6 +200,11 @@ var GenidOptimized = class {
|
|
|
260
200
|
return this._calcId(this._lastTimeTick);
|
|
261
201
|
}
|
|
262
202
|
if (this._currentSeqNumber > this.maxSeqNumber) {
|
|
203
|
+
if (this.method === BigInt(GenidMethod.TRADITIONAL)) {
|
|
204
|
+
this._lastTimeTick = this._getNextTimeTick();
|
|
205
|
+
this._currentSeqNumber = this.minSeqNumber;
|
|
206
|
+
return this._calcId(this._lastTimeTick);
|
|
207
|
+
}
|
|
263
208
|
this._beginOverCostAction(currentTimeTick);
|
|
264
209
|
this._lastTimeTick++;
|
|
265
210
|
this._currentSeqNumber = this.minSeqNumber;
|
|
@@ -270,83 +215,29 @@ var GenidOptimized = class {
|
|
|
270
215
|
}
|
|
271
216
|
return this._calcId(this._lastTimeTick);
|
|
272
217
|
}
|
|
218
|
+
_beginOverCostAction(_useTimeTick) {}
|
|
219
|
+
_endOverCostAction(_useTimeTick) {}
|
|
220
|
+
_beginTurnBackAction(_useTimeTick) {}
|
|
221
|
+
_endTurnBackAction(_useTimeTick) {}
|
|
273
222
|
/**
|
|
274
|
-
*
|
|
275
|
-
* @
|
|
276
|
-
* @param {bigint} useTimeTick - 当前时间戳
|
|
277
|
-
*/
|
|
278
|
-
_beginOverCostAction(useTimeTick) {}
|
|
279
|
-
/**
|
|
280
|
-
* 钩子函数:结束漂移操作(可被子类重写)
|
|
281
|
-
* @protected
|
|
282
|
-
* @param {bigint} useTimeTick - 当前时间戳
|
|
283
|
-
*/
|
|
284
|
-
_endOverCostAction(useTimeTick) {}
|
|
285
|
-
/**
|
|
286
|
-
* 钩子函数:开始时钟回拨操作(可被子类重写)
|
|
287
|
-
* @protected
|
|
288
|
-
* @param {bigint} useTimeTick - 当前时间戳
|
|
289
|
-
*/
|
|
290
|
-
_beginTurnBackAction(useTimeTick) {}
|
|
291
|
-
/**
|
|
292
|
-
* 钩子函数:结束时钟回拨操作(可被子类重写)
|
|
293
|
-
* @protected
|
|
294
|
-
* @param {bigint} useTimeTick - 当前时间戳
|
|
295
|
-
*/
|
|
296
|
-
_endTurnBackAction(useTimeTick) {}
|
|
297
|
-
/**
|
|
298
|
-
* 生成下一个 ID
|
|
299
|
-
*
|
|
300
|
-
* @returns {number} 唯一 ID(Number 类型)
|
|
301
|
-
* @throws {Error} 如果 ID 超出 JavaScript 安全整数范围
|
|
302
|
-
*
|
|
303
|
-
* @example
|
|
304
|
-
* const id = genid.nextNumber();
|
|
305
|
-
* console.log(id); // 123456789012345
|
|
223
|
+
* 生成 ID,返回 number。超出安全整数范围时抛错。
|
|
224
|
+
* @throws 当 ID >= Number.MAX_SAFE_INTEGER + 1 时
|
|
306
225
|
*/
|
|
307
226
|
nextNumber() {
|
|
308
227
|
const id = this._isOverCost ? this._nextOverCostId() : this._nextNormalId();
|
|
309
228
|
if (id >= 9007199254740992n) throw new Error(`[GenidOptimized] 生成的 ID ${id.toString()} 超出 JavaScript 安全整数范围 (9007199254740992)。请使用 nextBigId() 方法。`);
|
|
310
229
|
return Number(id);
|
|
311
230
|
}
|
|
312
|
-
/**
|
|
313
|
-
* 生成下一个 ID
|
|
314
|
-
*
|
|
315
|
-
* 如果 ID 在安全范围内返回 Number,否则返回 BigInt
|
|
316
|
-
*
|
|
317
|
-
* @returns {number|bigint} 唯一 ID
|
|
318
|
-
*
|
|
319
|
-
* @example
|
|
320
|
-
* const id = genid.nextId();
|
|
321
|
-
* console.log(typeof id); // 'number' 或 'bigint'
|
|
322
|
-
*/
|
|
231
|
+
/** 生成 ID,安全范围内返回 number,否则返回 bigint */
|
|
323
232
|
nextId() {
|
|
324
233
|
const id = this._isOverCost ? this._nextOverCostId() : this._nextNormalId();
|
|
325
234
|
return id >= 9007199254740992n ? id : Number(id);
|
|
326
235
|
}
|
|
327
|
-
/**
|
|
328
|
-
* 生成下一个 ID
|
|
329
|
-
*
|
|
330
|
-
* @returns {bigint} 唯一 ID(BigInt 类型)
|
|
331
|
-
*
|
|
332
|
-
* @example
|
|
333
|
-
* const id = genid.nextBigId();
|
|
334
|
-
* console.log(id); // 123456789012345678n
|
|
335
|
-
*/
|
|
236
|
+
/** 生成 ID,始终返回 bigint */
|
|
336
237
|
nextBigId() {
|
|
337
238
|
return this._isOverCost ? this._nextOverCostId() : this._nextNormalId();
|
|
338
239
|
}
|
|
339
|
-
/**
|
|
340
|
-
* 批量生成 ID
|
|
341
|
-
*
|
|
342
|
-
* @param {number} count - 要生成的 ID 数量
|
|
343
|
-
* @param {boolean} [asBigInt=false] - 是否返回 BigInt 数组
|
|
344
|
-
* @returns {Array<number|bigint>} 唯一 ID 数组
|
|
345
|
-
*
|
|
346
|
-
* @example
|
|
347
|
-
* const ids = genid.nextBatch(100);
|
|
348
|
-
* const bigIds = genid.nextBatch(100, true);
|
|
349
|
-
*/
|
|
240
|
+
/** 批量生成 ID */
|
|
350
241
|
nextBatch(count, asBigInt = false) {
|
|
351
242
|
if (count <= 0) throw new Error("[GenidOptimized] 批量生成数量必须大于 0");
|
|
352
243
|
const ids = [];
|
|
@@ -354,24 +245,11 @@ var GenidOptimized = class {
|
|
|
354
245
|
return ids;
|
|
355
246
|
}
|
|
356
247
|
/**
|
|
357
|
-
* 解析 ID
|
|
358
|
-
*
|
|
359
|
-
* @param {number|bigint|string} id - 要解析的 ID
|
|
360
|
-
* @returns {Object} 解析结果
|
|
361
|
-
* @returns {Date} return.timestamp - 生成时间戳
|
|
362
|
-
* @returns {number} return.timestampMs - 时间戳(毫秒)
|
|
363
|
-
* @returns {number} return.workerId - 工作节点 ID
|
|
364
|
-
* @returns {number} return.sequence - 序列号
|
|
248
|
+
* 解析 ID,提取时间戳、workerId、序列号
|
|
365
249
|
*
|
|
366
250
|
* @example
|
|
367
|
-
*
|
|
368
|
-
*
|
|
369
|
-
* // {
|
|
370
|
-
* // timestamp: Date,
|
|
371
|
-
* // timestampMs: 1609459200000,
|
|
372
|
-
* // workerId: 1,
|
|
373
|
-
* // sequence: 42
|
|
374
|
-
* // }
|
|
251
|
+
* genid.parse(id)
|
|
252
|
+
* // { timestamp: Date, timestampMs: 1609459200000, workerId: 1, sequence: 42 }
|
|
375
253
|
*/
|
|
376
254
|
parse(id) {
|
|
377
255
|
const idBigInt = BigInt(id);
|
|
@@ -387,15 +265,7 @@ var GenidOptimized = class {
|
|
|
387
265
|
sequence: Number(sequence)
|
|
388
266
|
};
|
|
389
267
|
}
|
|
390
|
-
/**
|
|
391
|
-
* 获取生成器统计信息
|
|
392
|
-
*
|
|
393
|
-
* @returns {Object} 统计数据
|
|
394
|
-
*
|
|
395
|
-
* @example
|
|
396
|
-
* const stats = genid.getStats();
|
|
397
|
-
* console.log(stats);
|
|
398
|
-
*/
|
|
268
|
+
/** 获取运行统计信息 */
|
|
399
269
|
getStats() {
|
|
400
270
|
const uptime = Date.now() - this._stats.startTime;
|
|
401
271
|
const totalGenerated = Number(this._stats.totalGenerated);
|
|
@@ -408,9 +278,7 @@ var GenidOptimized = class {
|
|
|
408
278
|
currentState: this._isOverCost ? "OVER_COST" : "NORMAL"
|
|
409
279
|
};
|
|
410
280
|
}
|
|
411
|
-
/**
|
|
412
|
-
* 重置统计数据
|
|
413
|
-
*/
|
|
281
|
+
/** 重置统计数据 */
|
|
414
282
|
resetStats() {
|
|
415
283
|
this._stats = {
|
|
416
284
|
totalGenerated: 0n,
|
|
@@ -419,11 +287,7 @@ var GenidOptimized = class {
|
|
|
419
287
|
startTime: Date.now()
|
|
420
288
|
};
|
|
421
289
|
}
|
|
422
|
-
/**
|
|
423
|
-
* 获取配置信息
|
|
424
|
-
*
|
|
425
|
-
* @returns {Object} 配置详情
|
|
426
|
-
*/
|
|
290
|
+
/** 获取当前配置信息 */
|
|
427
291
|
getConfig() {
|
|
428
292
|
const maxWorkerId = (1 << Number(this.workerIdBitLength)) - 1;
|
|
429
293
|
const maxSequence = (1 << Number(this.seqBitLength)) - 1;
|
|
@@ -442,18 +306,8 @@ var GenidOptimized = class {
|
|
|
442
306
|
};
|
|
443
307
|
}
|
|
444
308
|
/**
|
|
445
|
-
* 验证 ID
|
|
446
|
-
*
|
|
447
|
-
* @param {number|bigint|string} id - 要验证的 ID
|
|
448
|
-
* @param {boolean} [strictWorkerId=false] - 是否严格验证 workerId 必须匹配当前实例
|
|
449
|
-
* @returns {boolean} ID 是否有效
|
|
450
|
-
*
|
|
451
|
-
* @example
|
|
452
|
-
* const genid = new GenidOptimized({ workerId: 1 });
|
|
453
|
-
* const id = genid.nextId();
|
|
454
|
-
* genid.isValid(id); // true
|
|
455
|
-
* genid.isValid(12345); // false
|
|
456
|
-
* genid.isValid(id, true); // true (workerId 匹配)
|
|
309
|
+
* 验证 ID 是否为当前配置下合法的 Snowflake ID
|
|
310
|
+
* @param strictWorkerId - 为 true 时要求 workerId 匹配当前实例
|
|
457
311
|
*/
|
|
458
312
|
isValid(id, strictWorkerId = false) {
|
|
459
313
|
try {
|
|
@@ -476,12 +330,7 @@ var GenidOptimized = class {
|
|
|
476
330
|
return false;
|
|
477
331
|
}
|
|
478
332
|
}
|
|
479
|
-
/**
|
|
480
|
-
* 将 ID 格式化为二进制字符串以便调试
|
|
481
|
-
*
|
|
482
|
-
* @param {number|bigint|string} id - 要格式化的 ID
|
|
483
|
-
* @returns {string} 格式化的二进制表示
|
|
484
|
-
*/
|
|
333
|
+
/** 将 ID 格式化为带标注的二进制字符串(调试用) */
|
|
485
334
|
formatBinary(id) {
|
|
486
335
|
const idBigInt = BigInt(id);
|
|
487
336
|
if (idBigInt < 0n) throw new Error("[GenidOptimized] ID 不能为负数");
|
|
@@ -499,6 +348,5 @@ var GenidOptimized = class {
|
|
|
499
348
|
].join("\n");
|
|
500
349
|
}
|
|
501
350
|
};
|
|
502
|
-
|
|
503
351
|
//#endregion
|
|
504
|
-
export { GenidOptimized };
|
|
352
|
+
export { GenidMethod, GenidOptimized };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdlab996/genid",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.3.0",
|
|
5
5
|
"description": "基于 Snowflake 算法的高性能分布式唯一 ID 生成器",
|
|
6
6
|
"author": "wudi <wuchendi96@gmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -47,11 +47,11 @@
|
|
|
47
47
|
"node": ">=20"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@biomejs/biome": "^2.
|
|
50
|
+
"@biomejs/biome": "^2.4.7",
|
|
51
51
|
"@types/node": "^25",
|
|
52
|
-
"tsdown": "^0.
|
|
52
|
+
"tsdown": "^0.21.4",
|
|
53
53
|
"typescript": "^5",
|
|
54
|
-
"vitest": "^4.0
|
|
54
|
+
"vitest": "^4.1.0"
|
|
55
55
|
},
|
|
56
56
|
"publishConfig": {
|
|
57
57
|
"access": "public",
|