This commit is contained in:
Sebastian Korotkiewicz 2024-02-06 06:10:46 +01:00
parent 54b9ab6559
commit 6d78355cec
Signed by: skorotkiewicz
GPG key ID: 5BDC557B496BDB0D
3 changed files with 65 additions and 75 deletions

View file

@ -1,28 +1,23 @@
function decodeSnowflake(idStr) { function decodeSnowflake(idStr) {
const id = BigInt(idStr); const id = BigInt(idStr);
const binary = id.toString(2).padStart(64, '0');
const timestampShift = 22n; const timestampShift = 22n;
const machineIdShift = 12n; const machineIdShift = 12n;
const sequenceMask = 0xFFFn; // 12 bitów na sekwencję const sequenceMask = 0xfffn;
const timestamp = (id >> (timestampShift + machineIdShift)) & 0x1FFFFFFFFFFn; const timestamp = (id >> timestampShift) & 0x1ffffffffffn; // Adjusting the shift
const machineId = (id >> machineIdShift) & 0x3FFn; // 10 bitów na ID maszyny const machineId = (id >> machineIdShift) & 0x3ffn;
const sequence = id & sequenceMask; const sequence = id & sequenceMask;
// Upewnij się, że epoka jest taka sama, jak użyta do generowania Snowflake IDs const date = new Date(Number(timestamp)); // Converting BigInt to Number, then to Date
const epoch = BigInt(1288834974657); // Powinna być taka sama, jak w generatorze
const date = new Date(Number(epoch + (timestamp * 1000n)));
return { return {
timestamp: date, timestamp: date.toISOString(),
machineId: machineId.toString(), machineId: machineId.toString(),
sequence: sequence.toString(), sequence: sequence.toString(),
}; };
} }
// Użycie // Use
const idStr = '7160488856901390336'; // Przykładowy identyfikator Snowflake const idStr = "7160488856901390336";
const decoded = decodeSnowflake(idStr); const decoded = decodeSnowflake(idStr);
console.log(decoded); console.log(decoded);

View file

@ -1,20 +1,19 @@
class Snowflake { class Snowflake {
constructor(machineId) { constructor(machineId) {
if (machineId < 0 || machineId >= 1024) { if (machineId < 0 || machineId >= 1024) {
throw new Error('Machine ID must be in the range 0-1023.'); throw new Error("Machine ID must be in the range 0-1023.");
} }
this.machineId = BigInt(machineId); this.machineId = BigInt(machineId);
this.sequence = BigInt(0); this.sequence = BigInt(0);
this.lastTimestamp = BigInt(-1); this.lastTimestamp = BigInt(-1);
// Konfiguracja bitów: 41 bitów na czas, 10 bitów na ID maszyny, 12 bitów na sekwencję
this.timestampShift = 22n; this.timestampShift = 22n;
this.machineIdShift = 12n; this.machineIdShift = 12n;
this.sequenceMask = 0xFFFn; // 4095 w dziesiętnym, BigInt this.sequenceMask = 0xfffn;
} }
generate() { async generate() {
let timestamp = BigInt(Date.now()); let timestamp = BigInt(Date.now());
if (timestamp === this.lastTimestamp) { if (timestamp === this.lastTimestamp) {
@ -22,6 +21,7 @@ class Snowflake {
if (this.sequence === 0n) { if (this.sequence === 0n) {
while (timestamp <= this.lastTimestamp) { while (timestamp <= this.lastTimestamp) {
await new Promise((resolve) => setTimeout(resolve, 1));
timestamp = BigInt(Date.now()); timestamp = BigInt(Date.now());
} }
} }
@ -31,16 +31,16 @@ class Snowflake {
this.lastTimestamp = timestamp; this.lastTimestamp = timestamp;
const id = ((timestamp & 0x1FFFFFFFFFFn) << this.timestampShift) | const id =
((timestamp & 0x1ffffffffffn) << this.timestampShift) |
(this.machineId << this.machineIdShift) | (this.machineId << this.machineIdShift) |
this.sequence; this.sequence;
return id.toString(); // Zwraca string, ponieważ BigInt może być zbyt duży dla niektórych zastosowań return id.toString();
} }
} }
// Użycie const machineId = 1; // machine ID (0-1023)
const machineId = 1; // ID maszyny (0-1023)
const snowflake = new Snowflake(machineId); const snowflake = new Snowflake(machineId);
const id1 = snowflake.generate(); const id1 = snowflake.generate();

View file

@ -1,30 +1,28 @@
class Snowflake { class Snowflake {
constructor(machineId, epoch) { constructor(machineId) {
if (machineId < 0 || machineId >= 1024) { if (machineId < 0 || machineId >= 1024) {
throw new Error("Machine ID must be in the range 0-1023."); throw new Error("Machine ID must be in the range 0-1023.");
} }
this.epoch = BigInt(epoch); // Ustawienie epoki
this.machineId = BigInt(machineId); this.machineId = BigInt(machineId);
this.sequence = BigInt(0); this.sequence = BigInt(0);
this.lastTimestamp = BigInt(-1); this.lastTimestamp = BigInt(-1);
// Konfiguracja bitów: 41 bitów na czas, 10 bitów na ID maszyny, 12 bitów na sekwencję
this.timestampShift = 22n; this.timestampShift = 22n;
this.machineIdShift = 12n; this.machineIdShift = 12n;
this.sequenceMask = 0xfffn; // 4095 w dziesiętnym, BigInt this.sequenceMask = 0xfffn;
} }
async generate() { async generate() {
let timestamp = BigInt(Date.now()) - this.epoch; // Odejmowanie epoki let timestamp = BigInt(Date.now());
if (timestamp === this.lastTimestamp) { if (timestamp === this.lastTimestamp) {
this.sequence = (this.sequence + 1n) & this.sequenceMask; this.sequence = (this.sequence + 1n) & this.sequenceMask;
if (this.sequence === 0n) { if (this.sequence === 0n) {
while (timestamp <= this.lastTimestamp) { while (timestamp <= this.lastTimestamp) {
await new Promise((resolve) => setTimeout(resolve, 1)); // Opóźnienie 1 ms await new Promise((resolve) => setTimeout(resolve, 1));
timestamp = BigInt(Date.now()) - this.epoch; timestamp = BigInt(Date.now());
} }
} }
} else { } else {
@ -38,40 +36,37 @@ class Snowflake {
(this.machineId << this.machineIdShift) | (this.machineId << this.machineIdShift) |
this.sequence; this.sequence;
return id.toString(); // Zwraca string, ponieważ BigInt może być zbyt duży dla niektórych zastosowań return id.toString();
} }
} }
function decodeSnowflake(idStr, epoch) { function decodeSnowflake(idStr) {
const id = BigInt(idStr); const id = BigInt(idStr);
const timestampShift = 22n; const timestampShift = 22n;
const machineIdShift = 12n; const machineIdShift = 12n;
const sequenceMask = 0xfffn; // 12 bitów na sekwencję const sequenceMask = 0xfffn;
const timestamp = (id >> (timestampShift + machineIdShift)) & 0x1ffffffffffn; const timestamp = (id >> timestampShift) & 0x1ffffffffffn; // Adjusting the shift
const machineId = (id >> machineIdShift) & 0x3ffn; // 10 bitów na ID maszyny const machineId = (id >> machineIdShift) & 0x3ffn;
const sequence = id & sequenceMask; const sequence = id & sequenceMask;
const epochBigInt = BigInt(epoch); // Upewnij się, że epoka jest BigInt const date = new Date(Number(timestamp)); // Converting BigInt to Number, then to Date
const date = new Date(Number(epochBigInt + timestamp * 1000n)); // Dodaj epokę do czasu
return { return {
timestamp: date, timestamp: date.toISOString(),
machineId: machineId.toString(), machineId: machineId.toString(),
sequence: sequence.toString(), sequence: sequence.toString(),
}; };
} }
// Użycie // Use
(async () => { (async () => {
const machineId = 1; // ID maszyny (0-1023) const machineId = 1; // machine ID (0-1023)
const epoch = 1288834974657; // Ustawienie epoki const snowflake = new Snowflake(machineId);
const snowflake = new Snowflake(machineId, epoch);
const id1 = await snowflake.generate(); const id1 = await snowflake.generate();
console.log("encodeID", id1); console.log("encodeID", id1);
const idStr = id1; // Przykładowy identyfikator Snowflake const decoded = decodeSnowflake(id1);
const decoded = decodeSnowflake(idStr, epoch);
console.log("decodeID", decoded); console.log("decodeID", decoded);
})(); })();