63 lines
2.1 KiB
JavaScript
63 lines
2.1 KiB
JavaScript
function Snowflake(_workerId, _dataCenterId, _sequence) {
|
|
this.twepoch = 1288834974657n;
|
|
this.workerIdBits = 5n;
|
|
this.dataCenterIdBits = 5n;
|
|
this.maxWrokerId = -1n ^ (-1n << this.workerIdBits);
|
|
this.maxDataCenterId = -1n ^ (-1n << this.dataCenterIdBits);
|
|
this.sequenceBits = 12n;
|
|
this.workerIdShift = this.sequenceBits;
|
|
this.dataCenterIdShift = this.sequenceBits + this.workerIdBits;
|
|
this.timestampLeftShift = this.sequenceBits + this.workerIdBits + this.dataCenterIdBits;
|
|
this.sequenceMask = -1n ^ (-1n << this.sequenceBits);
|
|
this.lastTimestamp = -1n;
|
|
this.workerId = 1n;
|
|
this.dataCenterId = 1n;
|
|
this.sequence = 0n;
|
|
if (this.workerId > this.maxWrokerId || this.workerId < 0) {
|
|
throw new Error('_workerId must max than 0 and small than maxWrokerId-[' + this.maxWrokerId + ']');
|
|
}
|
|
if (this.dataCenterId > this.maxDataCenterId || this.dataCenterId < 0) {
|
|
throw new Error('_dataCenterId must max than 0 and small than maxDataCenterId-[' + this.maxDataCenterId + ']');
|
|
}
|
|
|
|
this.workerId = BigInt(_workerId);
|
|
this.dataCenterId = BigInt(_dataCenterId);
|
|
this.sequence = BigInt(_sequence);
|
|
}
|
|
|
|
Snowflake.prototype.tilNextMillis = function (lastTimestamp) {
|
|
let timestamp = this.timeGen();
|
|
while (timestamp <= lastTimestamp) {
|
|
timestamp = this.timeGen();
|
|
}
|
|
return BigInt(timestamp);
|
|
};
|
|
Snowflake.prototype.timeGen = function () {
|
|
return BigInt(Date.now());
|
|
};
|
|
Snowflake.prototype.nextId = function () {
|
|
let timestamp = this.timeGen();
|
|
if (timestamp < this.lastTimestamp) {
|
|
throw new Error('Clock moved backwards. Refusing to generate id for ' +
|
|
(this.lastTimestamp - timestamp));
|
|
}
|
|
if (this.lastTimestamp === timestamp) {
|
|
this.sequence = (this.sequence + 1n) & this.sequenceMask;
|
|
if (this.sequence === 0n) {
|
|
timestamp = this.tilNextMillis(this.lastTimestamp);
|
|
}
|
|
} else {
|
|
this.sequence = 0n;
|
|
}
|
|
this.lastTimestamp = timestamp;
|
|
return ((timestamp - this.twepoch) << this.timestampLeftShift) |
|
|
(this.dataCenterId << this.dataCenterIdShift) |
|
|
(this.workerId << this.workerIdShift) |
|
|
this.sequence;
|
|
};
|
|
|
|
let snowflake = new Snowflake(1n, 1n, 0n);
|
|
|
|
snowflake.nextId()
|
|
|