Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pool is subtype of Effect #3674

Merged
merged 3 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/lemon-worms-return.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": minor
---

`Pool` is now a subtype of `Effect`, equivalent to `Pool.get`
13 changes: 12 additions & 1 deletion packages/effect/dtslint/Unify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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>
Expand All @@ -130,7 +138,7 @@ export type ResourceUnify = Unify.Unify<
| Resource.Resource<any, any>
>

// $ExpectType 0 | Option<string | number> | 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<string | number> | 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">
Expand Down Expand Up @@ -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>
Expand Down
27 changes: 26 additions & 1 deletion packages/effect/src/Pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -28,7 +29,7 @@ export type PoolTypeId = typeof PoolTypeId
* @since 2.0.0
* @category models
*/
export interface Pool<in out A, out E = never> extends Pool.Variance<A, E>, Pipeable {
export interface Pool<in out A, out E = never> extends Pool.Variance<A, E>, Effect.Effect<A, E, Scope.Scope>, 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.
Expand All @@ -42,6 +43,30 @@ export interface Pool<in out A, out E = never> extends Pool.Variance<A, E>, Pipe
* than eagerly.
*/
invalidate(item: A): Effect.Effect<void>

readonly [Unify.typeSymbol]?: unknown
readonly [Unify.unifySymbol]?: PoolUnify<this>
readonly [Unify.ignoreSymbol]?: PoolUnifyIgnore
}

/**
* @category models
* @since 3.9.0
*/
export interface PoolUnify<A extends { [Unify.typeSymbol]?: any }> extends Effect.EffectUnify<A> {
Pool?: () => Extract<A[Unify.typeSymbol], Pool<any, any>> extends Pool<infer A0, infer _E0> | infer _ ?
A0 extends any ? Extract<A[Unify.typeSymbol], Pool<A0, any>> extends Pool<A0, infer E1> ? Pool<A0, E1>
: never
: never :
never
}

/**
* @category models
* @since 3.9.0
*/
export interface PoolUnifyIgnore extends Effect.EffectUnifyIgnore {
Effect?: true
}

/**
Expand Down
8 changes: 7 additions & 1 deletion packages/effect/src/internal/pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -122,7 +123,7 @@ interface Strategy<A, E> {
readonly reclaim: (pool: PoolImpl<A, E>) => Effect<Option.Option<PoolItem<A, E>>>
}

class PoolImpl<A, E> implements Pool<A, E> {
class PoolImpl<A, E> extends Effectable.Class<A, E, Scope> implements Pool<A, E> {
readonly [PoolTypeId]: Pool.Variance<A, E>[PoolTypeId_]

isShuttingDown = false
Expand All @@ -140,6 +141,7 @@ class PoolImpl<A, E> implements Pool<A, E> {
readonly strategy: Strategy<A, E>,
readonly targetUtilization: number
) {
super()
this[PoolTypeId] = poolVariance
this.semaphore = circular.unsafeMakeSemaphore(concurrency * maxSize)
}
Expand Down Expand Up @@ -253,6 +255,10 @@ class PoolImpl<A, E> implements Pool<A, E> {
)
)

commit() {
return this.get
}

readonly get: Effect<A, E, Scope> = core.flatMap(
core.suspend(() => this.isShuttingDown ? core.interrupt : this.getPoolItem),
(_) => _.exit
Expand Down
10 changes: 10 additions & 0 deletions packages/effect/test/Pool.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}))
})