(options: {
readonly duration?: Duration.Input | undefined
readonly times?: number | undefined
}): <Output, Input, Error, Env>(
self: Schedule<Output, Input, Error, Env>
) => Schedule<Output, Input, Error, Env>
<Output, Input, Error, Env>(
self: Schedule<Output, Input, Error, Env>,
options: {
readonly duration?: Duration.Input | undefined
readonly times?: number | undefined
}
): Schedule<Output, Input, Error, Env>Returns a new Schedule that limits an existing schedule by elapsed
duration, number of outputs, or both.
When to use
Use to bound an existing schedule while preserving its output and delay
behavior. When both duration and times are specified, the schedule
stops as soon as either limit is reached.
Gotchas
The times option limits schedule outputs. When used with repeat or retry,
the effect is evaluated once before the schedule is stepped, so the total
number of evaluations can be one greater than the configured number of
outputs.
The duration option is based on the elapsed time observed by the schedule
step. Long-running effects can cause the duration limit to be detected on the
following schedule step.
Example (Limiting by duration and recurrence count)
import { Console, Data, Effect, Schedule } from "effect"
class RetryAttemptError extends Data.TaggedError("RetryAttemptError")<{ readonly message: string }> {}
// Limit an infinite schedule to five recurrences
const limitedHeartbeat = Schedule.spaced("1 second").pipe(
Schedule.upTo({ times: 5 })
)
const heartbeatProgram = Effect.gen(function*() {
yield* Effect.repeat(
Effect.gen(function*() {
yield* Console.log("Heartbeat")
return "pulse"
}),
limitedHeartbeat
)
yield* Console.log("Heartbeat sequence completed")
})
// Limit retry attempts by both count and elapsed time
const limitedRetry = Schedule.exponential("100 millis").pipe(
Schedule.upTo({
duration: "5 seconds",
times: 3
})
)
const retryProgram = Effect.gen(function*() {
let attempt = 0
const result = yield* Effect.retry(
Effect.gen(function*() {
attempt++
yield* Console.log(`Attempt ${attempt}`)
if (attempt < 5) { // Will fail more than 3 times
return yield* Effect.fail(new RetryAttemptError({ message: `Attempt ${attempt} failed` }))
}
return `Success on attempt ${attempt}`
}),
limitedRetry
)
yield* Console.log(`Result: ${result}`)
}).pipe(
Effect.catch((error: unknown) =>
Console.log(`Failed after limited retries: ${String(error)}`)
)
)
// Empty options leave the schedule unchanged
const unchanged = Schedule.fixed("500 millis").pipe(
Schedule.upTo({})
)export const const upTo: {
(options: {
readonly duration?: Duration.Input | undefined
readonly times?: number | undefined
}): <Output, Input, Error, Env>(
self: Schedule<Output, Input, Error, Env>
) => Schedule<Output, Input, Error, Env>
<Output, Input, Error, Env>(
self: Schedule<Output, Input, Error, Env>,
options: {
readonly duration?:
| Duration.Input
| undefined
readonly times?: number | undefined
}
): Schedule<Output, Input, Error, Env>
}
Returns a new Schedule that limits an existing schedule by elapsed
duration, number of outputs, or both.
When to use
Use to bound an existing schedule while preserving its output and delay
behavior. When both duration and times are specified, the schedule
stops as soon as either limit is reached.
Gotchas
The times option limits schedule outputs. When used with repeat or retry,
the effect is evaluated once before the schedule is stepped, so the total
number of evaluations can be one greater than the configured number of
outputs.
The duration option is based on the elapsed time observed by the schedule
step. Long-running effects can cause the duration limit to be detected on the
following schedule step.
Example (Limiting by duration and recurrence count)
import { Console, Data, Effect, Schedule } from "effect"
class RetryAttemptError extends Data.TaggedError("RetryAttemptError")<{ readonly message: string }> {}
// Limit an infinite schedule to five recurrences
const limitedHeartbeat = Schedule.spaced("1 second").pipe(
Schedule.upTo({ times: 5 })
)
const heartbeatProgram = Effect.gen(function*() {
yield* Effect.repeat(
Effect.gen(function*() {
yield* Console.log("Heartbeat")
return "pulse"
}),
limitedHeartbeat
)
yield* Console.log("Heartbeat sequence completed")
})
// Limit retry attempts by both count and elapsed time
const limitedRetry = Schedule.exponential("100 millis").pipe(
Schedule.upTo({
duration: "5 seconds",
times: 3
})
)
const retryProgram = Effect.gen(function*() {
let attempt = 0
const result = yield* Effect.retry(
Effect.gen(function*() {
attempt++
yield* Console.log(`Attempt ${attempt}`)
if (attempt < 5) { // Will fail more than 3 times
return yield* Effect.fail(new RetryAttemptError({ message: `Attempt ${attempt} failed` }))
}
return `Success on attempt ${attempt}`
}),
limitedRetry
)
yield* Console.log(`Result: ${result}`)
}).pipe(
Effect.catch((error: unknown) =>
Console.log(`Failed after limited retries: ${String(error)}`)
)
)
// Empty options leave the schedule unchanged
const unchanged = Schedule.fixed("500 millis").pipe(
Schedule.upTo({})
)
upTo: {
(options: {
readonly duration?: Duration.Input | undefined
readonly times?: number | undefined
}
options: {
readonly duration?: Duration.Input | undefinedduration?: 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 | undefined
readonly times?: number | undefinedtimes?: number | undefined
}): <function (type parameter) Output in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>): Schedule<Output, Input, Error, Env>Output, function (type parameter) Input in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>): Schedule<Output, Input, Error, Env>Input, function (type parameter) Error in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>): Schedule<Output, Input, Error, Env>Error, function (type parameter) Env in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>): Schedule<Output, Input, Error, Env>Env>(
self: Schedule<Output, Input, Error, Env>(parameter) self: {
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; <…;
}
self: 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<function (type parameter) Output in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>): Schedule<Output, Input, Error, Env>Output, function (type parameter) Input in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>): Schedule<Output, Input, Error, Env>Input, function (type parameter) Error in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>): Schedule<Output, Input, Error, Env>Error, function (type parameter) Env in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>): Schedule<Output, Input, Error, Env>Env>
) => 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<function (type parameter) Output in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>): Schedule<Output, Input, Error, Env>Output, function (type parameter) Input in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>): Schedule<Output, Input, Error, Env>Input, function (type parameter) Error in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>): Schedule<Output, Input, Error, Env>Error, function (type parameter) Env in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>): Schedule<Output, Input, Error, Env>Env>
<function (type parameter) Output in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Output, function (type parameter) Input in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Input, function (type parameter) Error in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Error, function (type parameter) Env in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Env>(
self: Schedule<Output, Input, Error, Env>(parameter) self: {
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; <…;
}
self: 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<function (type parameter) Output in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Output, function (type parameter) Input in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Input, function (type parameter) Error in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Error, function (type parameter) Env in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Env>,
options: {
readonly duration?: Duration.Input | undefined
readonly times?: number | undefined
}
options: {
readonly duration?: Duration.Input | undefinedduration?: 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 | undefined
readonly times?: number | undefinedtimes?: number | undefined
}
): 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<function (type parameter) Output in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Output, function (type parameter) Input in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Input, function (type parameter) Error in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Error, function (type parameter) Env in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Env>
} = dual<(...args: Array<any>) => any, <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}) => Schedule<Output, Input, Error, Env>>(arity: 2, body: <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}) => Schedule<Output, Input, Error, Env>): ((...args: Array<any>) => any) & (<Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}) => Schedule<Output, Input, Error, Env>) (+1 overload)
Creates a function that can be called in data-first style or data-last
(pipe-friendly) style.
When to use
Use to expose one implementation through both direct and pipe-friendly
call styles.
Details
Pass either the arity of the uncurried function or a predicate that decides
whether the current call is data-first. Arity is the common case. Use a
predicate when optional arguments make arity ambiguous.
Example (Selecting data-first or data-last style by arity)
import { Function, pipe } from "effect"
const sum = Function.dual<
(that: number) => (self: number) => number,
(self: number, that: number) => number
>(2, (self, that) => self + that)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
Example (Defining overloads with call signatures)
import { Function, pipe } from "effect"
const sum: {
(that: number): (self: number) => number
(self: number, that: number): number
} = Function.dual(2, (self: number, that: number): number => self + that)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
Example (Selecting data-first or data-last style with a predicate)
import { Function, pipe } from "effect"
const sum = Function.dual<
(that: number) => (self: number) => number,
(self: number, that: number) => number
>(
(args) => args.length === 2,
(self, that) => self + that
)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
dual(2, <function (type parameter) Output in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Output, function (type parameter) Input in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Input, function (type parameter) Error in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Error, function (type parameter) Env in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Env>(
self: Schedule<Output, Input, Error, Env>(parameter) self: {
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; <…;
}
self: 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<function (type parameter) Output in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Output, function (type parameter) Input in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Input, function (type parameter) Error in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Error, function (type parameter) Env in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Env>,
options: {
readonly duration?: Duration.Input | undefined
readonly times?: number | undefined
}
options: {
readonly duration?: Duration.Input | undefinedduration?: 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 | undefined
readonly times?: number | undefinedtimes?: number | undefined
}
): 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<function (type parameter) Output in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Output, function (type parameter) Input in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Input, function (type parameter) Error in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Error, function (type parameter) Env in <Output, Input, Error, Env>(self: Schedule<Output, Input, Error, Env>, options: {
readonly duration?: Duration.Input | undefined;
readonly times?: number | undefined;
}): Schedule<Output, Input, Error, Env>
Env> => {
const const duration:
| Duration.Duration
| undefined
duration = options: {
readonly duration?: Duration.Input | undefined
readonly times?: number | undefined
}
options.duration?: Duration.Input | undefinedduration === var undefinedundefined ? var undefinedundefined : import DurationDuration.const fromInputUnsafe: (
input: Input
) => Duration
Decodes a Duration.Input into a Duration.
When to use
Use when the input has already been validated or comes from a trusted source
and throwing is acceptable for invalid duration syntax.
Gotchas
If the input is not a valid Duration.Input, it throws an error.
Example (Decoding duration inputs)
import { Duration } from "effect"
const duration1 = Duration.fromInputUnsafe(1000) // 1000 milliseconds
const duration2 = Duration.fromInputUnsafe("5 seconds")
const duration3 = Duration.fromInputUnsafe("Infinity")
const duration4 = Duration.fromInputUnsafe([2, 500_000_000]) // 2 seconds and 500ms
fromInputUnsafe(options: {
readonly duration?: Duration.Input | undefined
readonly times?: number | undefined
}
options.duration?: Duration.Input | undefinedduration)
return const while_: {
<Input, Output, Error2 = never, Env2 = never>(
predicate: (
metadata: Metadata<Output, Input>
) => boolean | Effect<boolean, Error2, Env2>
): <Error, Env>(
self: Schedule<Output, Input, Error, Env>
) => Schedule<
Output,
Input,
Error | Error2,
Env | Env2
>
<
Output,
Input,
Error,
Env,
Error2 = never,
Env2 = never
>(
self: Schedule<Output, Input, Error, Env>,
predicate: (
metadata: Metadata<Output, Input>
) => boolean | Effect<boolean, Error2, Env2>
): Schedule<
Output,
Input,
Error | Error2,
Env | Env2
>
}
while_(self: Schedule<Output, Input, Error, Env>(parameter) self: {
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; <…;
}
self, ({ attempt: numberattempt, elapsed: numberelapsed }) =>
import effecteffect.const succeed: <A>(
value: A
) => Effect.Effect<A>
succeed(
(options: {
readonly duration?: Duration.Input | undefined
readonly times?: number | undefined
}
options.times?: number | undefinedtimes === var undefinedundefined || attempt: numberattempt <= options: {
readonly duration?: Duration.Input | undefined
readonly times?: number | undefined
}
options.times?: numbertimes) &&
(const duration:
| Duration.Duration
| undefined
duration === var undefinedundefined || import DurationDuration.const isLessThanOrEqualTo: {
(that: Duration): (self: Duration) => boolean
(self: Duration, that: Duration): boolean
}
isLessThanOrEqualTo(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(elapsed: numberelapsed), const duration: Duration.Durationconst duration: {
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;
}
duration))
))
})