'use strict';

// Generic circuit breaker for off-thread read-pool calls (getAllSessionsData, the prompt
// index compute, message/timeline parse, ...). At early boot a worker's read-only
// connection can't attach to the WAL shared-memory until a writer is established + the DB
// settles, so the request times out. Without a breaker, every off-thread call in that
// window waits the full timeout and then falls back to a cold main-thread build.
//
// After `degradeAfter` consecutive failures the breaker OPENS for `cooldownMs`; while open,
// the caller SKIPS the off-thread attempt (serving cache/SWR) rather than timing out into a
// main build. One success CLOSES it (half-open: the first attempt after the cooldown probes
// the pool again). Pure + injectable clock for testing.

function createReadPoolBreaker({ degradeAfter = 2, cooldownMs = 30000 } = {}) {
  const _degradeAfter = Math.max(1, Number(degradeAfter) || 1);
  const _cooldownMs = Math.max(0, Number(cooldownMs) || 0);
  let failures = 0;
  let openUntil = 0;
  return {
    isOpen(now) { return Number(now) < openUntil; },
    recordFailure(now) {
      failures += 1;
      if (failures >= _degradeAfter) openUntil = Number(now) + _cooldownMs;
      return { failures, openUntil };
    },
    recordSuccess() { failures = 0; openUntil = 0; },
    getState() { return { failures, openUntil, degradeAfter: _degradeAfter, cooldownMs: _cooldownMs }; },
  };
}

module.exports = { createReadPoolBreaker };
