Skip to content

OG card for a not-yet-released commit is cached 24h, so it never flips when the release lands #151

Description

@lukaso-bot

renderImage in packages/web-og/src/index.tsx picks its cache lifetime purely
on whether it got a result at all:

const longCache = `public, max-age=${24 * 60 * 60}, s-maxage=${24 * 60 * 60}`;
const shortCache = 'public, max-age=60';
const cacheControl = result ? longCache : shortCache;

A LookupResult with firstRelease: null is a real result, so it takes
longCache — and ResultCard renders it as the string "not yet released"
(const tag = r.firstRelease?.tag ?? 'not yet released').

So the one card whose whole job is to flip is pinned for 24h. A commit shared
before its release lands unfurls as "not yet released", and Slack/X keep that
PNG for a day after the release ships. This is the OG analogue of the badge
invariant the project already states in CLAUDE.md and priorities.md:

Badge cache semantics. Released → long cache; not-yet/checking → short
cache. Get this wrong and badges stop flipping (or flip too slowly).

badge.ts gets this right (the liveness probe asserts both arms: released →
max-age=86400, not-yet → max-age=300). web-og does not.

Not from #144

This is on main today and is not caused by #144 — that PR only changed which
cache slot /internal reads. It surfaced in #144's round-4 review as the
amplifier behind a stale-answer finding: #144 bounded how stale an answer it
will hand back (SWR_MAX_STALE, 30 min) precisely because web-og pins whatever
it gets for 24h. Bounding staleness limits the damage; it doesn't fix this.

Suggested fix

Key the lifetime on the answer's terminality, not its presence — the same test
resolve.ts already uses for the cache TTL (hardTtlFor):

const cacheControl = result?.firstRelease ? longCache : shortCache;

A partial result should be short-cached too, for the same reason.

Note on overlap

#141 is open against this same function (renderImage's cache-control being
overridden by workers-og's 1-year immutable default). Whoever lands second
should rebase rather than both editing these lines. Fixing it inside #141 is
reasonable if that PR is still in flight — it is the same header, one decision.

Guard

Whatever lands, it needs a test that goes red on the current code: render a
result with firstRelease: null and assert the response's cache-control is
the short one. packages/web-og/test currently asserts the placeholder arm only.

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