import * as Duration from "./Duration.ts"; import * as Effect from "./Effect.ts"; import type * as Exit from "./Exit.ts"; import { type Pipeable } from "./Pipeable.ts"; import * as Scope from "./Scope.ts"; import * as Semaphore from "./Semaphore.ts"; declare const TypeId = "~effect/Pool"; /** * A `Pool` is a pool of items of type `A`, each of which may be * associated with the acquisition and release of resources. An attempt to get * an item `A` from a pool may fail with an error of type `E`. * * **When to use** * * Use when you need to share a bounded set of scoped resources across fibers * while the pool manages acquisition, reuse, and release. * * @see {@link make} for creating a pool with size bounds * @see {@link makeWithTTL} for creating a pool with idle item expiration * @see {@link makeWithStrategy} for creating a pool with a custom strategy * @see {@link get} for acquiring an item from a pool * @see {@link invalidate} for removing a broken item from the pool * * @stability stable * @category models * @since 2.0.0 */ export interface Pool extends Pipeable { readonly [TypeId]: typeof TypeId; readonly config: Config; readonly state: State; } /** * Normalized configuration used by a `Pool`. * * **When to use** * * Use as the normalized, read-only description of how a pool acquires, sizes, * shares, and resizes its items after construction. * * **Details** * * The config stores the acquire effect, size bounds, per-item concurrency, * target utilization, and resizing strategy used by the pool implementation. * * @see {@link Pool} for the value exposing this configuration * @see {@link State} for mutable runtime state instead of static configuration * @see {@link Strategy} for the resizing and reclamation contract stored on the config * * @stability stable * @category models * @since 4.0.0 */ export interface Config { readonly acquire: Effect.Effect; readonly concurrency: number; readonly isFixed: boolean; readonly minSize: number; readonly maxSize: number; readonly strategy: Strategy; readonly targetUtilization: number; } /** * Mutable runtime state maintained by a `Pool`. * * **When to use** * * Use when you need to inspect or support the runtime state backing a `Pool`, * including its scope, item sets, semaphores, waiters, invalidation tracking, * and shutdown flag. * * **Details** * * This state is exposed for inspection and implementation support. User code * should prefer the high-level pool operations. * * @see {@link Pool} for the pool value exposing this state * @see {@link PoolItem} for the entries stored in the runtime item sets * @see {@link get} for acquiring items through the high-level API * @see {@link invalidate} for invalidating items through the high-level API * * @stability stable * @category models * @since 4.0.0 */ export interface State { readonly scope: Scope.Scope; isShuttingDown: boolean; usage: number; readonly resizeSemaphore: Semaphore.Semaphore; readonly items: Set>; availableHead: PoolItem | undefined; availableTail: PoolItem | undefined; readonly invalidated: Set>; readonly waiters: Set<(failure?: Exit.Failure) => void>; } /** * Internal record for a value managed by a `Pool`. * * **When to use** * * Use when implementing a custom pool `Strategy` that needs to inspect * acquired items, track reference counts, or return reclaimable items to the * pool. * * **Details** * * Each item stores the acquisition `Exit`, its finalizer, the current * reference count, when it last became idle, and whether automatic reclaiming * has been disabled because the item was invalidated. * * @see {@link Strategy} for the custom strategy callbacks that receive and return pool items * @see {@link State} for the runtime sets that store active, available, and invalidated pool items * * @stability stable * @category models * @since 4.0.0 */ export interface PoolItem { readonly exit: Exit.Exit; finalizer: Effect.Effect; refCount: number; /** Clock time at which the item was acquired or its last borrower released it. */ idleSince: number; disableReclaim: boolean; isAvailable: boolean; availablePrevious: PoolItem | undefined; availableNext: PoolItem | undefined; release: (exit: Exit.Exit) => Effect.Effect; } /** * Strategy used by a `Pool` to manage background resizing and item * reclamation. * * **When to use** * * Use when defining a custom pool lifecycle policy that needs to run background * work, observe acquired items, or choose items for reclamation. * * **Details** * * `run` starts any strategy-specific background work, `onAcquire` is invoked * when an item is acquired, and `reclaim` selects an item that can be removed * or replaced. * * @see {@link makeWithStrategy} for constructing a pool from a custom `Strategy` * * @stability stable * @category models * @since 4.0.0 */ export interface Strategy { readonly run: (pool: Pool) => Effect.Effect; readonly onAcquire: (item: PoolItem) => Effect.Effect; readonly reclaim: (pool: Pool) => Effect.Effect | undefined>; } /** * Returns `true` if the specified value is a `Pool`, `false` otherwise. * * **When to use** * * Use to validate unknown values at runtime boundaries before treating them as * `Pool` values. * * **Details** * * This predicate narrows the input to `Pool`. * * @stability stable * @category guards * @since 2.0.0 */ export declare const isPool: (u: unknown) => u is Pool; /** * Makes a new pool of the specified fixed size. * * **When to use** * * Use when you need a fixed-size pool with no growth or shrinkage. * * **Details** * * The pool is returned in a `Scope`, which governs the lifetime of the pool. * When the pool is shutdown because the `Scope` is closed, the individual * items allocated by the pool will be released in some unspecified order. * * By setting the `concurrency` parameter, you can control the level of concurrent * access per pool item. By default, the number of permits is set to `1`. * * `targetUtilization` determines when to create new pool items. It is a value * between 0 and 1, where 1 means only create new pool items when all the existing * items are fully utilized. * * A `targetUtilization` of 0.5 will create new pool items when the existing items are * 50% utilized. * * @see {@link makeWithTTL} for pools with min/max sizes and a TTL-based shrinking policy * @see {@link makeWithStrategy} for pools with a custom resizing and reclamation strategy * @stability stable * @category constructors * @since 2.0.0 */ export declare const make: (options: { readonly acquire: Effect.Effect; readonly size: number; readonly concurrency?: number | undefined; readonly targetUtilization?: number | undefined; }) => Effect.Effect, never, R | Scope.Scope>; /** * Creates a scoped pool with minimum and maximum sizes and a time-to-live * policy for shrinking unused excess items. * * **When to use** * * Use to create an elastic scoped pool that can grow up to a maximum size and * later reclaim unused excess items. * * **Details** * * The returned pool requires `Scope`; when that scope is closed, allocated * items are released in an unspecified order. `concurrency` controls how many * fibers may use each pool item at once and defaults to `1`. * * `targetUtilization` controls when new items are created and is clamped by the * pool implementation. A value of `1` waits until existing items are fully * utilized before creating more items. * * `timeToLiveStrategy` defaults to `"usage"`, which expires idle, unreserved * excess items after `timeToLive` since their last borrower released them * (or acquisition if never borrowed). It checks once per `timeToLive`, so * retirement can take up to twice that duration. `"creation"` measures from * item creation instead. * * **Example** (Creating a connection pool) * * ```ts import.meta.vitest * import { Duration, Effect, Pool } from "effect" * * interface Connection { * readonly execute: (sql: string) => Effect.Effect> * readonly close: Effect.Effect * } * * const acquireDBConnection = Effect.acquireRelease( * Effect.succeed({ * execute: (sql) => Effect.succeed([`executed: ${sql}`]), * close: Effect.void * } satisfies Connection), * (connection) => connection.close * ) * * const program = Effect.scoped( * Effect.flatMap( * Pool.makeWithTTL({ * acquire: acquireDBConnection, * min: 10, * max: 20, * timeToLive: Duration.seconds(60) * }), * (pool) => Effect.flatMap(Pool.get(pool), (connection) => connection.execute("select 1")) * ) * ) * * await Effect.runPromise(program) // => ["executed: select 1"] * ``` * * @stability stable * @category constructors * @since 2.0.0 */ export declare const makeWithTTL: (options: { readonly acquire: Effect.Effect; readonly min: number; readonly max: number; readonly concurrency?: number | undefined; readonly targetUtilization?: number | undefined; readonly timeToLive: Duration.Input; readonly timeToLiveStrategy?: "creation" | "usage" | undefined; }) => Effect.Effect, never, R | Scope.Scope>; /** * Creates a scoped pool using a custom resizing and reclamation strategy. * * **When to use** * * Use to build a pool whose item lifecycle is controlled by an explicit * `Strategy`, such as custom background resizing, replacement, or reclamation. * * **Details** * * The returned pool requires `Scope`; closing the scope shuts down the pool and * releases allocated items. * * @see {@link make} for fixed-size pools without custom resizing or reclamation * @see {@link makeWithTTL} for min/max pools that shrink excess items with a TTL policy * @see {@link Strategy} for the custom strategy contract consumed by this constructor * * @stability stable * @category constructors * @since 4.0.0 */ export declare const makeWithStrategy: (options: { readonly acquire: Effect.Effect; readonly min: number; readonly max: number; readonly concurrency?: number | undefined; readonly targetUtilization?: number | undefined; readonly strategy: Strategy; }) => Effect.Effect, never, Scope.Scope | R>; /** * Retrieves an item from the pool in a scoped effect. * * **When to use** * * Use to borrow a pooled resource for the lifetime of the current scope so it * is automatically returned when that scope closes. * * **Details** * * The returned effect waits for an available item when the pool is at capacity. * If acquiring a new item fails, the effect fails with the acquisition error. * * **Gotchas** * * Retrying a failed `get` can repeat the acquisition attempt. * * @see {@link invalidate} for removing an unhealthy item from future reuse * * @stability stable * @category getters * @since 2.0.0 */ export declare const get: (self: Pool) => Effect.Effect; /** * Borrows an item while an effect runs and returns it when the effect exits. * * **When to use** * * Use when an item is needed by one effect. Unlike `Effect.scoped` with * {@link get}, this avoids allocating a scope and registering a finalizer. * * **Example** (Running a single operation with a pooled item) * * ```ts import.meta.vitest * import { Effect, Pool } from "effect" * * const program = Effect.scoped( * Effect.flatMap( * Pool.make({ acquire: Effect.succeed("resource"), size: 2 }), * (pool) => Pool.use(pool, (item) => Effect.succeed(item.length)) * ) * ) * * await Effect.runPromise(program) // => 8 * ``` * * @see {@link get} for borrowing an item for the lifetime of a scope * * @stability stable * @category combinators * @since 4.0.0 */ export declare const use: { /** * Borrows an item while an effect runs and returns it when the effect exits. * * **When to use** * * Use when an item is needed by one effect. Unlike `Effect.scoped` with * {@link get}, this avoids allocating a scope and registering a finalizer. * * **Example** (Running a single operation with a pooled item) * * ```ts import.meta.vitest * import { Effect, Pool } from "effect" * * const program = Effect.scoped( * Effect.flatMap( * Pool.make({ acquire: Effect.succeed("resource"), size: 2 }), * (pool) => Pool.use(pool, (item) => Effect.succeed(item.length)) * ) * ) * * await Effect.runPromise(program) // => 8 * ``` * * @see {@link get} for borrowing an item for the lifetime of a scope * * @stability stable * @category combinators * @since 4.0.0 */ (f: (item: A) => Effect.Effect): (self: Pool) => Effect.Effect; /** * Borrows an item while an effect runs and returns it when the effect exits. * * **When to use** * * Use when an item is needed by one effect. Unlike `Effect.scoped` with * {@link get}, this avoids allocating a scope and registering a finalizer. * * **Example** (Running a single operation with a pooled item) * * ```ts import.meta.vitest * import { Effect, Pool } from "effect" * * const program = Effect.scoped( * Effect.flatMap( * Pool.make({ acquire: Effect.succeed("resource"), size: 2 }), * (pool) => Pool.use(pool, (item) => Effect.succeed(item.length)) * ) * ) * * await Effect.runPromise(program) // => 8 * ``` * * @see {@link get} for borrowing an item for the lifetime of a scope * * @stability stable * @category combinators * @since 4.0.0 */ (self: Pool, f: (item: A) => Effect.Effect): Effect.Effect; }; /** * Invalidates the specified item so the pool can remove it and reallocate the * item, lazily if needed. * * **When to use** * * Use to prevent a pooled item from being reused after it becomes unsuitable, * such as a stale connection or a resource that failed a health check. * * **Gotchas** * * The item is matched with strict equality. Passing an equivalent but different * object instance does nothing. * * @see {@link get} for retrieving scoped items from the pool * * @stability stable * @category combinators * @since 2.0.0 */ export declare const invalidate: { /** * Invalidates the specified item so the pool can remove it and reallocate the * item, lazily if needed. * * **When to use** * * Use to prevent a pooled item from being reused after it becomes unsuitable, * such as a stale connection or a resource that failed a health check. * * **Gotchas** * * The item is matched with strict equality. Passing an equivalent but different * object instance does nothing. * * @see {@link get} for retrieving scoped items from the pool * * @stability stable * @category combinators * @since 2.0.0 */ (item: A): (self: Pool) => Effect.Effect; /** * Invalidates the specified item so the pool can remove it and reallocate the * item, lazily if needed. * * **When to use** * * Use to prevent a pooled item from being reused after it becomes unsuitable, * such as a stale connection or a resource that failed a health check. * * **Gotchas** * * The item is matched with strict equality. Passing an equivalent but different * object instance does nothing. * * @see {@link get} for retrieving scoped items from the pool * * @stability stable * @category combinators * @since 2.0.0 */ (self: Pool, item: A): Effect.Effect; }; /** * Reserves a leased item for exclusive use until the scope closes. This * removes the item's remaining capacity from the pool but does not wait * for existing leases to finish. It has no effect when per-item concurrency is * `1` or the pool does not contain the item. * * @see {@link get} for acquiring an item * * @stability stable * @category combinators * @since 4.0.0 */ export declare const reserve: { /** * Reserves a leased item for exclusive use until the scope closes. This * removes the item's remaining capacity from the pool but does not wait * for existing leases to finish. It has no effect when per-item concurrency is * `1` or the pool does not contain the item. * * @see {@link get} for acquiring an item * * @stability stable * @category combinators * @since 4.0.0 */ (item: A): (self: Pool) => Effect.Effect; /** * Reserves a leased item for exclusive use until the scope closes. This * removes the item's remaining capacity from the pool but does not wait * for existing leases to finish. It has no effect when per-item concurrency is * `1` or the pool does not contain the item. * * @see {@link get} for acquiring an item * * @stability stable * @category combinators * @since 4.0.0 */ (self: Pool, item: A): Effect.Effect; }; export {}; //# sourceMappingURL=Pool.d.ts.map