EdgeAIG's picture
download
raw
12.6 kB
/**
* Coordinates rate limits through shared persistent storage.
*
* The `RateLimiter` service consumes tokens for string keys using fixed-window
* counters or token-bucket state. It can protect external APIs, enforce quotas,
* or throttle workers across fibers and processes that share the same store.
* This module includes helpers that fail when a limit is exceeded, return the
* delay needed before continuing, or wrap an effect so it waits automatically.
* It also defines the store service and in-memory or Redis-backed store layers.
*
* @since 4.0.0
*/
import * as Config from "../../Config.ts";
import * as Context from "../../Context.ts";
import * as Duration from "../../Duration.ts";
import * as Effect from "../../Effect.ts";
import * as Layer from "../../Layer.ts";
import * as Schema from "../../Schema.ts";
import * as Redis from "./Redis.ts";
/**
* Runtime type identifier for `RateLimiter` values.
*
* @category type IDs
* @since 4.0.0
*/
export declare const TypeId: TypeId;
/**
* Type-level identifier used to brand `RateLimiter` values.
*
* @category type IDs
* @since 4.0.0
*/
export type TypeId = "~effect/persistence/RateLimiter";
/**
* Service for consuming rate-limit tokens for a key using fixed-window or
* token-bucket algorithms.
*
* @category models
* @since 4.0.0
*/
export interface RateLimiter {
readonly [TypeId]: TypeId;
readonly consume: (options: {
readonly algorithm?: "fixed-window" | "token-bucket" | undefined;
readonly onExceeded?: "delay" | "fail" | undefined;
readonly window: Duration.Input;
readonly limit: number;
readonly key: string;
readonly tokens?: number | undefined;
}) => Effect.Effect<ConsumeResult, RateLimiterError>;
}
/**
* Service tag for persistent token-consumption services.
*
* **When to use**
*
* Use to access or provide rate-limit checks backed by fixed-window counters or
* token-bucket state.
*
* @category services
* @since 4.0.0
*/
export declare const RateLimiter: Context.Service<RateLimiter, RateLimiter>;
/**
* Creates a `RateLimiter` from the current `RateLimiterStore`.
*
* **Details**
*
* The limiter supports fixed-window and token-bucket algorithms and either
* fails or returns a delay when a limit is exceeded.
*
* @category constructors
* @since 4.0.0
*/
export declare const make: Effect.Effect<RateLimiter, never, RateLimiterStore>;
/**
* Provides `RateLimiter` using the current `RateLimiterStore`.
*
* @category layers
* @since 4.0.0
*/
export declare const layer: Layer.Layer<RateLimiter, never, RateLimiterStore>;
/**
* Accesses a function that applies rate limiting to an effect.
*
* **Example** (Applying rate limits to effects)
*
* ```ts
* import { Effect } from "effect"
* import { RateLimiter } from "effect/unstable/persistence"
*
* Effect.gen(function*() {
* // Access the `withLimiter` function from the RateLimiter module
* const withLimiter = yield* RateLimiter.makeWithRateLimiter
*
* // Apply a rate limiter to an effect
* yield* Effect.log("Making a request with rate limiting").pipe(
* withLimiter({
* key: "some-key",
* limit: 10,
* onExceeded: "delay",
* window: "5 seconds",
* algorithm: "fixed-window"
* })
* )
* })
* ```
*
* @category accessors
* @since 4.0.0
*/
export declare const makeWithRateLimiter: Effect.Effect<((options: {
readonly algorithm?: "fixed-window" | "token-bucket" | undefined;
readonly onExceeded?: "delay" | "fail" | undefined;
readonly window: Duration.Input;
readonly limit: number;
readonly key: string;
readonly tokens?: number | undefined;
}) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E | RateLimiterError, R>), never, RateLimiter>;
/**
* Accesses a function that sleeps when the rate limit is exceeded.
*
* **Example** (Sleeping until rate limit permits)
*
* ```ts
* import { Effect } from "effect"
* import { RateLimiter } from "effect/unstable/persistence"
*
* Effect.gen(function*() {
* // Access the `sleep` function from the RateLimiter module
* const sleep = yield* RateLimiter.makeSleep
*
* // Use the `sleep` function with specific rate limiting parameters.
* // This will only sleep if the rate limit has been exceeded.
* yield* sleep({
* key: "some-key",
* limit: 10,
* window: "5 seconds",
* algorithm: "fixed-window"
* })
* })
* ```
*
* @category accessors
* @since 4.0.0
*/
export declare const makeSleep: Effect.Effect<((options: {
readonly algorithm?: "fixed-window" | "token-bucket" | undefined;
readonly window: Duration.Input;
readonly limit: number;
readonly key: string;
readonly tokens?: number | undefined;
}) => Effect.Effect<ConsumeResult, RateLimiterError>), never, RateLimiter>;
/**
* Runtime type identifier for `RateLimiterError`.
*
* @category type IDs
* @since 4.0.0
*/
export declare const ErrorTypeId: ErrorTypeId;
/**
* Type-level identifier used to brand `RateLimiterError` values.
*
* @category type IDs
* @since 4.0.0
*/
export type ErrorTypeId = "~@effect/experimental/RateLimiter/RateLimiterError";
declare const RateLimitExceeded_base: Schema.Class<RateLimitExceeded, Schema.Struct<{
readonly _tag: Schema.tag<"RateLimitExceeded">;
readonly retryAfter: Schema.DurationFromMillis;
readonly key: Schema.String;
readonly limit: Schema.Number;
readonly remaining: Schema.Number;
}>, import("../../Cause.ts").YieldableError>;
/**
* Error reason for a rate-limit check that exceeded the configured limit.
*
* **Details**
*
* Includes the affected key, limit, remaining token count, and retry delay.
*
* @category errors
* @since 4.0.0
*/
export declare class RateLimitExceeded extends RateLimitExceeded_base {
/**
* Public message used when the rate limiter rejects a request.
*
* @since 4.0.0
*/
get message(): string;
}
declare const RateLimitStoreError_base: Schema.Class<RateLimitStoreError, Schema.Struct<{
readonly _tag: Schema.tag<"RateLimitStoreError">;
readonly message: Schema.String;
readonly cause: Schema.optional<Schema.Defect>;
}>, import("../../Cause.ts").YieldableError>;
/**
* Error reason for failures in the backing `RateLimiterStore`.
*
* @category errors
* @since 4.0.0
*/
export declare class RateLimitStoreError extends RateLimitStoreError_base {
}
/**
* Union of reasons carried by `RateLimiterError`.
*
* @category errors
* @since 4.0.0
*/
export type RateLimiterErrorReason = RateLimitExceeded | RateLimitStoreError;
/**
* Schema for all reasons that can be carried by `RateLimiterError`.
*
* @category errors
* @since 4.0.0
*/
export declare const RateLimiterErrorReason: Schema.Union<[
typeof RateLimitExceeded,
typeof RateLimitStoreError
]>;
declare const RateLimiterError_base: Schema.Class<RateLimiterError, Schema.Struct<{
readonly _tag: Schema.tag<"RateLimiterError">;
readonly reason: Schema.Union<[typeof RateLimitExceeded, typeof RateLimitStoreError]>;
}>, import("../../Cause.ts").YieldableError>;
/**
* Error raised by rate limiter operations, wrapping a concrete failure
* `reason`.
*
* @category errors
* @since 4.0.0
*/
export declare class RateLimiterError extends RateLimiterError_base {
constructor(props: {
readonly reason: RateLimiterErrorReason;
});
/**
* Marks this value as a rate limiter error for runtime guards.
*
* @since 4.0.0
*/
readonly [ErrorTypeId]: ErrorTypeId;
get message(): string;
}
/**
* Metadata returned after consuming tokens from a rate limiter.
*
* @category models
* @since 4.0.0
*/
export interface ConsumeResult {
/**
* The amount of delay to wait before making the next request, when the rate
* limiter is using the "delay" `onExceeded` strategy. It will be
* Duration.zero if the request is allowed immediately.
*/
readonly delay: Duration.Duration;
/**
* The maximum number of requests allowed in the current window.
*/
readonly limit: number;
/**
* The number of remaining requests in the current window.
*/
readonly remaining: number;
/**
* The time until the rate limit fully resets.
*/
readonly resetAfter: Duration.Duration;
}
declare const RateLimiterStore_base: Context.ServiceClass<RateLimiterStore, "effect/persistence/RateLimiter/RateLimiterStore", {
/**
* Returns the token count *after* taking the specified `tokens` and time to
* live for the `key`.
*
* If `limit` is provided, the number of taken tokens will be capped at the
* limit.
*
* In the case the limit is exceeded, the returned count will be greater
* than the limit, but the TTL will not be updated.
*/
readonly fixedWindow: (options: {
readonly key: string;
readonly tokens: number;
readonly refillRate: Duration.Duration;
readonly limit: number | undefined;
}) => Effect.Effect<readonly [count: number, ttl: number], RateLimiterError>;
/**
* Returns the current remaining tokens for the `key` after consuming the
* specified amount of tokens.
*
* If `allowOverflow` is true, the number of tokens can drop below zero.
*
* In the case of no overflow, the returned token count will only be
* negative if the requested tokens exceed the available tokens, but the
* real token count will not be persisted below zero.
*/
readonly tokenBucket: (options: {
readonly key: string;
readonly tokens: number;
readonly limit: number;
readonly refillRate: Duration.Duration;
readonly allowOverflow: boolean;
}) => Effect.Effect<number, RateLimiterError>;
}>;
/**
* Defines the low-level backing store for fixed-window counters and token-bucket state.
*
* **When to use**
*
* Use to provide the shared counter storage used by persistent rate-limit
* checks.
*
* @category store
* @since 4.0.0
*/
export declare class RateLimiterStore extends RateLimiterStore_base {
}
/**
* Provides a process-local in-memory `RateLimiterStore`.
*
* @category RateLimiterStore
* @since 4.0.0
*/
export declare const layerStoreMemory: Layer.Layer<RateLimiterStore>;
/**
* Creates a Redis-backed `RateLimiterStore` using Lua scripts and the
* configured key prefix.
*
* @category RateLimiterStore
* @since 4.0.0
*/
export declare const makeStoreRedis: (options?: {
readonly prefix?: string | undefined;
} | undefined) => Effect.Effect<{
/**
* Returns the token count *after* taking the specified `tokens` and time to
* live for the `key`.
*
* If `limit` is provided, the number of taken tokens will be capped at the
* limit.
*
* In the case the limit is exceeded, the returned count will be greater
* than the limit, but the TTL will not be updated.
*/
readonly fixedWindow: (options: {
readonly key: string;
readonly tokens: number;
readonly refillRate: Duration.Duration;
readonly limit: number | undefined;
}) => Effect.Effect<readonly [count: number, ttl: number], RateLimiterError>;
/**
* Returns the current remaining tokens for the `key` after consuming the
* specified amount of tokens.
*
* If `allowOverflow` is true, the number of tokens can drop below zero.
*
* In the case of no overflow, the returned token count will only be
* negative if the requested tokens exceed the available tokens, but the
* real token count will not be persisted below zero.
*/
readonly tokenBucket: (options: {
readonly key: string;
readonly tokens: number;
readonly limit: number;
readonly refillRate: Duration.Duration;
readonly allowOverflow: boolean;
}) => Effect.Effect<number, RateLimiterError>;
}, never, Redis.Redis>;
/**
* Provides a Redis-backed `RateLimiterStore` using `makeStoreRedis`.
*
* @category layers
* @since 4.0.0
*/
export declare const layerStoreRedis: (options?: {
readonly prefix?: string | undefined;
}) => Layer.Layer<RateLimiterStore, never, Redis.Redis>;
/**
* Provides a Redis-backed `RateLimiterStore` from wrapped configuration
* options.
*
* @category layers
* @since 4.0.0
*/
export declare const layerStoreRedisConfig: (options: Config.Wrap<{
readonly prefix?: string | undefined;
}>) => Layer.Layer<RateLimiterStore, Config.ConfigError, Redis.Redis>;
export {};
//# sourceMappingURL=RateLimiter.d.ts.map

Xet Storage Details

Size:
12.6 kB
·
Xet hash:
32876b2c4696be2b16de28390ec5f8098542f01b15226750f5086a0cbb4b5cca

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.