Skip to content

readinessReconcile timeouts are ordered so the deadline can never fire: 90min budget, 10min stall, ~50min container life #376

Description

@khaliqgant

Splitting this out of #372, where it surfaced while confirming the wedge in production. It is a distinct defect from "the breaker cannot trip", and it is not addressed by #374.

The mismatch

Three timeouts govern a stalled readinessReconcile sweep, and they are ordered so that the system can never act on what it detects:

constant value source
DEFAULT_READINESS_RECONCILE_TIMEOUT_MS 90 min schema.ts:62 (90 * 60_000)
READINESS_RECONCILE_STALL_INTERVALSstate: 'stalled' 10 min public-health.ts:64/491
observed container lifetime ~50 min measured, see below

The deadline that would convert a hang into an actionable failure is 90 minutes. The container is replaced at roughly 50 minutes. The deadline therefore never fires. Meanwhile the stall is declared at 10 minutes — so the system knows it is wedged for about 80 minutes before it would have been permitted to do anything, and is recycled first.

Evidence for the ~50 minute lifetime

Two independent surfaces agree:

  1. Boot timestamps observed on /healthz across the incident.
  2. cloud#3046 carries 51 dependency-park comments at ~32–68 minute spacing, mostly an identical dedupe signature. The dedupe map (#dependencyParkNotices, factory.ts:8941) is in-memory and is never cleared for a still-parked issue — so each repeated comment requires a fresh process. 51 comments ≈ 51 container lifetimes.

Why #374 does not cover this

#374 bounds the sweep, which is the right mechanism — but sweepBudgetMs defaults to reconcileTimeoutMs, i.e. the same 90 minutes, and the deployed template sets no override. So the default inherits exactly this mismatch and the bound never fires. #374 plus an explicit sweepBudgetMs near the stall threshold would fix the immediate outage; this issue is about the defaults being self-defeating rather than about any one call site.

Suggested shape of a fix

The relationship between "we declare it stalled" and "we are allowed to act" should be expressed rather than left to three independently-chosen constants. A default deadline that exceeds the process's own expected lifetime is never a real deadline, and is worth asserting against.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions