Skip to content

Latest commit

 

History

History
150 lines (117 loc) · 3.68 KB

File metadata and controls

150 lines (117 loc) · 3.68 KB
title Your First Schedule
id scheduling-hello-world
skillLevel beginner
applicationPatternId scheduling
summary Learn the basics of scheduling in Effect - retry operations and repeat them on intervals.
tags
scheduling
retry
repeat
getting-started
rule
description
Use Schedule to control when and how often effects run.
author PaulJPhilp
related
scheduling-repeat-interval
scheduling-exponential-backoff
lessonOrder 2

Guideline

Use Schedule to control timing in Effect programs - retrying failed operations, repeating successful ones, or adding delays.


Rationale

Schedules solve common timing problems:

  1. Retries - Try again after failures
  2. Polling - Check for updates periodically
  3. Rate limiting - Control how fast things run
  4. Backoff - Increase delays between attempts

Good Example

import { Effect, Schedule } from "effect"

// ============================================
// 1. Retry a failing operation
// ============================================

let attempts = 0
const flakyOperation = Effect.gen(function* () {
  attempts++
  if (attempts < 3) {
    yield* Effect.log(`Attempt ${attempts} failed`)
    return yield* Effect.fail(new Error("Temporary failure"))
  }
  return `Success on attempt ${attempts}`
})

// Retry up to 5 times
const withRetry = flakyOperation.pipe(
  Effect.retry(Schedule.recurs(5))
)

// ============================================
// 2. Repeat a successful operation
// ============================================

const logTime = Effect.gen(function* () {
  const now = new Date().toISOString()
  yield* Effect.log(`Current time: ${now}`)
  return now
})

// Repeat 3 times
const repeated = logTime.pipe(
  Effect.repeat(Schedule.recurs(3))
)

// ============================================
// 3. Add delays between operations
// ============================================

// Repeat every second, 5 times
const polling = logTime.pipe(
  Effect.repeat(
    Schedule.spaced("1 second").pipe(
      Schedule.intersect(Schedule.recurs(5))
    )
  )
)

// ============================================
// 4. Common schedule patterns
// ============================================

// Fixed delay between attempts
const fixedDelay = Schedule.spaced("500 millis")

// Increasing delay (1s, 2s, 4s, 8s...)
const exponentialBackoff = Schedule.exponential("1 second")

// Maximum number of attempts
const limitedAttempts = Schedule.recurs(3)

// Combine: exponential backoff, max 5 attempts
const retryPolicy = Schedule.exponential("100 millis").pipe(
  Schedule.intersect(Schedule.recurs(5))
)

// ============================================
// 5. Run examples
// ============================================

const program = Effect.gen(function* () {
  yield* Effect.log("--- Retry Example ---")
  const result = yield* withRetry
  yield* Effect.log(`Result: ${result}`)

  yield* Effect.log("\n--- Repeat Example ---")
  yield* repeated
})

Effect.runPromise(program)

Common Schedules

Schedule What It Does
Schedule.recurs(n) Run at most n times
Schedule.spaced(duration) Wait duration between runs
Schedule.exponential(base) Double the delay each time
Schedule.forever Run indefinitely
Schedule.once Run exactly once

Combining Schedules

Combinator Meaning
intersect Both conditions must be true
union Either condition can be true
andThen First schedule, then second

When to Use

  • Retries - Network requests, database connections
  • Polling - Check for job completion
  • Rate limiting - API call quotas
  • Periodic tasks - Health checks, cache refresh