Files
dotfiles/.config/opencode/skills/systematic-debugging/condition-based-waiting.md

1.7 KiB

title, type, permalink
title type permalink
condition-based-waiting note opencode-config/skills/systematic-debugging/condition-based-waiting

Condition-Based Waiting

Overview

Arbitrary sleep durations create flaky tests and race conditions.

Core principle: wait for the condition that proves readiness, not a guessed delay.

When to Use

Use this when:

  • Tests rely on sleep or fixed setTimeout delays
  • Asynchronous operations complete at variable speeds
  • Tests pass locally but fail in CI or under load

Avoid arbitrary waits except when explicitly validating timing behavior (for example, debounce intervals), and document why timing-based waiting is necessary.

Core Pattern

// ❌ Timing guess
await new Promise((r) => setTimeout(r, 100));

// ✅ Condition wait
await waitFor(() => getState() === 'ready', 'state ready');

Generic Helper

async function waitFor<T>(
  condition: () => T | false | undefined | null,
  description: string,
  timeoutMs = 5000,
  pollMs = 10
): Promise<T> {
  const started = Date.now();

  while (true) {
    const result = condition();
    if (result) return result;

    if (Date.now() - started > timeoutMs) {
      throw new Error(`Timeout waiting for ${description} after ${timeoutMs}ms`);
    }

    await new Promise((r) => setTimeout(r, pollMs));
  }
}

Practical Guidance

  • Keep polling intervals modest (for example, 10ms) to avoid hot loops.
  • Always include a timeout and actionable error message.
  • Query fresh state inside the loop; do not cache stale values outside it.

Common Mistakes

  • Polling too aggressively (high CPU, little benefit)
  • Waiting forever without timeout
  • Mixing arbitrary delays and condition checks without rationale