Skip to content

Commit 817a04c

Browse files
authoredMar 13, 2024··
add support for AbortSignal's to runPromise (#2285)
1 parent 802674b commit 817a04c

File tree

5 files changed

+75
-19
lines changed

5 files changed

+75
-19
lines changed
 

‎.changeset/five-games-sneeze.md

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
"effect": patch
3+
---
4+
5+
add support for AbortSignal's to runPromise
6+
7+
If the signal is aborted, the effect execution will be interrupted.
8+
9+
```ts
10+
import { Effect } from "effect";
11+
12+
const controller = new AbortController();
13+
14+
Effect.runPromise(Effect.never, { signal: controller.signal });
15+
16+
// abort after 1 second
17+
setTimeout(() => controller.abort(), 1000);
18+
```

‎packages/effect/src/Effect.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -4672,7 +4672,10 @@ export const runCallback: <A, E>(
46724672
* @since 2.0.0
46734673
* @category execution
46744674
*/
4675-
export const runPromise: <A, E>(effect: Effect<A, E>) => Promise<A> = _runtime.unsafeRunPromiseEffect
4675+
export const runPromise: <A, E>(
4676+
effect: Effect<A, E, never>,
4677+
options?: { readonly signal?: AbortSignal } | undefined
4678+
) => Promise<A> = _runtime.unsafeRunPromiseEffect
46764679

46774680
/**
46784681
* Runs an `Effect` workflow, returning a `Promise` which resolves with the
@@ -4681,8 +4684,10 @@ export const runPromise: <A, E>(effect: Effect<A, E>) => Promise<A> = _runtime.u
46814684
* @since 2.0.0
46824685
* @category execution
46834686
*/
4684-
export const runPromiseExit: <A, E>(effect: Effect<A, E>) => Promise<Exit.Exit<A, E>> =
4685-
_runtime.unsafeRunPromiseExitEffect
4687+
export const runPromiseExit: <A, E>(
4688+
effect: Effect<A, E, never>,
4689+
options?: { readonly signal?: AbortSignal } | undefined
4690+
) => Promise<Exit.Exit<A, E>> = _runtime.unsafeRunPromiseExitEffect
46864691

46874692
/**
46884693
* @since 2.0.0

‎packages/effect/src/Runtime.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ export const runCallback: <R>(
134134
* @since 2.0.0
135135
* @category execution
136136
*/
137-
export const runPromise: <R>(runtime: Runtime<R>) => <A, E>(effect: Effect.Effect<A, E, R>) => Promise<A> =
137+
export const runPromise: <R>(
138+
runtime: Runtime<R>
139+
) => <A, E>(effect: Effect.Effect<A, E, R>, options?: { readonly signal?: AbortSignal } | undefined) => Promise<A> =
138140
internal.unsafeRunPromise
139141

140142
/**
@@ -149,7 +151,10 @@ export const runPromise: <R>(runtime: Runtime<R>) => <A, E>(effect: Effect.Effec
149151
*/
150152
export const runPromiseExit: <R>(
151153
runtime: Runtime<R>
152-
) => <A, E>(effect: Effect.Effect<A, E, R>) => Promise<Exit.Exit<A, E>> = internal.unsafeRunPromiseExit
154+
) => <A, E>(
155+
effect: Effect.Effect<A, E, R>,
156+
options?: { readonly signal?: AbortSignal } | undefined
157+
) => Promise<Exit.Exit<A, E>> = internal.unsafeRunPromiseExit
153158

154159
/**
155160
* @since 2.0.0

‎packages/effect/src/internal/runtime.ts

+28-13
Original file line numberDiff line numberDiff line change
@@ -257,30 +257,45 @@ export const unsafeRunSyncExit =
257257
}
258258

259259
/** @internal */
260-
export const unsafeRunPromise =
261-
<R>(runtime: Runtime.Runtime<R>) => <A, E>(effect: Effect.Effect<A, E, R>): Promise<A> =>
262-
unsafeRunPromiseExit(runtime)(effect).then((result) => {
263-
switch (result._tag) {
264-
case OpCodes.OP_SUCCESS: {
265-
return result.i0
266-
}
267-
case OpCodes.OP_FAILURE: {
268-
throw fiberFailure(result.i0)
269-
}
260+
export const unsafeRunPromise = <R>(runtime: Runtime.Runtime<R>) =>
261+
<A, E>(effect: Effect.Effect<A, E, R>, options?: {
262+
readonly signal?: AbortSignal
263+
}): Promise<A> =>
264+
unsafeRunPromiseExit(runtime)(effect, options).then((result) => {
265+
switch (result._tag) {
266+
case OpCodes.OP_SUCCESS: {
267+
return result.i0
270268
}
271-
})
269+
case OpCodes.OP_FAILURE: {
270+
throw fiberFailure(result.i0)
271+
}
272+
}
273+
})
272274

273275
/** @internal */
274276
export const unsafeRunPromiseExit =
275-
<R>(runtime: Runtime.Runtime<R>) => <A, E>(effect: Effect.Effect<A, E, R>): Promise<Exit.Exit<A, E>> =>
277+
<R>(runtime: Runtime.Runtime<R>) =>
278+
<A, E>(effect: Effect.Effect<A, E, R>, options?: {
279+
readonly signal?: AbortSignal
280+
}): Promise<Exit.Exit<A, E>> =>
276281
new Promise((resolve) => {
277282
const op = fastPath(effect)
278283
if (op) {
279284
resolve(op)
280285
}
281-
unsafeFork(runtime)(effect).addObserver((exit) => {
286+
const fiber = unsafeFork(runtime)(effect)
287+
fiber.addObserver((exit) => {
282288
resolve(exit)
283289
})
290+
if (options?.signal !== undefined) {
291+
if (options.signal.aborted) {
292+
fiber.unsafeInterruptAsFork(fiber.id())
293+
} else {
294+
options.signal.addEventListener("abort", () => {
295+
fiber.unsafeInterruptAsFork(fiber.id())
296+
})
297+
}
298+
}
284299
})
285300

286301
/** @internal */

‎packages/effect/test/Runtime.test.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Effect, FiberRef, Layer, Runtime } from "effect"
1+
import { Effect, Exit, FiberRef, Layer, Runtime } from "effect"
22
import { assert, describe } from "vitest"
33
import * as it from "./utils/extend.js"
44

@@ -27,4 +27,17 @@ describe("Runtime", () => {
2727
result = Runtime.runSync(Runtime.deleteFiberRef(runtime, ref))(FiberRef.get(ref))
2828
assert.deepStrictEqual(result, { value: 0 })
2929
}))
30+
31+
it.it("runPromiseExit/signal", async () => {
32+
const aborted = AbortSignal.abort()
33+
assert(Exit.isInterrupted(await Runtime.runPromiseExit(Runtime.defaultRuntime)(Effect.never, { signal: aborted })))
34+
35+
const controller = new AbortController()
36+
setTimeout(() => controller.abort(), 10)
37+
assert(
38+
Exit.isInterrupted(
39+
await Runtime.runPromiseExit(Runtime.defaultRuntime)(Effect.never, { signal: controller.signal })
40+
)
41+
)
42+
})
3043
})

0 commit comments

Comments
 (0)
Please sign in to comment.