EdgeAIG's picture
download
raw
5.52 kB
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.