Hyperlinkv0.8.0-beta.28

Schedule

Schedule.cronconsteffect/Schedule.ts:969
(expression: Cron.Cron): Schedule<
  Duration.Duration,
  unknown,
  Cron.CronParseError
>
(expression: string, tz?: string | DateTime.TimeZone): Schedule<
  Duration.Duration,
  unknown,
  Cron.CronParseError
>

Returns a new Schedule that recurs on the specified Cron schedule and outputs the duration between recurrences.

Example (Scheduling work with cron expressions)

import { Console, Data, Effect, Schedule } from "effect"

class ScheduledTaskError extends Data.TaggedError("ScheduledTaskError")<{ readonly message: string }> {}

// Run every minute
const everyMinute = Schedule.cron("* * * * *")

const minutelyProgram = Effect.gen(function*() {
  yield* Effect.repeat(
    Effect.gen(function*() {
      yield* Console.log("Running minutely task")
      return "minute"
    }),
    everyMinute.pipe(
      Schedule.upTo({ times: 3 }), // Run only 3 times for demo
      Schedule.tap(({ output: duration }) =>
        Console.log(`Next execution in: ${duration}`)
      )
    )
  )
})

// Run every day at 2:30 AM
const dailyBackup = Schedule.cron("30 2 * * *")

const backupProgram = Effect.gen(function*() {
  yield* Effect.repeat(
    Effect.gen(function*() {
      yield* Console.log("Running daily backup...")
      // Simulate backup process
      yield* Effect.sleep("2 seconds")
      yield* Console.log("Backup completed")
      return "backup-done"
    }),
    dailyBackup.pipe(
      Schedule.upTo({ times: 2 }) // Run 2 times for demo
    )
  )
})

// Run every Monday at 9:00 AM with timezone
const weeklyReport = Schedule.cron("0 9 * * 1", "America/New_York")

const reportProgram = Effect.gen(function*() {
  yield* Effect.repeat(
    Effect.gen(function*() {
      yield* Console.log("Generating weekly report...")
      const report = {
        week: 42,
        status: "ready" as const
      }
      yield* Console.log(`Report generated: ${JSON.stringify(report)}`)
      return report
    }),
    weeklyReport.pipe(Schedule.upTo({ times: 1 }))
  )
})

// Run every 15 minutes during business hours (9 AM - 5 PM)
const businessHoursCheck = Schedule.cron("0,15,30,45 9-17 * * 1-5")

const businessProgram = Effect.gen(function*() {
  const statuses = ["healthy", "healthy", "degraded", "healthy"] as const
  let index = 0

  yield* Effect.repeat(
    Effect.gen(function*() {
      yield* Console.log("Business hours health check...")
      const status = statuses[index++]
      yield* Console.log(`System status: ${status}`)
      return status
    }),
    businessHoursCheck.pipe(
      Schedule.upTo({ times: 4 }) // Demo with 4 checks
    )
  )
})

// Run on specific days of the month
const monthlyInvoice = Schedule.cron("0 10 1,15 * *") // 1st and 15th at 10 AM

const invoiceProgram = Effect.gen(function*() {
  yield* Effect.repeat(
    Effect.gen(function*() {
      yield* Console.log("Processing monthly invoices...")
      const invoiceCount = 72
      yield* Console.log(`Processed ${invoiceCount} invoices`)
      return { count: invoiceCount, batch: "2024-01-a" }
    }),
    monthlyInvoice.pipe(Schedule.upTo({ times: 1 }))
  )
})

// Complex cron with error handling
const complexCron = Schedule.cron("0 2,4,6 * * *").pipe(
  Schedule.tap(({ output: duration }) =>
    Console.log(`Scheduled to run again in ${duration}`)
  )
)

const robustProgram = Effect.gen(function*() {
  let attempt = 0

  yield* Effect.repeat(
    Effect.gen(function*() {
      attempt++
      yield* Console.log("Complex scheduled task...")
      if (attempt === 1) {
        return yield* Effect.fail(new ScheduledTaskError({ message: "Scheduled task failed" }))
      }
      return "success"
    }),
    complexCron.pipe(Schedule.upTo({ times: 3 }))
  ).pipe(
    Effect.catch((error: unknown) =>
      Console.log(`Cron task error: ${String(error)}`)
    )
  )
})
constructors
Source effect/Schedule.ts:96916 lines
export const cron: {
  (expression: Cron.Cron): Schedule<Duration.Duration, unknown, Cron.CronParseError>
  (expression: string, tz?: string | DateTime.TimeZone): Schedule<Duration.Duration, unknown, Cron.CronParseError>
} = (expression: string | Cron.Cron, tz?: string | DateTime.TimeZone) => {
  const parsed = Cron.isCron(expression) ? Result.succeed(expression) : Cron.parse(expression, tz)
  return fromStep(effect.map(effect.fromResult(parsed), (cron) => (now, _) => {
    if (now === Number.POSITIVE_INFINITY) {
      return Cause.done(Duration.zero)
    }
    return effect.sync(() => {
      const next = Cron.next(cron, now).getTime()
      const duration = Duration.millis(next - now)
      return [duration, duration]
    })
  }))
}