Skip to content

Commit f9461b9

Browse files
vinassefranchetim-smart
authored andcommitted
Make runtime run sync dual (#4374)
Co-authored-by: Tim <hello@timsmart.co>
1 parent d63a5c4 commit f9461b9

File tree

6 files changed

+263
-63
lines changed

6 files changed

+263
-63
lines changed

.changeset/yellow-lemons-worry.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"effect": minor
3+
---
4+
5+
Make Runtime.run* apis dual

packages/effect/src/Runtime.ts

Lines changed: 54 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,16 @@ export interface RunForkOptions {
8181
* @since 2.0.0
8282
* @category execution
8383
*/
84-
export const runFork: <R>(
85-
runtime: Runtime<R>
86-
) => <A, E>(self: Effect.Effect<A, E, R>, options?: RunForkOptions) => Fiber.RuntimeFiber<A, E> = internal.unsafeFork
84+
export const runFork: {
85+
<R>(
86+
runtime: Runtime<R>
87+
): <A, E>(effect: Effect.Effect<A, E, R>, options?: RunForkOptions | undefined) => Fiber.RuntimeFiber<A, E>
88+
<R, A, E>(
89+
runtime: Runtime<R>,
90+
effect: Effect.Effect<A, E, R>,
91+
options?: RunForkOptions | undefined
92+
): Fiber.RuntimeFiber<A, E>
93+
} = internal.unsafeFork
8794

8895
/**
8996
* Executes the effect synchronously returning the exit.
@@ -94,8 +101,10 @@ export const runFork: <R>(
94101
* @since 2.0.0
95102
* @category execution
96103
*/
97-
export const runSyncExit: <R>(runtime: Runtime<R>) => <A, E>(effect: Effect.Effect<A, E, R>) => Exit.Exit<A, E> =
98-
internal.unsafeRunSyncExit
104+
export const runSyncExit: {
105+
<A, E, R>(runtime: Runtime<R>, effect: Effect.Effect<A, E, R>): Exit.Exit<A, E>
106+
<R>(runtime: Runtime<R>): <A, E>(effect: Effect.Effect<A, E, R>) => Exit.Exit<A, E>
107+
} = internal.unsafeRunSyncExit
99108

100109
/**
101110
* Executes the effect synchronously throwing in case of errors or async boundaries.
@@ -106,7 +115,10 @@ export const runSyncExit: <R>(runtime: Runtime<R>) => <A, E>(effect: Effect.Effe
106115
* @since 2.0.0
107116
* @category execution
108117
*/
109-
export const runSync: <R>(runtime: Runtime<R>) => <A, E>(effect: Effect.Effect<A, E, R>) => A = internal.unsafeRunSync
118+
export const runSync: {
119+
<A, E, R>(runtime: Runtime<R>, effect: Effect.Effect<A, E, R>): A
120+
<R>(runtime: Runtime<R>): <A, E>(effect: Effect.Effect<A, E, R>) => A
121+
} = internal.unsafeRunSync
110122

111123
/**
112124
* @since 2.0.0
@@ -126,10 +138,19 @@ export interface RunCallbackOptions<in A, in E = never> extends RunForkOptions {
126138
* @since 2.0.0
127139
* @category execution
128140
*/
129-
export const runCallback: <R>(
130-
runtime: Runtime<R>
131-
) => <A, E>(effect: Effect.Effect<A, E, R>, options?: RunCallbackOptions<A, E> | undefined) => Cancel<A, E> =
132-
internal.unsafeRunCallback
141+
export const runCallback: {
142+
<R>(
143+
runtime: Runtime<R>
144+
): <A, E>(
145+
effect: Effect.Effect<A, E, R>,
146+
options?: RunCallbackOptions<A, E> | undefined
147+
) => (fiberId?: FiberId.FiberId, options?: RunCallbackOptions<A, E> | undefined) => void
148+
<R, A, E>(
149+
runtime: Runtime<R>,
150+
effect: Effect.Effect<A, E, R>,
151+
options?: RunCallbackOptions<A, E> | undefined
152+
): (fiberId?: FiberId.FiberId, options?: RunCallbackOptions<A, E> | undefined) => void
153+
} = internal.unsafeRunCallback
133154

134155
/**
135156
* Runs the `Effect`, returning a JavaScript `Promise` that will be resolved
@@ -142,10 +163,16 @@ export const runCallback: <R>(
142163
* @since 2.0.0
143164
* @category execution
144165
*/
145-
export const runPromise: <R>(
146-
runtime: Runtime<R>
147-
) => <A, E>(effect: Effect.Effect<A, E, R>, options?: { readonly signal?: AbortSignal } | undefined) => Promise<A> =
148-
internal.unsafeRunPromise
166+
export const runPromise: {
167+
<R>(
168+
runtime: Runtime<R>
169+
): <A, E>(effect: Effect.Effect<A, E, R>, options?: { readonly signal?: AbortSignal } | undefined) => Promise<A>
170+
<R, A, E>(
171+
runtime: Runtime<R>,
172+
effect: Effect.Effect<A, E, R>,
173+
options?: { readonly signal?: AbortSignal } | undefined
174+
): Promise<A>
175+
} = internal.unsafeRunPromise
149176

150177
/**
151178
* Runs the `Effect`, returning a JavaScript `Promise` that will be resolved
@@ -157,12 +184,19 @@ export const runPromise: <R>(
157184
* @since 2.0.0
158185
* @category execution
159186
*/
160-
export const runPromiseExit: <R>(
161-
runtime: Runtime<R>
162-
) => <A, E>(
163-
effect: Effect.Effect<A, E, R>,
164-
options?: { readonly signal?: AbortSignal } | undefined
165-
) => Promise<Exit.Exit<A, E>> = internal.unsafeRunPromiseExit
187+
export const runPromiseExit: {
188+
<R>(
189+
runtime: Runtime<R>
190+
): <A, E>(
191+
effect: Effect.Effect<A, E, R>,
192+
options?: { readonly signal?: AbortSignal } | undefined
193+
) => Promise<Exit.Exit<A, E>>
194+
<R, A, E>(
195+
runtime: Runtime<R>,
196+
effect: Effect.Effect<A, E, R>,
197+
options?: { readonly signal?: AbortSignal } | undefined
198+
): Promise<Exit.Exit<A, E>>
199+
} = internal.unsafeRunPromiseExit
166200

167201
/**
168202
* @since 2.0.0

packages/effect/src/internal/runtime.ts

Lines changed: 104 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,33 @@ import * as OpCodes from "./opCodes/effect.js"
2626
import * as runtimeFlags from "./runtimeFlags.js"
2727
import * as supervisor_ from "./supervisor.js"
2828

29+
const makeDual = <Args extends Array<any>, Return>(
30+
f: (runtime: Runtime.Runtime<never>, effect: Effect.Effect<any, any>, ...args: Args) => Return
31+
): {
32+
<R>(runtime: Runtime.Runtime<R>): <A, E>(effect: Effect.Effect<A, E, R>, ...args: Args) => Return
33+
<R, A, E>(runtime: Runtime.Runtime<R>, effect: Effect.Effect<A, E, R>, ...args: Args): Return
34+
} =>
35+
function(this: any) {
36+
if (arguments.length === 1) {
37+
const runtime = arguments[0]
38+
return (effect: any, ...args: Args) => f(runtime, effect, ...args)
39+
}
40+
return f.apply(this, arguments as any)
41+
} as any
42+
2943
/** @internal */
30-
export const unsafeFork = <R>(runtime: Runtime.Runtime<R>) =>
31-
<A, E>(
44+
export const unsafeFork: {
45+
<R>(runtime: Runtime.Runtime<R>): <A, E>(
46+
effect: Effect.Effect<A, E, R>,
47+
options?: Runtime.RunForkOptions | undefined
48+
) => Fiber.RuntimeFiber<A, E>
49+
<R, A, E>(
50+
runtime: Runtime.Runtime<R>,
51+
effect: Effect.Effect<A, E, R>,
52+
options?: Runtime.RunForkOptions | undefined
53+
): Fiber.RuntimeFiber<A, E>
54+
} = makeDual(<R, A, E>(
55+
runtime: Runtime.Runtime<R>,
3256
self: Effect.Effect<A, E, R>,
3357
options?: Runtime.RunForkOptions
3458
): Fiber.RuntimeFiber<A, E> => {
@@ -93,15 +117,25 @@ export const unsafeFork = <R>(runtime: Runtime.Runtime<R>) =>
93117
}
94118

95119
return fiberRuntime
96-
}
120+
})
97121

98122
/** @internal */
99-
export const unsafeRunCallback = <R>(runtime: Runtime.Runtime<R>) =>
100-
<A, E>(
101-
effect: Effect.Effect<A, E, R>,
102-
options: Runtime.RunCallbackOptions<A, E> = {}
103-
): (fiberId?: FiberId.FiberId, options?: Runtime.RunCallbackOptions<A, E> | undefined) => void => {
104-
const fiberRuntime = unsafeFork(runtime)(effect, options)
123+
export const unsafeRunCallback: {
124+
<R>(runtime: Runtime.Runtime<R>): <A, E>(
125+
effect: Effect.Effect<A, E, R>,
126+
options?: Runtime.RunCallbackOptions<A, E> | undefined
127+
) => (fiberId?: FiberId.FiberId, options?: Runtime.RunCallbackOptions<A, E> | undefined) => void
128+
<R, A, E>(
129+
runtime: Runtime.Runtime<R>,
130+
effect: Effect.Effect<A, E, R>,
131+
options?: Runtime.RunCallbackOptions<A, E> | undefined
132+
): (fiberId?: FiberId.FiberId, options?: Runtime.RunCallbackOptions<A, E> | undefined) => void
133+
} = makeDual((
134+
runtime,
135+
effect,
136+
options: Runtime.RunCallbackOptions<any, any> = {}
137+
): (fiberId?: FiberId.FiberId, options?: Runtime.RunCallbackOptions<any, any> | undefined) => void => {
138+
const fiberRuntime = unsafeFork(runtime, effect, options)
105139

106140
if (options.onExit) {
107141
fiberRuntime.addObserver((exit) => {
@@ -119,17 +153,19 @@ export const unsafeRunCallback = <R>(runtime: Runtime.Runtime<R>) =>
119153
: undefined
120154
}
121155
)
122-
}
156+
})
123157

124158
/** @internal */
125-
export const unsafeRunSync = <R>(runtime: Runtime.Runtime<R>) => <A, E>(effect: Effect.Effect<A, E, R>): A => {
159+
export const unsafeRunSync: {
160+
<A, E, R>(runtime: Runtime.Runtime<R>, effect: Effect.Effect<A, E, R>): A
161+
<R>(runtime: Runtime.Runtime<R>): <A, E>(effect: Effect.Effect<A, E, R>) => A
162+
} = makeDual((runtime, effect) => {
126163
const result = unsafeRunSyncExit(runtime)(effect)
127164
if (result._tag === "Failure") {
128165
throw fiberFailure(result.effect_instruction_i0)
129-
} else {
130-
return result.effect_instruction_i0
131166
}
132-
}
167+
return result.effect_instruction_i0
168+
})
133169

134170
class AsyncFiberExceptionImpl<A, E = never> extends Error implements Runtime.AsyncFiberException<A, E> {
135171
readonly _tag = "AsyncFiberException"
@@ -229,31 +265,47 @@ const fastPath = <A, E, R>(effect: Effect.Effect<A, E, R>): Exit.Exit<A, E> | un
229265
}
230266

231267
/** @internal */
232-
export const unsafeRunSyncExit =
233-
<R>(runtime: Runtime.Runtime<R>) => <A, E>(effect: Effect.Effect<A, E, R>): Exit.Exit<A, E> => {
234-
const op = fastPath(effect)
235-
if (op) {
236-
return op
237-
}
238-
const scheduler = new scheduler_.SyncScheduler()
239-
const fiberRuntime = unsafeFork(runtime)(effect, { scheduler })
240-
scheduler.flush()
241-
const result = fiberRuntime.unsafePoll()
242-
if (result) {
243-
return result
244-
}
245-
return core.exitDie(core.capture(asyncFiberException(fiberRuntime), core.currentSpanFromFiber(fiberRuntime)))
268+
export const unsafeRunSyncExit: {
269+
<A, E, R>(runtime: Runtime.Runtime<R>, effect: Effect.Effect<A, E, R>): Exit.Exit<A, E>
270+
<R>(runtime: Runtime.Runtime<R>): <A, E>(effect: Effect.Effect<A, E, R>) => Exit.Exit<A, E>
271+
} = makeDual((runtime, effect) => {
272+
const op = fastPath(effect)
273+
if (op) {
274+
return op
246275
}
276+
const scheduler = new scheduler_.SyncScheduler()
277+
const fiberRuntime = unsafeFork(runtime)(effect, { scheduler })
278+
scheduler.flush()
279+
const result = fiberRuntime.unsafePoll()
280+
if (result) {
281+
return result
282+
}
283+
return core.exitDie(core.capture(asyncFiberException(fiberRuntime), core.currentSpanFromFiber(fiberRuntime)))
284+
})
247285

248286
/** @internal */
249-
export const unsafeRunPromise = <R>(runtime: Runtime.Runtime<R>) =>
250-
<A, E>(
251-
effect: Effect.Effect<A, E, R>,
287+
export const unsafeRunPromise: {
288+
<R>(runtime: Runtime.Runtime<R>): <A, E>(
289+
effect: Effect.Effect<A, E, R>,
290+
options?: {
291+
readonly signal?: AbortSignal | undefined
292+
} | undefined
293+
) => Promise<A>
294+
<R, A, E>(
295+
runtime: Runtime.Runtime<R>,
296+
effect: Effect.Effect<A, E, R>,
297+
options?: {
298+
readonly signal?: AbortSignal | undefined
299+
} | undefined
300+
): Promise<A>
301+
} = makeDual((
302+
runtime,
303+
effect,
252304
options?: {
253305
readonly signal?: AbortSignal | undefined
254306
} | undefined
255-
): Promise<A> =>
256-
unsafeRunPromiseExit(runtime)(effect, options).then((result) => {
307+
) =>
308+
unsafeRunPromiseExit(runtime, effect, options).then((result) => {
257309
switch (result._tag) {
258310
case OpCodes.OP_SUCCESS: {
259311
return result.effect_instruction_i0
@@ -263,16 +315,29 @@ export const unsafeRunPromise = <R>(runtime: Runtime.Runtime<R>) =>
263315
}
264316
}
265317
})
318+
)
266319

267320
/** @internal */
268-
export const unsafeRunPromiseExit = <R>(runtime: Runtime.Runtime<R>) =>
269-
<A, E>(
270-
effect: Effect.Effect<A, E, R>,
321+
export const unsafeRunPromiseExit: {
322+
<R>(
323+
runtime: Runtime.Runtime<R>
324+
): <A, E>(
325+
effect: Effect.Effect<A, E, R>,
326+
options?: { readonly signal?: AbortSignal | undefined } | undefined
327+
) => Promise<Exit.Exit<A, E>>
328+
<R, A, E>(
329+
runtime: Runtime.Runtime<R>,
330+
effect: Effect.Effect<A, E, R>,
331+
options?: { readonly signal?: AbortSignal | undefined } | undefined
332+
): Promise<Exit.Exit<A, E>>
333+
} = makeDual((
334+
runtime,
335+
effect,
271336
options?: {
272337
readonly signal?: AbortSignal | undefined
273338
} | undefined
274-
): Promise<Exit.Exit<A, E>> =>
275-
new Promise((resolve) => {
339+
) =>
340+
new Promise<Exit.Exit<any, any>>((resolve) => {
276341
const op = fastPath(effect)
277342
if (op) {
278343
resolve(op)
@@ -291,6 +356,7 @@ export const unsafeRunPromiseExit = <R>(runtime: Runtime.Runtime<R>) =>
291356
}
292357
}
293358
})
359+
)
294360

295361
/** @internal */
296362
export class RuntimeImpl<in R> implements Runtime.Runtime<R> {

0 commit comments

Comments
 (0)