not so initial commit
This commit is contained in:
68
snowflake.ts
Normal file
68
snowflake.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
export class SnowflakeGenerator {
|
||||
private epoch: bigint;
|
||||
private workerId: bigint;
|
||||
private processId: bigint;
|
||||
private sequence: bigint;
|
||||
private lastTimestamp: bigint;
|
||||
|
||||
constructor(workerId: bigint = 1n, processId: bigint = 1n, epoch: bigint = 1766617200000n) {
|
||||
// dec 1 2025 (creation of this)
|
||||
this.epoch = epoch;
|
||||
this.workerId = workerId;
|
||||
this.processId = processId;
|
||||
this.sequence = 0n;
|
||||
this.lastTimestamp = -1n;
|
||||
}
|
||||
|
||||
private getCurrentTimestamp(): bigint {
|
||||
return BigInt(Date.now());
|
||||
}
|
||||
|
||||
private waitForNextMillisecond(lastTimestamp: bigint): bigint {
|
||||
let timestamp = this.getCurrentTimestamp();
|
||||
while (timestamp <= lastTimestamp) {
|
||||
timestamp = this.getCurrentTimestamp();
|
||||
}
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public generateSnowflake(): number {
|
||||
const timestamp = this.getCurrentTimestamp() - this.epoch;
|
||||
|
||||
if (timestamp === this.lastTimestamp) {
|
||||
this.sequence += 1n;
|
||||
if (this.sequence > 4095n) { // max sequence value (12 bits)
|
||||
// Wait for the next millisecond if we've reached the max sequence value
|
||||
const newTimestamp = this.waitForNextMillisecond(this.lastTimestamp);
|
||||
this.sequence = 0n;
|
||||
return Number.parseInt(String(this.createSnowflake(newTimestamp)));
|
||||
}
|
||||
} else {
|
||||
this.sequence = 0n;
|
||||
}
|
||||
|
||||
this.lastTimestamp = timestamp;
|
||||
return Number.parseInt(String(this.createSnowflake(timestamp)));
|
||||
}
|
||||
|
||||
private createSnowflake(timestamp: bigint): bigint {
|
||||
return (timestamp << 22n) | (BigInt(this.workerId) << 18n) | (BigInt(this.processId) << 12n) | BigInt(this.sequence);
|
||||
}
|
||||
|
||||
public decodeSnowflake(id: bigint | number) {
|
||||
const snowflake = BigInt(id);
|
||||
|
||||
const sequence = snowflake & (1n << 6n) - 1n;
|
||||
const processId = (snowflake >> 6n) & ((1n << 6n) - 1n);
|
||||
const workerId = (snowflake >> 12n) & ((1n << 10n) - 1n);
|
||||
const timestamp = (snowflake >> 22n) + this.epoch;
|
||||
|
||||
return {
|
||||
timestamp, // bigint (ms since Unix epoch)
|
||||
date: new Date(Number(timestamp)),
|
||||
workerId,
|
||||
processId,
|
||||
sequence,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user