thi-ng / umbrella

⛱ Broadly scoped ecosystem & mono-repository of 199 TypeScript projects (and ~180 examples) for general purpose, functional, data driven development
https://thi.ng
Apache License 2.0
3.35k stars 149 forks source link

[@thi.ng/ksuid] KSUID32 overflows during 2088 #403

Closed aelr closed 1 year ago

aelr commented 1 year ago

This code using KSUID32 fails:

idgen.fromEpoch(new Date("2089-01-01").getTime())

It throws at https://github.com/aelr/umbrella/blob/develop/packages/ksuid/src/aksuid.ts#L77:

assert(t >= 0, "configured base epoch must be in the past");

For this specific case, t = -2139591296

Also, should the error message be, "configured base epoch must not be in the past"?

postspectacular commented 1 year ago

Thanks & fixed! :) Also updated the readme to point out the new max date for the KSUID32 implementation. With the default offset, the max. supported date for KSUID32 is 2156-10-20T18:54:55Z. If you need even further ahead, you'll have to switch to one of the other impls (KSUID64 or ULID)

postspectacular commented 1 year ago

Btw. @aelr, the fix has been released yesterday a v3.1.15

aelr commented 1 year ago

Thank you!

postspectacular commented 1 year ago

Please let me know if that's working for you now. If you're using these IDs for a new project, you might also be able to adjust the time shift to an offset around now and so gain an additional 3 years since the initial version of this library... You can do that like so:

const idgen = defKSUID32({ epoch: new Date("2023-08-08").getTime() });
aelr commented 1 year ago

I actually shifted away from KSUID after checking the perf numbers. Instead I'm using @thi.ng/base-n to base62-encode Date.now() and appending a nanoid for the random bits. On my laptop, the ops/sec is 1.2 million/sec vs 90k/sec.

const encodeTimestamp = (ts) => BASE62.encode(ts).padStart(8, "0");
const nanoid = customAlphabet(B62_CHARS, 21);
const genId = (ts) => encodeTimestamp(ts) + nanoid();