Built-in Schedules
To demonstrate the functionality of different schedules, we will be working with the following helper:
import { Effect } from "effect"
let start = new Date().getTime()
export const log = Effect.sync(() => {
const now = new Date().getTime()
console.log(`delay: ${now - start}`)
start = now
})
The log
helper logs the time delay between each execution. We will use this helper to showcase the behavior of various built-in schedules.
forever
A schedule that always recurs and produces number of recurrence at each run.
import { Effect, Schedule } from "effect"
import * as Delay from "./Delay"
const schedule = Schedule.forever
Effect.runPromise(Effect.repeat(Delay.log, schedule))
/*
Output:
delay: 3
delay: 7 < forever
delay: 5
delay: 1
delay: 1
delay: 1
delay: 1
delay: 1
...
*/
once
A schedule that recurs one time.
import { Effect, Schedule } from "effect"
import * as Delay from "./Delay"
const schedule = Schedule.once
Effect.runPromise(Effect.repeat(Delay.log, schedule))
/*
Output:
delay: 3
delay: 8 < once
*/
recurs
A schedule that only recurs the specified number of times.
import { Effect, Schedule } from "effect"
import * as Delay from "./Delay"
const schedule = Schedule.recurs(5)
Effect.runPromise(Effect.repeat(Delay.log, schedule))
/*
Output:
delay: 5
delay: 8 < recurs
delay: 6
delay: 2
delay: 1
delay: 1
*/
Recurring at specific intervals
In the context of scheduling, two commonly used schedules are spaced
and fixed
. While they both involve recurring at specific intervals, they have a fundamental difference in how they determine the timing of repetitions.
The spaced
schedule creates a recurring pattern where each repetition is spaced apart by a specified duration. This means that there is a delay between the completion of one repetition and the start of the next. The duration between repetitions remains constant, providing a consistent spacing pattern.
On the other hand, the fixed
schedule recurs on a fixed interval, regardless of the duration of the actions or the completion time of previous repetitions. It operates independently of the execution time, ensuring a regular recurrence at the specified interval.
spaced
A schedule that recurs continuously, each repetition spaced the specified duration from the last run.
import { Effect, Schedule } from "effect"
import * as Delay from "./Delay"
const schedule = Schedule.spaced("200 millis")
const action = Effect.delay(Delay.log, "100 millis")
Effect.runPromise(Effect.repeat(action, schedule))
/*
Output:
delay: 109
delay: 316 < spaced
delay: 302
delay: 306
delay: 306
...
*/
The first delay is approximately 100 milliseconds, as the initial execution is not affected by the schedule. Subsequent delays are approximately 200 milliseconds apart, demonstrating the effect of the spaced
schedule.
fixed
A schedule that recurs on a fixed interval. Returns the number of repetitions of the schedule so far.
import { Effect, Schedule } from "effect"
import * as Delay from "./Delay"
const schedule = Schedule.fixed("200 millis")
const action = Effect.delay(Delay.log, "100 millis")
Effect.runPromise(Effect.repeat(action, schedule))
/*
Output:
delay: 109
delay: 316 < fixed
delay: 202
delay: 202
delay: 203
...
*/
The first delay is approximately 100 milliseconds, as the initial execution is not affected by the schedule. Subsequent delays are consistently around 200 milliseconds apart, demonstrating the effect of the fixed
schedule.
exponential
A schedule that recurs using exponential backoff
import { Effect, Schedule } from "effect"
import * as Delay from "./Delay"
const schedule = Schedule.exponential("10 millis")
Effect.runPromise(Effect.repeat(Delay.log, schedule))
/*
Output:
delay: 4
delay: 17 < exponential
delay: 21
delay: 40
delay: 85
delay: 168
delay: 324
delay: 644
delay: 1287
...
*/
fibonacci
A schedule that always recurs, increasing delays by summing the preceding two delays (similar to the fibonacci sequence). Returns the current duration between recurrences.
import { Effect, Schedule } from "effect"
import * as Delay from "./Delay"
const schedule = Schedule.fibonacci("10 millis")
Effect.runPromise(Effect.repeat(Delay.log, schedule))
/*
Output:
delay: 3
delay: 17 < fibonacci
delay: 11
delay: 23
delay: 32
delay: 52
delay: 84
delay: 132
delay: 212
delay: 342
delay: 556
delay: 892
...
*/