(duration: Duration.Input): Schedule<Duration.Duration>Returns a new Schedule that will always recur, but only during the
specified duration of time.
When to use
Use to bound a repeating or retrying schedule by elapsed time.
Example (Repeating work during a duration)
import { Console, Data, Effect, Schedule } from "effect"
class RetryAttemptError extends Data.TaggedError("RetryAttemptError")<{ readonly message: string }> {}
// Run a task for exactly 5 seconds, regardless of how many iterations
const fiveSecondSchedule = Schedule.during("5 seconds")
const timedProgram = Effect.gen(function*() {
yield* Effect.repeat(
Effect.gen(function*() {
yield* Console.log("Task executed inside the time window")
yield* Effect.sleep("500 millis") // Each task takes 500ms
return "task done"
}),
fiveSecondSchedule.pipe(
Schedule.tap(({ output: elapsedDuration }) =>
Console.log(`Total elapsed: ${elapsedDuration}`)
)
)
)
yield* Console.log("Time limit reached!")
})
// Combine with other schedules for time-bounded execution
const timeAndCountLimited = Schedule.max([
Schedule.spaced("1 second"),
Schedule.during("10 seconds"), // Stop after 10 seconds OR
Schedule.recurs(15) // 15 attempts, whichever comes first
])
// Burst execution within time window
const burstWindow = Schedule.during("3 seconds")
const burstProgram = Effect.gen(function*() {
yield* Console.log("Starting burst execution...")
yield* Effect.repeat(
Effect.gen(function*() {
yield* Console.log("Burst task")
return "burst"
}),
burstWindow
)
yield* Console.log("Burst window completed")
})
// Timed retry window - retry for up to 30 seconds
const timedRetry = Schedule.max([
Schedule.exponential("200 millis"),
Schedule.during("30 seconds")
])
const retryProgram = Effect.gen(function*() {
let attempt = 0
const result = yield* Effect.retry(
Effect.gen(function*() {
attempt++
yield* Console.log(`Retry attempt ${attempt}`)
if (attempt < 4) {
return yield* Effect.fail(new RetryAttemptError({ message: `Attempt ${attempt} failed` }))
}
return `Success on attempt ${attempt}`
}),
timedRetry
)
yield* Console.log(`Result: ${result}`)
}).pipe(
Effect.catch((error: unknown) => Console.log(`Timed out: ${String(error)}`))
)export const const during: (
duration: Duration.Input
) => Schedule<Duration.Duration>
Returns a new Schedule that will always recur, but only during the
specified duration of time.
When to use
Use to bound a repeating or retrying schedule by elapsed time.
Example (Repeating work during a duration)
import { Console, Data, Effect, Schedule } from "effect"
class RetryAttemptError extends Data.TaggedError("RetryAttemptError")<{ readonly message: string }> {}
// Run a task for exactly 5 seconds, regardless of how many iterations
const fiveSecondSchedule = Schedule.during("5 seconds")
const timedProgram = Effect.gen(function*() {
yield* Effect.repeat(
Effect.gen(function*() {
yield* Console.log("Task executed inside the time window")
yield* Effect.sleep("500 millis") // Each task takes 500ms
return "task done"
}),
fiveSecondSchedule.pipe(
Schedule.tap(({ output: elapsedDuration }) =>
Console.log(`Total elapsed: ${elapsedDuration}`)
)
)
)
yield* Console.log("Time limit reached!")
})
// Combine with other schedules for time-bounded execution
const timeAndCountLimited = Schedule.max([
Schedule.spaced("1 second"),
Schedule.during("10 seconds"), // Stop after 10 seconds OR
Schedule.recurs(15) // 15 attempts, whichever comes first
])
// Burst execution within time window
const burstWindow = Schedule.during("3 seconds")
const burstProgram = Effect.gen(function*() {
yield* Console.log("Starting burst execution...")
yield* Effect.repeat(
Effect.gen(function*() {
yield* Console.log("Burst task")
return "burst"
}),
burstWindow
)
yield* Console.log("Burst window completed")
})
// Timed retry window - retry for up to 30 seconds
const timedRetry = Schedule.max([
Schedule.exponential("200 millis"),
Schedule.during("30 seconds")
])
const retryProgram = Effect.gen(function*() {
let attempt = 0
const result = yield* Effect.retry(
Effect.gen(function*() {
attempt++
yield* Console.log(`Retry attempt ${attempt}`)
if (attempt < 4) {
return yield* Effect.fail(new RetryAttemptError({ message: `Attempt ${attempt} failed` }))
}
return `Success on attempt ${attempt}`
}),
timedRetry
)
yield* Console.log(`Result: ${result}`)
}).pipe(
Effect.catch((error: unknown) => Console.log(`Timed out: ${String(error)}`))
)
during = (duration: Duration.Inputduration: import DurationDuration.type Input =
| number
| bigint
| Duration.Duration
| readonly [seconds: number, nanos: number]
| `${number} nano`
| `${number} nanos`
| `${number} micro`
| `${number} micros`
| `${number} milli`
| `${number} millis`
| `${number} second`
| `${number} seconds`
| `${number} minute`
| `${number} minutes`
| `${number} hour`
| `${number} hours`
| `${number} day`
| `${number} days`
| `${number} week`
| `${number} weeks`
| "Infinity"
| "-Infinity"
| Duration.DurationObject
Valid input types that can be converted to a Duration.
When to use
Use when an API should accept any value that Effect can convert into a
Duration, including existing durations, millisecond numbers, nanosecond
bigints, high-resolution tuples, duration strings, infinity strings, or
duration objects.
Details
String inputs accept values like "10 seconds", "500 millis",
"Infinity", and "-Infinity". Finite fractional values that are
normalized to nanoseconds are rounded to the nearest nanosecond, with ties
away from zero.
Input): interface Schedule<out Output, in Input = unknown, out Error = never, out Env = never>A Schedule defines a strategy for repeating or retrying effects based on some policy.
Example (Defining retry and repeat schedules)
import { Console, Data, Effect, Schedule } from "effect"
class NetworkError extends Data.TaggedError("NetworkError")<{
readonly attempt: number
}> {}
// Basic retry schedule - retry up to 3 times with exponential backoff
const retrySchedule = Schedule.max([
Schedule.exponential("100 millis"),
Schedule.recurs(3)
])
// Basic repeat schedule - repeat every 30 seconds forever
const repeatSchedule: Schedule.Schedule<number, unknown, never> = Schedule
.spaced("30 seconds")
const program = Effect.gen(function*() {
let attempts = 0
const result1 = yield* Effect.retry(
Effect.gen(function*() {
attempts++
if (attempts < 3) {
return yield* Effect.fail(new NetworkError({ attempt: attempts }))
}
return "Success"
}),
retrySchedule
)
console.log(result1) // "Success"
yield* Console.log("heartbeat").pipe(
Effect.repeat(repeatSchedule.pipe(Schedule.upTo({ times: 5 })))
)
})
The Schedule namespace contains types and utilities for working with schedules.
Schedule<import DurationDuration.Duration> => {
const const durationMillis: numberdurationMillis = import DurationDuration.const toMillis: (self: Input) => numberConverts a Duration to milliseconds.
Example (Converting durations to milliseconds)
import { Duration } from "effect"
console.log(Duration.toMillis(Duration.seconds(5))) // 5000
console.log(Duration.toMillis(Duration.minutes(2))) // 120000
toMillis(duration: Duration.Inputduration)
return const fromStepWithMetadata: <
Input,
Output,
EnvX,
ErrorX,
Error,
Env
>(
step: Effect<
(
options: InputMetadata<Input>
) => Pull.Pull<
[Output, Duration.Duration],
ErrorX,
Output,
EnvX
>,
Error,
Env
>
) => Schedule<
Output,
Input,
Error | Pull.ExcludeDone<ErrorX>,
Env | EnvX
>
Creates a Schedule from a step function that receives metadata about the schedule's execution.
Example (Creating a metadata-aware schedule)
import { Cause, Duration, Effect, Schedule } from "effect"
const firstThreeInputs = Schedule.fromStepWithMetadata(Effect.succeed((metadata: Schedule.InputMetadata<string>) => {
if (metadata.attempt > 3) {
return Cause.done("finished")
}
return Effect.succeed([
`attempt ${metadata.attempt}: ${metadata.input}`,
Duration.millis(250)
] as [string, Duration.Duration])
}))
fromStepWithMetadata(
import effecteffect.const succeed: <A>(
value: A
) => Effect.Effect<A>
succeed((meta: InputMetadata<unknown>(parameter) meta: {
input: Input;
attempt: number;
start: number;
now: number;
elapsed: number;
elapsedSincePrevious: number;
}
meta) => {
const const elapsed: Duration.Durationconst elapsed: {
value: DurationValue;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
elapsed = import DurationDuration.const millis: (millis: number) => DurationCreates a Duration from milliseconds.
Example (Creating durations from milliseconds)
import { Duration } from "effect"
const duration = Duration.millis(1000)
console.log(Duration.toMillis(duration)) // 1000
millis(meta: InputMetadata<unknown>(parameter) meta: {
input: Input;
attempt: number;
start: number;
now: number;
elapsed: number;
elapsedSincePrevious: number;
}
meta.InputMetadata<Input>.elapsed: numberelapsed)
return meta: InputMetadata<unknown>(parameter) meta: {
input: Input;
attempt: number;
start: number;
now: number;
elapsed: number;
elapsedSincePrevious: number;
}
meta.InputMetadata<Input>.elapsed: numberelapsed > const durationMillis: numberdurationMillis
? import effecteffect.const succeed: <A>(
value: A
) => Effect.Effect<A>
succeed([const elapsed: Duration.Durationconst elapsed: {
value: DurationValue;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
elapsed, import DurationDuration.const zero: Durationconst zero: {
value: DurationValue;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
A Duration representing zero time.
Example (Referencing the zero duration)
import { Duration } from "effect"
console.log(Duration.toMillis(Duration.zero)) // 0
zero])
: import CauseCause.const done: <A = void>(
value?: A
) => Effect.Effect<never, Done<A>>
Creates an Effect that fails with a Done error. Shorthand for
Effect.fail(Cause.Done(value)).
When to use
Use when you model stream or queue completion through the error channel.
Example (Failing with Done)
import { Cause, Effect } from "effect"
const program = Cause.done("finished")
Effect.runPromiseExit(program).then((exit) => {
console.log(exit._tag) // "Failure"
})
done(const elapsed: Duration.Durationconst elapsed: {
value: DurationValue;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
elapsed)
})
)
}