| import { Clock } from "../../Clock.js"; | |
| import * as Context from "../../Context.js"; | |
| import * as DateTime from "../../DateTime.js"; | |
| import * as Effect from "../../Effect.js"; | |
| import { identity } from "../../Function.js"; | |
| import * as Layer from "../../Layer.js"; | |
| import * as Schema from "../../Schema.js"; | |
| import * as SchemaTransformation from "../../SchemaTransformation.js"; | |
| /** | |
| * Runtime brand identifier for cluster snowflake ids. | |
| * | |
| * @category type IDs | |
| * @since 4.0.0 | |
| */ | |
| export const TypeId = "~effect/cluster/Snowflake"; | |
| /** | |
| * Constructs a branded cluster snowflake id from a bigint or bigint-compatible | |
| * string. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const Snowflake = input => typeof input === "string" ? BigInt(input) : input; | |
| /** | |
| * Schema for snowflake ids represented as branded bigints. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const SnowflakeFromBigInt = /*#__PURE__*/Schema.BigInt.pipe(/*#__PURE__*/Schema.brand(TypeId)); | |
| /** | |
| * Schema that decodes snowflake ids from strings into branded bigints and encodes | |
| * them back to strings. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const SnowflakeFromString = /*#__PURE__*/Schema.String.pipe(/*#__PURE__*/Schema.decodeTo(SnowflakeFromBigInt, SchemaTransformation.bigintFromString)); | |
| /** | |
| * Defines the custom snowflake epoch in Unix milliseconds. | |
| * | |
| * @category constants | |
| * @since 4.0.0 | |
| */ | |
| export const constEpochMillis = /*#__PURE__*/Date.UTC(2025, 0, 1); | |
| const sinceUnixEpoch = constEpochMillis - /*#__PURE__*/Date.UTC(1970, 0, 1); | |
| const constBigInt12 = /*#__PURE__*/BigInt(12); | |
| const constBigInt22 = /*#__PURE__*/BigInt(22); | |
| const constBigInt1024 = /*#__PURE__*/BigInt(1024); | |
| const constBigInt4096 = /*#__PURE__*/BigInt(4096); | |
| /** | |
| * Creates a branded snowflake id from a timestamp, machine id, and sequence number, | |
| * using the custom snowflake epoch and 10-bit machine id and 12-bit sequence | |
| * fields. | |
| * | |
| * **When to use** | |
| * | |
| * Use to pack known timestamp, machine id, and sequence parts into a branded | |
| * snowflake id. | |
| * | |
| * **Gotchas** | |
| * | |
| * Machine id values are encoded modulo 1024, and sequence values modulo 4096; | |
| * values outside those ranges wrap instead of being rejected. | |
| * | |
| * @see {@link toParts} for the inverse operation that decodes a snowflake id into timestamp, machine id, and sequence parts | |
| * @see {@link makeGenerator} for generating ids with Clock-backed timestamp and sequence management | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const make = options => BigInt(options.timestamp - constEpochMillis) << constBigInt22 | BigInt(options.machineId % 1024) << constBigInt12 | BigInt(options.sequence % 4096); | |
| /** | |
| * Extracts the Unix timestamp in milliseconds from a snowflake id. | |
| * | |
| * @category parts | |
| * @since 4.0.0 | |
| */ | |
| export const timestamp = snowflake => Number(snowflake >> constBigInt22) + sinceUnixEpoch; | |
| /** | |
| * Extracts the timestamp from a snowflake id as a `DateTime.Utc`. | |
| * | |
| * @category parts | |
| * @since 4.0.0 | |
| */ | |
| export const dateTime = snowflake => DateTime.makeUnsafe(timestamp(snowflake)); | |
| /** | |
| * Extracts the machine id component from a snowflake id. | |
| * | |
| * @category parts | |
| * @since 4.0.0 | |
| */ | |
| export const machineId = snowflake => Number((snowflake >> constBigInt12) % constBigInt1024); | |
| /** | |
| * Extracts the per-machine sequence component from a snowflake id. | |
| * | |
| * @category parts | |
| * @since 4.0.0 | |
| */ | |
| export const sequence = snowflake => Number(snowflake % constBigInt4096); | |
| /** | |
| * Decomposes a snowflake id into its timestamp, machine id, and sequence parts. | |
| * | |
| * @category parts | |
| * @since 4.0.0 | |
| */ | |
| export const toParts = snowflake => ({ | |
| timestamp: timestamp(snowflake), | |
| machineId: machineId(snowflake), | |
| sequence: sequence(snowflake) | |
| }); | |
| /** | |
| * Creates a stateful snowflake generator using `Clock`. | |
| * | |
| * **Details** | |
| * | |
| * The generator starts with a random machine id, never moves generated timestamps | |
| * backward, resets the sequence each millisecond, and advances the timestamp when | |
| * more than 4096 ids are requested in the same millisecond. | |
| * | |
| * @category Generator | |
| * @since 4.0.0 | |
| */ | |
| export const makeGenerator = /*#__PURE__*/Effect.gen(function* () { | |
| let machineId = Math.floor(Math.random() * 1024); | |
| const clock = yield* Clock; | |
| let sequence = 0; | |
| let sequenceAt = Math.floor(clock.currentTimeMillisUnsafe()); | |
| return identity({ | |
| setMachineId: newMachineId => Effect.sync(() => { | |
| machineId = newMachineId; | |
| }), | |
| nextUnsafe() { | |
| let now = Math.floor(clock.currentTimeMillisUnsafe()); | |
| // account for clock drift, only allow time to move forward | |
| if (now < sequenceAt) { | |
| now = sequenceAt; | |
| } else if (now > sequenceAt) { | |
| // reset sequence if we're in a new millisecond | |
| sequence = 0; | |
| sequenceAt = now; | |
| } else if (sequence >= 4096) { | |
| // if we've hit the max sequence for this millisecond, go to the next | |
| // millisecond | |
| sequenceAt++; | |
| sequence = 0; | |
| } | |
| return make({ | |
| machineId, | |
| sequence: sequence++, | |
| timestamp: sequenceAt | |
| }); | |
| } | |
| }); | |
| }); | |
| /** | |
| * Context service for a stateful snowflake id generator. | |
| * | |
| * @category Generator | |
| * @since 4.0.0 | |
| */ | |
| export class Generator extends /*#__PURE__*/Context.Service()("effect/cluster/Snowflake/Generator") {} | |
| /** | |
| * Layer that provides the default snowflake `Generator` service. | |
| * | |
| * @category Generator | |
| * @since 4.0.0 | |
| */ | |
| export const layerGenerator = /*#__PURE__*/Layer.effect(Generator)(makeGenerator); | |
| //# sourceMappingURL=Snowflake.js.map |
Xet Storage Details
- Size:
- 5.52 kB
- Xet hash:
- cd9d1246ea7e953eb56ccabed91b598dc823477a1d284315ab2d838200b6cffc
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.