Skip to content

Commit 194d748

Browse files
committed
add ExecutionPlan module (#4910)
1 parent 58bfeaa commit 194d748

File tree

12 files changed

+803
-83
lines changed

12 files changed

+803
-83
lines changed

.changeset/public-books-unite.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
"effect": minor
3+
---
4+
5+
add ExecutionPlan module
6+
7+
A `ExecutionPlan` can be used with `Effect.withExecutionPlan` or `Stream.withExecutionPlan`, allowing you to provide different resources for each step of execution until the effect succeeds or the plan is exhausted.
8+
9+
```ts
10+
import { type AiLanguageModel } from "@effect/ai"
11+
import type { Layer } from "effect"
12+
import { Effect, ExecutionPlan, Schedule } from "effect"
13+
14+
declare const layerBad: Layer.Layer<AiLanguageModel.AiLanguageModel>
15+
declare const layerGood: Layer.Layer<AiLanguageModel.AiLanguageModel>
16+
17+
const ThePlan = ExecutionPlan.make(
18+
{
19+
// First try with the bad layer 2 times with a 3 second delay between attempts
20+
provide: layerBad,
21+
attempts: 2,
22+
schedule: Schedule.spaced(3000)
23+
},
24+
// Then try with the bad layer 3 times with a 1 second delay between attempts
25+
{
26+
provide: layerBad,
27+
attempts: 3,
28+
schedule: Schedule.spaced(1000)
29+
},
30+
// Finally try with the good layer.
31+
//
32+
// If `attempts` is omitted, the plan will only attempt once, unless a schedule is provided.
33+
{
34+
provide: layerGood
35+
}
36+
)
37+
38+
declare const effect: Effect.Effect<
39+
void,
40+
never,
41+
AiLanguageModel.AiLanguageModel
42+
>
43+
const withPlan: Effect.Effect<void> = Effect.withExecutionPlan(effect, ThePlan)
44+
```

packages/effect/docgen.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"paths": {
1414
"effect": ["../../../effect/src/index.js"],
1515
"effect/*": ["../../../effect/src/*.js"],
16+
"@effect/ai": ["../../../ai/ai/src/index.js"],
1617
"@effect/platform": ["../../../platform/src/index.js"],
1718
"@effect/platform/*": ["../../../platform/src/*.js"],
1819
"@effect/printer": ["../../../printer/src/index.js"],

packages/effect/src/Effect.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type * as Deferred from "./Deferred.js"
1212
import type * as Duration from "./Duration.js"
1313
import type * as Either from "./Either.js"
1414
import type { Equivalence } from "./Equivalence.js"
15+
import type { ExecutionPlan } from "./ExecutionPlan.js"
1516
import type { ExecutionStrategy } from "./ExecutionStrategy.js"
1617
import type * as Exit from "./Exit.js"
1718
import type * as Fiber from "./Fiber.js"
@@ -32,6 +33,7 @@ import * as effect from "./internal/core-effect.js"
3233
import * as core from "./internal/core.js"
3334
import * as defaultServices from "./internal/defaultServices.js"
3435
import * as circular from "./internal/effect/circular.js"
36+
import * as internalExecutionPlan from "./internal/executionPlan.js"
3537
import * as fiberRuntime from "./internal/fiberRuntime.js"
3638
import * as layer from "./internal/layer.js"
3739
import * as option_ from "./internal/option.js"
@@ -4398,22 +4400,33 @@ export declare namespace Retry {
43984400
export const retry: {
43994401
<E, O extends NoExcessProperties<Retry.Options<E>, O>>(
44004402
options: O
4401-
): <A, R>(
4402-
self: Effect<A, E, R>
4403-
) => Retry.Return<R, E, A, O>
4404-
<B, E, R1>(
4405-
policy: Schedule.Schedule<B, NoInfer<E>, R1>
4406-
): <A, R>(self: Effect<A, E, R>) => Effect<A, E, R1 | R>
4403+
): <A, R>(self: Effect<A, E, R>) => Retry.Return<R, E, A, O>
4404+
<B, E, R1>(policy: Schedule.Schedule<B, NoInfer<E>, R1>): <A, R>(self: Effect<A, E, R>) => Effect<A, E, R1 | R>
44074405
<A, E, R, O extends NoExcessProperties<Retry.Options<E>, O>>(
44084406
self: Effect<A, E, R>,
44094407
options: O
44104408
): Retry.Return<R, E, A, O>
4411-
<A, E, R, B, R1>(
4412-
self: Effect<A, E, R>,
4413-
policy: Schedule.Schedule<B, E, R1>
4414-
): Effect<A, E, R1 | R>
4409+
<A, E, R, B, R1>(self: Effect<A, E, R>, policy: Schedule.Schedule<B, NoInfer<E>, R1>): Effect<A, E, R1 | R>
44154410
} = schedule_.retry_combined
44164411

4412+
/**
4413+
* Apply an `ExecutionPlan` to the effect, which allows you to fallback to
4414+
* different resources in case of failure.
4415+
*
4416+
* @since 3.16.0
4417+
* @category Error handling
4418+
* @experimental
4419+
*/
4420+
export const withExecutionPlan: {
4421+
<Input, Provides, PlanE, PlanR>(
4422+
plan: ExecutionPlan<{ provides: Provides; input: Input; error: PlanE; requirements: PlanR }>
4423+
): <A, E extends Input, R>(effect: Effect<A, E, R>) => Effect<A, E | PlanE, Exclude<R, Provides> | PlanR>
4424+
<A, E extends Input, R, Provides, Input, PlanE, PlanR>(
4425+
effect: Effect<A, E, R>,
4426+
plan: ExecutionPlan<{ provides: Provides; input: Input; error: PlanE; requirements: PlanR }>
4427+
): Effect<A, E | PlanE, Exclude<R, Provides> | PlanR>
4428+
} = internalExecutionPlan.withExecutionPlan
4429+
44174430
/**
44184431
* Retries a failing effect and runs a fallback effect if retries are exhausted.
44194432
*
@@ -10348,7 +10361,7 @@ export const scheduleForked: {
1034810361
self: Effect<A, E, R>,
1034910362
schedule: Schedule.Schedule<Out, unknown, R2>
1035010363
): Effect<Fiber.RuntimeFiber<Out, E>, never, Scope.Scope | R | R2>
10351-
} = circular.scheduleForked
10364+
} = schedule_.scheduleForked
1035210365

1035310366
/**
1035410367
* Runs an effect repeatedly according to a schedule, starting from a specified

0 commit comments

Comments
 (0)