From 96db097d7bcddec487c9fe017b42fde76fe0ff22 Mon Sep 17 00:00:00 2001 From: Maxim Khramtsov Date: Wed, 25 Sep 2024 04:09:09 +0200 Subject: [PATCH] `Pool` is subtype of `Effect` (#3674) Co-authored-by: maksim.khramtsov Co-authored-by: Tim --- .changeset/lemon-worms-return.md | 5 +++++ packages/effect/dtslint/Unify.ts | 13 ++++++++++++- packages/effect/src/Pool.ts | 27 ++++++++++++++++++++++++++- packages/effect/src/internal/pool.ts | 8 +++++++- packages/effect/test/Pool.test.ts | 10 ++++++++++ 5 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 .changeset/lemon-worms-return.md diff --git a/.changeset/lemon-worms-return.md b/.changeset/lemon-worms-return.md new file mode 100644 index 0000000000..75a5d4fea4 --- /dev/null +++ b/.changeset/lemon-worms-return.md @@ -0,0 +1,5 @@ +--- +"effect": minor +--- + +`Pool` is now a subtype of `Effect`, equivalent to `Pool.get` diff --git a/packages/effect/dtslint/Unify.ts b/packages/effect/dtslint/Unify.ts index 92069fae68..c2a59db3ac 100644 --- a/packages/effect/dtslint/Unify.ts +++ b/packages/effect/dtslint/Unify.ts @@ -7,6 +7,7 @@ import type * as FiberRef from "effect/FiberRef" import type * as ManagedRuntime from "effect/ManagedRuntime" import type * as Micro from "effect/Micro" import type * as Option from "effect/Option" +import type * as Pool from "effect/Pool" import type * as Queue from "effect/Queue" import type * as RcRef from "effect/RcRef" import type * as Ref from "effect/Ref" @@ -116,6 +117,13 @@ export type DequeueUnify = Unify.Unify< | Queue.Dequeue<1> | Queue.Dequeue<"a"> > +// $ExpectType Pool<1, 2> | Pool<"a", "b" | "c"> +export type PoolUnify = Unify.Unify< + | Pool.Pool<1, 2> + | Pool.Pool<"a", "b"> + | Pool.Pool<"a", "c"> +> + // $ExpectType ScopedRef<1> | ScopedRef<"a"> export type ScopedRefUnify = Unify.Unify< | ScopedRef.ScopedRef<1> @@ -130,7 +138,7 @@ export type ResourceUnify = Unify.Unify< | Resource.Resource > -// $ExpectType 0 | Option | Ref<1> | Ref<"a"> | SynchronizedRef<1> | SynchronizedRef<"a"> | SubscriptionRef<1> | SubscriptionRef<"a"> | RcRef<"a", "b"> | Deferred<"a", "b"> | FiberRef<1> | FiberRef<"a"> | ManagedRuntime<"a", "b"> | Queue<1> | Queue<"a"> | Dequeue<"a" | 1> | ScopedRef<1> | ScopedRef<"a"> | Resource<"a", "b"> | RcRef<1, 0> | Deferred<1, 0> | Resource<1, 0> | Latch | ManagedRuntime<1, 0> | Fiber<"a" | 1, 0 | "b"> | RuntimeFiber<"a" | 1, 0 | "b"> | Either<"a" | 1, 0 | "b"> | Effect<"a" | 1, 0 | "b", "R" | "R1"> +// $ExpectType 0 | Option | Ref<1> | Ref<"a"> | SynchronizedRef<1> | SynchronizedRef<"a"> | SubscriptionRef<1> | SubscriptionRef<"a"> | RcRef<"a", "b"> | Deferred<"a", "b"> | FiberRef<1> | FiberRef<"a"> | ManagedRuntime<"a", "b"> | Queue<1> | Queue<"a"> | Dequeue<"a" | 1> | Pool<1, 2> | Pool<"a", "b" | "c"> | ScopedRef<1> | ScopedRef<"a"> | Resource<"a", "b"> | RcRef<1, 0> | Deferred<1, 0> | Resource<1, 0> | Latch | ManagedRuntime<1, 0> | Fiber<"a" | 1, 0 | "b"> | RuntimeFiber<"a" | 1, 0 | "b"> | Either<"a" | 1, 0 | "b"> | Effect<"a" | 1, 0 | "b", "R" | "R1"> export type AllUnify = Unify.Unify< | Either.Either<1, 0> | Either.Either<"a", "b"> @@ -158,6 +166,9 @@ export type AllUnify = Unify.Unify< | Queue.Queue<"a"> | Queue.Dequeue<1> | Queue.Dequeue<"a"> + | Pool.Pool<1, 2> + | Pool.Pool<"a", "b"> + | Pool.Pool<"a", "c"> | ScopedRef.ScopedRef<1> | ScopedRef.ScopedRef<"a"> | Resource.Resource<1, 0> diff --git a/packages/effect/src/Pool.ts b/packages/effect/src/Pool.ts index 59383ee57f..fd705d28c9 100644 --- a/packages/effect/src/Pool.ts +++ b/packages/effect/src/Pool.ts @@ -7,6 +7,7 @@ import * as internal from "./internal/pool.js" import type { Pipeable } from "./Pipeable.js" import type * as Scope from "./Scope.js" import type * as Types from "./Types.js" +import type * as Unify from "./Unify.js" /** * @since 2.0.0 @@ -28,7 +29,7 @@ export type PoolTypeId = typeof PoolTypeId * @since 2.0.0 * @category models */ -export interface Pool extends Pool.Variance, Pipeable { +export interface Pool extends Pool.Variance, Effect.Effect, Pipeable { /** * Retrieves an item from the pool in a scoped effect. Note that if * acquisition fails, then the returned effect will fail for that same reason. @@ -42,6 +43,30 @@ export interface Pool extends Pool.Variance, Pipe * than eagerly. */ invalidate(item: A): Effect.Effect + + readonly [Unify.typeSymbol]?: unknown + readonly [Unify.unifySymbol]?: PoolUnify + readonly [Unify.ignoreSymbol]?: PoolUnifyIgnore +} + +/** + * @category models + * @since 3.9.0 + */ +export interface PoolUnify extends Effect.EffectUnify { + Pool?: () => Extract> extends Pool | infer _ ? + A0 extends any ? Extract> extends Pool ? Pool + : never + : never : + never +} + +/** + * @category models + * @since 3.9.0 + */ +export interface PoolUnifyIgnore extends Effect.EffectUnifyIgnore { + Effect?: true } /** diff --git a/packages/effect/src/internal/pool.ts b/packages/effect/src/internal/pool.ts index 8079a98fb6..d32b91beb2 100644 --- a/packages/effect/src/internal/pool.ts +++ b/packages/effect/src/internal/pool.ts @@ -2,6 +2,7 @@ import type { Cause } from "effect/Cause" import * as Context from "../Context.js" import * as Duration from "../Duration.js" import type { Effect, Semaphore } from "../Effect.js" +import * as Effectable from "../Effectable.js" import type { Exit } from "../Exit.js" import { dual, identity } from "../Function.js" import * as Iterable from "../Iterable.js" @@ -122,7 +123,7 @@ interface Strategy { readonly reclaim: (pool: PoolImpl) => Effect>> } -class PoolImpl implements Pool { +class PoolImpl extends Effectable.Class implements Pool { readonly [PoolTypeId]: Pool.Variance[PoolTypeId_] isShuttingDown = false @@ -140,6 +141,7 @@ class PoolImpl implements Pool { readonly strategy: Strategy, readonly targetUtilization: number ) { + super() this[PoolTypeId] = poolVariance this.semaphore = circular.unsafeMakeSemaphore(concurrency * maxSize) } @@ -253,6 +255,10 @@ class PoolImpl implements Pool { ) ) + commit() { + return this.get + } + readonly get: Effect = core.flatMap( core.suspend(() => this.isShuttingDown ? core.interrupt : this.getPoolItem), (_) => _.exit diff --git a/packages/effect/test/Pool.test.ts b/packages/effect/test/Pool.test.ts index 756a838b34..c0de074820 100644 --- a/packages/effect/test/Pool.test.ts +++ b/packages/effect/test/Pool.test.ts @@ -423,4 +423,14 @@ describe("Pool", () => { expect(yield* Ref.get(allocations)).toBe(11) expect(yield* Ref.get(released)).toBe(11) })) + + it.scoped("is subtype of Effect", () => + Effect.gen(function*() { + const pool = yield* Pool.make({ + acquire: Effect.succeed(1), + size: 1 + }) + const item = yield* pool + assert.strictEqual(item, 1) + })) })