UNPKG

jittered-fractional-indexing

Version:

Provides functions for generating ordering strings with random jitter to minimize the likelihood of collisions

79 lines (76 loc) 3.97 kB
/** * Generates a fractional index key between two keys, with `jitterBits` for * collision avoidance. * * The implementation works by binary splitting the key range until the desired * number of bits of jitter is reached. For instance, for one bit of jitter, we * first generate a key between the original lower and upper bounds, then with * 50% probability each, we either generate a key between the original lower * bound and the midpoint, or a key between the midpoint and the original upper * bound. At this point, we have one bit of jitter, so we return this key. * * Runs in O(`jitterBits`) time with respect to the underlying * `fractional-indexing` implementation (specifically, for `b` bits of jitter, * we call the underlying, unjittered implementation of `generateKeyBetween` * `b + 1` times). * * @param a - Lower bound of the key range. * @param b - Upper bound of the key range. * @param opts - Optional configuration. * @param opts.digits - The digits to use for the key. Defaults to * `fractional-indexing`'s default. * @param opts.jitterBits - The number of bits of jitter. Defaults to 30. * Birthday bounds can be used to estimate the probability of collision * given a specific number of keys and bits of jitter, i.e., with * `k` keys and `b` bits of jitter, the probability of collision is * `1 - (2^b)!/((2^b - k)!(2^b)^k)`. When `b = 30` and `k = 10_000`, we get * a ~4.5% chance of collision. Note that this probability is specific to `a` * and `b`, i.e., it is when 10,000 keys are generated at the same time for * the same `a` and `b`; it is not a general probability of collision for all * key ranges. * @param opts.getRandomBit - A function to generate a random bit. Defaults to * `Math.random() < 0.5`. For cryptographic randomness, use * `crypto.getRandomValues()` (browser) or `node:crypto`. The custom * `getRandomBit` function must return a uniformly-distributed (i.e., 50% * chance of a `true` or `false` result) boolean for an unbiased key. * @returns A new, jittered fractional index key between `a` and `b`. */ export declare function generateKeyBetween(a: string | null | undefined, b: string | null | undefined, opts?: { digits?: string; jitterBits?: number; getRandomBit?: () => boolean; }): string; /** * Generates `n` fractional index keys between two keys, with `jitterBits` for * collision avoidance. * * The implementation works by generating `n + 1` keys between `a` and `b` * using the underlying `fractional-indexing` implementation, then generating a * jittered key in each space using the jittered `generateKeyBetween` * implementation. When `jitterBits` is 0, the function falls back on the * underlying, unjittered implementation of `generateNKeysBetween` from * `fractional-indexing`. * * Runs in approximately O(`n * jitterBits`) time with respect to the unjittered * `fractional-indexing` implementation of `generateKeyBetween` (specifically, * for each of the `n` keys to generate, we call the unjittered implementation * of `generateKeyBetween` `b + 1` times where `b` is the number of bits of * jitter). * * @param a - Lower bound of the key range. * @param b - Upper bound of the key range. * @param opts - Optional configuration. * @param opts.digits - The digits to use for the key, passed to * `generateKeyBetween`. * @param opts.jitterBits - The number of bits of jitter *per key*, passed to * `generateKeyBetween`. * @param opts.getRandomBit - A function to generate a random bit, passed to * `generateKeyBetween`. * @returns `n` new, jittered fractional index keys between `a` and `b`. */ export declare function generateNKeysBetween(a: string | null | undefined, b: string | null | undefined, n: number, opts?: { digits?: string; jitterBits?: number; getRandomBit?: () => boolean; }): string[]; export { }