Skip to content

partial-with-a-firstRelease is cached as terminal on the web + badge surfaces (30d / 24h), so a truncated traversal pins a possibly-wrong tag #159

Description

@lukaso-bot

hardTtlFor() and badge.ts treat a soft-deadline partial that carries a firstRelease as terminal, so a truncated traversal's answer is pinned: 30 days in the result cache, 24h at camo.

packages/web/src/resolve.ts:54:

function hardTtlFor(r: LookupResult): number {
  if (r.firstRelease) return HARD_TTL_RELEASED; // 30 days
  if (r.partial) return HARD_TTL_PARTIAL;
  return HARD_TTL_PENDING;
}

isFresh() (same file, :60) has the same ordering — if (entry.value.firstRelease) return true — so such an entry never revalidates. packages/web/src/routes/badge.ts:141 does the same thing at the edge: resolved.result.firstRelease ? LONG_CACHE : SHORT_CACHE, and badgeStateForResult renders the tag rather than checking… whenever firstRelease is set.

Why it matters. A partial means the traversal was truncated by the soft deadline, so its firstRelease is a best-effort answer, not confirmed to be the earliest release containing the commit. Concretely: the gallop finds v2.0.0 and the deadline blows before it can walk back to v1.9.0, which is the true first release. That wrong-but-plausible tag is then treated as final — kept for 30 days in the result cache and served to camo with a 24h TTL — with no path to correction short of the cache entry expiring.

Deadline-heavy repos (gitlab.gnome.org/GNOME/gimp, kubernetes/kubernetes) are exactly where partial is common, so this is not a rare edge.

Where it came from. Found while reviewing #158 (fix(web-og): cache the OG card by terminality, not by result presence). #158 fixes the OG surface — its isTerminal() requires firstRelease != null && !partial, so an OG card for a partial revalidates every 300s. That makes #158's OG lifetime stricter than the web/badge surfaces, and this issue is the remaining half: #151 asked for "cache by whether the answer can still change", and on the result cache + badge it still caches by "did an answer come back".

Sketch of the fix. Test partial before firstRelease in both hardTtlFor() and isFresh(), so a partial-with-release gets HARD_TTL_PARTIAL and revalidates; and key badge's cache lifetime on firstRelease && !partial to match. Needs a deliberate call on the badge copy: a partial-with-release should probably still render the tag it found (better than checking…) but with the short TTL, so it self-corrects.

Not fixed in #158 — that PR touches only packages/web-og, and this is packages/web. Filed separately so the change lands in a PR that is about it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions