scheduling

This skill should be used when the user asks about "Effect Schedule", "retry schedules", "repetition", "Schedule.exponential", "Schedule.spaced", "Schedule.recurs", "cron scheduling", "backoff strategy", "schedule combinators", "Effect.repeat", "Effect.retry", "polling", or needs to understand how Effect handles scheduled operations and retry policies.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "scheduling" with this command: npx skills add andrueandersoncs/claude-skill-effect-ts/andrueandersoncs-claude-skill-effect-ts-scheduling

Scheduling in Effect

Overview

Effect's Schedule type describes patterns for:

  • Retrying failed operations
  • Repeating successful operations
  • Polling at intervals
  • Backoff strategies for resilience
Schedule<Out, In, Requirements>;
//       ^^^  ^^ Output and input types

Built-In Schedules

Fixed Intervals

import { Schedule } from "effect";

const everySecond = Schedule.spaced("1 second");

const fixed = Schedule.fixed("500 millis");

Recurrence Limits

const fiveTimes = Schedule.recurs(5);

const once = Schedule.once;

const forever = Schedule.forever;

Exponential Backoff

const exponential = Schedule.exponential("100 millis");

const capped = Schedule.exponential("100 millis").pipe(Schedule.upTo("30 seconds"));

const jittered = Schedule.exponential("100 millis").pipe(Schedule.jittered);

Time-Based Limits

const forOneMinute = Schedule.spaced("1 second").pipe(Schedule.upTo("1 minute"));

const untilSuccess = Schedule.recurWhile((result) => result.status === "pending");

Using Schedules

Effect.retry - Retry on Failure

const resilientFetch = fetchData().pipe(
  Effect.retry(Schedule.exponential("1 second").pipe(Schedule.compose(Schedule.recurs(5)))),
);

Effect.repeat - Repeat on Success

const polling = checkStatus().pipe(Effect.repeat(Schedule.spaced("5 seconds")));

Effect.schedule - Full Control

const scheduled = effect.pipe(Effect.schedule(mySchedule));

Schedule Combinators

Composing Schedules

const exponentialWithLimit = Schedule.exponential("1 second").pipe(Schedule.compose(Schedule.recurs(10)));

const eitherSchedule = Schedule.union(Schedule.spaced("1 second"), Schedule.recurs(5));

Adding Jitter

const jittered = Schedule.exponential("1 second").pipe(Schedule.jittered);

const customJitter = Schedule.exponential("1 second").pipe(Schedule.jittered({ min: 0.8, max: 1.2 }));

Delaying First Execution

const delayed = Schedule.spaced("1 second").pipe(Schedule.delayed(() => "5 seconds"));

Resetting Schedule

const resetting = Schedule.exponential("1 second").pipe(Schedule.resetAfter("1 minute"));

Conditional Retrying

Retry While Condition

// Use Match.tag for error type checking in predicates
const retryTransient = effect.pipe(
  Effect.retry({
    schedule: Schedule.exponential("1 second"),
    while: (error) =>
      Match.value(error).pipe(
        Match.tag("TransientError", () => true),
        Match.orElse(() => false),
      ),
  }),
);

Retry Until Condition

const retryUntilFatal = effect.pipe(
  Effect.retry({
    schedule: Schedule.recurs(10),
    until: (error) =>
      Match.value(error).pipe(
        Match.tag("FatalError", () => true),
        Match.orElse(() => false),
      ),
  }),
);

Cron Scheduling

import { Cron } from "effect";

const daily = Cron.parse("0 0 * * *");

const hourly = Cron.parse("0 * * * *");

const cronSchedule = Schedule.cron(daily);

Schedule Outputs

Schedules can produce values:

const withElapsed = Schedule.elapsed;

const withCount = Schedule.count;

const collecting = Schedule.collectAll<number>();

Using Schedule Output

const [result, elapsed] =
  yield * effect.pipe(Effect.retry(Schedule.exponential("1 second").pipe(Schedule.compose(Schedule.elapsed))));
console.log(`Took ${elapsed}ms after retries`);

Common Patterns

API Retry with Backoff

const apiCall = fetchFromApi().pipe(
  Effect.retry(
    Schedule.exponential("500 millis").pipe(
      Schedule.jittered,
      Schedule.compose(Schedule.recurs(5)),
      Schedule.upTo("30 seconds"),
    ),
  ),
);

Polling with Timeout

const poll = checkJobStatus(jobId).pipe(
  Effect.repeat(Schedule.spaced("2 seconds").pipe(Schedule.upTo("5 minutes"))),
  Effect.timeout("5 minutes"),
);

Circuit Breaker Pattern

const circuitBreaker = (effect: Effect.Effect<A, E>) => {
  let failures = 0;
  const maxFailures = 5;
  const resetTimeout = "30 seconds";

  return effect.pipe(
    Effect.retry(
      Schedule.exponential("1 second").pipe(
        Schedule.compose(Schedule.recurs(3)),
        Schedule.tapOutput(() =>
          Effect.sync(() => {
            failures++;
          }),
        ),
      ),
    ),
  );
};

Retry with Logging

const retryWithLogs = effect.pipe(
  Effect.retry(
    Schedule.exponential("1 second").pipe(
      Schedule.compose(Schedule.recurs(5)),
      Schedule.tapInput((error) => Effect.log(`Retrying after error: ${error}`)),
    ),
  ),
);

Schedule Reference

SchedulePattern
Schedule.foreverNever stops
Schedule.onceSingle execution
Schedule.recurs(n)Exactly n times
Schedule.spaced(d)Fixed delay d
Schedule.fixed(d)Fixed interval from start
Schedule.exponential(d)d, 2d, 4d, 8d...
Schedule.fibonacci(d)d, d, 2d, 3d, 5d...
Schedule.linear(d)d, 2d, 3d, 4d...

Best Practices

  1. Always add recurs limit - Avoid infinite retries
  2. Use jitter for distributed systems - Prevents thundering herd
  3. Cap exponential backoff - Use upTo() for max delay
  4. Log retry attempts - Use tapInput for visibility
  5. Different schedules for different errors - Transient vs permanent

Additional Resources

For comprehensive scheduling documentation, consult ${CLAUDE_PLUGIN_ROOT}/references/llms-full.txt.

Search for these sections:

  • "Built-In Schedules" for schedule types
  • "Schedule Combinators" for composition
  • "Repetition" for repeat patterns
  • "Retrying" for retry patterns
  • "Cron" for cron expressions

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

testing

No summary provided by upstream source.

Repository SourceNeeds Review
General

traits

No summary provided by upstream source.

Repository SourceNeeds Review
General

configuration

No summary provided by upstream source.

Repository SourceNeeds Review