(duration: Duration.Input): Schedule<number>Returns a schedule that recurs continuously, each repetition spaced the specified duration from the last run.
When to use
Use when each delay should start after the previous action completes.
Example (Repeating with fixed spacing)
import { Console, Effect, Schedule } from "effect"
// Basic spaced schedule - runs every 2 seconds
const everyTwoSeconds = Schedule.spaced("2 seconds")
// Heartbeat that runs indefinitely with fixed spacing
const heartbeat = Effect.gen(function*() {
yield* Console.log("Heartbeat")
}).pipe(
Effect.repeat(everyTwoSeconds)
)
// Limited repeat - run only 5 times with 1-second spacing
const limitedTask = Effect.gen(function*() {
yield* Console.log("Executing scheduled task...")
yield* Effect.sleep("500 millis") // simulate work
return "Task completed"
}).pipe(
Effect.repeat(
Schedule.spaced("1 second").pipe(Schedule.upTo({ times: 5 }))
)
)
// Simple spaced schedule with limited repetitions
const limitedSpaced = Schedule.max([
Schedule.spaced("100 millis"),
Schedule.recurs(5) // at most 5 times
])
const program = Effect.gen(function*() {
yield* Console.log("Starting spaced execution...")
yield* Effect.repeat(
Effect.succeed("work item"),
limitedSpaced
)
yield* Console.log("Completed executions")
})export const const spaced: (
duration: Duration.Input
) => Schedule<number>
Returns a schedule that recurs continuously, each repetition spaced the
specified duration from the last run.
When to use
Use when each delay should start after the previous action completes.
Example (Repeating with fixed spacing)
import { Console, Effect, Schedule } from "effect"
// Basic spaced schedule - runs every 2 seconds
const everyTwoSeconds = Schedule.spaced("2 seconds")
// Heartbeat that runs indefinitely with fixed spacing
const heartbeat = Effect.gen(function*() {
yield* Console.log("Heartbeat")
}).pipe(
Effect.repeat(everyTwoSeconds)
)
// Limited repeat - run only 5 times with 1-second spacing
const limitedTask = Effect.gen(function*() {
yield* Console.log("Executing scheduled task...")
yield* Effect.sleep("500 millis") // simulate work
return "Task completed"
}).pipe(
Effect.repeat(
Schedule.spaced("1 second").pipe(Schedule.upTo({ times: 5 }))
)
)
// Simple spaced schedule with limited repetitions
const limitedSpaced = Schedule.max([
Schedule.spaced("100 millis"),
Schedule.recurs(5) // at most 5 times
])
const program = Effect.gen(function*() {
yield* Console.log("Starting spaced execution...")
yield* Effect.repeat(
Effect.succeed("work item"),
limitedSpaced
)
yield* Console.log("Completed executions")
})
spaced = (duration: Duration.Inputduration: import DurationDuration.type Duration.Input = /*unresolved*/ anyInput): 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<number> => {
const const decoded: Duration.Durationconst decoded: {
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;
}
decoded = import DurationDuration.fromInputUnsafe(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) => 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.attempt - 1, const decoded: Duration.Durationconst decoded: {
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;
}
decoded])))
}