Skip to content

Commit

Permalink
Migrate to fully synchronous generation (#11)
Browse files Browse the repository at this point in the history
* Allow for sync generation

* Revert to fully synchronous

Co-authored-by: Lucemans <[email protected]>
  • Loading branch information
Antony1060 and lucemans authored Jan 3, 2022
1 parent 2580036 commit b67dd46
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 77 deletions.
60 changes: 31 additions & 29 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,45 +20,47 @@ export type SunflakeConfig = {
epoch?: number;
};

export const generateSunflake = (config: SunflakeConfig) => async (time: number = Date.now()): Promise<string> => {
export const generateSunflake = (
config: SunflakeConfig
): ((time?: number) => {}) => {
let { machineID = 1, epoch = 1640988001000 } = config;

lastTime = time;
machineID = machineID % 1023;
return (time: number = Date.now()) => {
// Get the sequence number
if (lastTime == time) {
seq++;

const bTime = (time - epoch).toString(2);
if (seq > 4095) {
seq = 0;

// Get the sequence number
if (lastTime == time) {
seq++;

if (seq > 4095) {
seq = 0;

// Make system wait till time is been shifted by one millisecond
while (Date.now() <= time) {
await new Promise<void>((acc) => setImmediate(acc));
// Make system wait till time is been shifted by one millisecond
// eslint-disable-next-line no-empty
while (Date.now() <= time) {}
}
} else {
seq = 0;
}
} else {
seq = 0;
}

lastTime = time;
lastTime = time;

let bSeq = seq.toString(2);
let bMid = machineID.toString(2);
machineID = machineID % 1023;

// Create sequence binary bit
while (bSeq.length < 12) bSeq = '0' + bSeq;
while (bMid.length < 10) bMid = '0' + bMid;
const bTime = (time - epoch).toString(2);

const bid = bTime + bMid + bSeq;
let bSeq = seq.toString(2);
let bMid = machineID.toString(2);

let id = '';
for (let i = bid.length; i > 0; i -= 4) {
id = parseInt(bid.substring(i - 4, i), 2).toString(16) + id;
}
// Create sequence binary bit
while (bSeq.length < 12) bSeq = '0' + bSeq;
while (bMid.length < 10) bMid = '0' + bMid;

const bid = bTime + bMid + bSeq;

let id = '';
for (let i = bid.length; i > 0; i -= 4) {
id = parseInt(bid.substring(i - 4, i), 2).toString(16) + id;
}

return hexToDec(id);
return hexToDec(id);
};
};
98 changes: 50 additions & 48 deletions tests/sunflake.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,52 +8,54 @@ it('Exports Sunflake', () => {

const snowflake = generateSunflake({ machineID: 1, epoch: EPOCH });

it('Generates two snowflake value', async () => {
const flake1 = await snowflake();
const flake2 = await snowflake();

expect(flake1 != flake2);
});

it('Generates two snowflake value in sync', async () => {
const [flake1, flake2] = await Promise.all([
snowflake(),
snowflake()
]);

expect(flake1 != flake2);
});

it('Generates two snowflake value in sync with same time', async () => {
const time = Date.now();
const [flake1, flake2] = await Promise.all([
snowflake(time),
snowflake(time),
]);

expect(flake1 !== flake2);
});

it('Generates 500 snowflake value in sync with same time', async () => {
const time = Date.now();
const hugeList = [];
for (let i = 0; i <= 500; i++) {
hugeList.push(snowflake(time));
}

const list = await Promise.all(hugeList);

expect(new Set(list).size === list.length);
});

it('Generates 5200 snowflake value in sync with same time', async () => {
const time = Date.now();
const hugeList = [];
for (let i = 0; i <= 5200; i++) {
hugeList.push(snowflake(time));
}

const list = await Promise.all(hugeList);

expect(new Set(list).size === list.length);
describe('Promise', () => {
it('Generates two snowflake value', () => {
const flake1 = snowflake();
const flake2 = snowflake();

expect(flake1 != flake2);
});

it('Generates two snowflake value in sync', async () => {
const [flake1, flake2] = await Promise.all([
snowflake(),
snowflake()
]);

expect(flake1 != flake2);
});

it('Generates two snowflake value in sync with same time', async () => {
const time = Date.now();
const [flake1, flake2] = await Promise.all([
snowflake(time),
snowflake(time),
]);

expect(flake1 !== flake2);
});

it('Generates 500 snowflake value in sync with same time', async () => {
const time = Date.now();
const hugeList = [];
for (let i = 0; i <= 500; i++) {
hugeList.push(snowflake(time));
}

const list = await Promise.all(hugeList);

expect(new Set(list).size === list.length);
});

it('Generates 5200 snowflake value in sync with same time', async () => {
const time = Date.now();
const hugeList = [];
for (let i = 0; i <= 5200; i++) {
hugeList.push(snowflake(time));
}

const list = await Promise.all(hugeList);

expect(new Set(list).size === list.length);
});
});

0 comments on commit b67dd46

Please sign in to comment.