Built-in Schedules

On this page

To demonstrate the functionality of different schedules, we will be working with the following helper:

Delay.ts
ts
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
})
Delay.ts
ts
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.

ts
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
...
*/
ts
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.

ts
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
*/
ts
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.

ts
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
*/
ts
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.

ts
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
...
*/
ts
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.

ts
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
...
*/
ts
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

ts
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
...
*/
ts
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.

ts
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
...
*/
ts
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
...
*/