Skip to content

fix(cli): Stop caching events and traces for 24 hours - #1681

Merged
BYK merged 2 commits into
mainfrom
fix/cli-cache-tiers
Oct 27, 2026
Merged

BYK merged 2 commits into
mainfrom
fix/cli-cache-tiers

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

The CLI's fallback "immutable" cache tier kept any /events/<id>/, /trace/<id>/, or /trace-items/<id>/ response for 24 hours. It was also checked before the /issues/ volatile pattern, so getLatestEvent (/issues/<id>/events/latest/) was cached for a day: re-running sentry issue view an hour later could show an outdated "latest" event.

The getsentry/sentry#128818 spike (findings) found that none of these responses are actually immutable. Event payloads embed nextEventID/previousEventID, user reports, and release data, reprocessing and merges can change them for the same ID, latest/oldest/recommended resolve to different events over time, and full traces gain spans as they arrive.

This removes the immutable tier:

Tier TTL Matches
no-cache 0 autofix and root-cause polling (unchanged)
volatile 60 s /issues/ (now including issue events), project event details, full traces, dataset=logs|spans, trace logs
stable 5 m everything else, now including organization event details and trace-item details

Server Cache-Control headers still take precedence, so when getsentry/sentry#128828 ships its private, max-age=300 headers the CLI follows them without a release. A TODO points at getsentry/sentry-api-schema#81 and #102 for classifying by generated @sentry/api operation metadata instead of URL regexes.

Notes for review:

  • No migration. Freshness is recomputed from createdAt and the current tier on read, so existing 24-hour entries on disk are treated by the new rules immediately.
  • immutableMinTimeToLive removed. It pointed at the deleted tier constant. The http-cache-semantics default is the same 24 hours, and it only applies to responses where the server sends immutable.
  • Cost: repeated reads of project/issue events and full traces will hit the API after 60 seconds instead of 24 hours; organization event and trace-item details after 5 minutes.

Task group 2 of the unify-sentry-api-layer OpenSpec change in #1669.

Checks run locally:

  • New classifyUrl cases plus fake-clock expiry tests for org event details (hit at 4 min, miss at 6 min), issue latest event, project event details, full traces, and server max-age overriding the fallback. 8 of them fail against the old classifier.
  • pnpm exec vitest run test/lib/response-cache*.test.ts: 60 passed
  • CLI typecheck, lint, and oxlint/oxfmt on the changed files: clean
  • pnpm run test:unit (first revision): 11,583 passed, 6 failed. The same 6 fail on unmodified main in my sandbox: filesystem-permission tests (completions, code-scanner, file-changes, telemetry readonly DB, upgrade lock) that depend on the environment, not this change.

--

View Junior Session in Sentry

The fallback "immutable" tier matched any `/events/<id>/`, `/trace/<id>/`,
or `/trace-items/<id>/` URL and was checked before the `/issues/` volatile
pattern, so `/issues/<id>/events/latest/` was cached for a day. Event
payloads embed mutable fields (next/previous event IDs, user reports,
release data), `latest`/`oldest`/`recommended` resolve to different events
over time, and full traces gain spans (getsentry/sentry#128818).

Replace it with a 5-minute `detail` tier limited to exact path shapes:
organization event details without `averageColumn` and project trace-item
details without `debug`. Issue events, project event details, and full
traces move to the 60-second volatile tier, which is now checked first.
Server cache headers still take precedence.

Existing on-disk entries are re-checked against the new tier on read, so
no migration is needed. Dropping `immutableMinTimeToLive` keeps the
http-cache-semantics default (24 hours) for server `immutable` responses.

Task group 2 of the unify-sentry-api-layer OpenSpec change (#1669).

Co-Authored-By: BYK <burak.kaya@sentry.io>
@vercel

vercel Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
sentry-local Skipped Skipped Oct 27, 2026 6:53pm UTC

Request Review

@github-actions github-actions Bot added the risk: medium PR risk score: medium label Oct 27, 2026
Comment thread packages/cli/src/lib/response-cache.ts Outdated
Comment thread packages/cli/src/lib/response-cache.ts Outdated
`detail` had the same 5-minute TTL as `stable` and only existed to mark
future R2 eligibility on the hosted MCP, which belongs to that store's own
allowlist. Dropping it removes the route table and URL parsing; organization
event details and trace-item details now fall through to `stable`.

Add a TODO to classify by generated `@sentry/api` operation metadata
(getsentry/sentry-api-schema#81, #102) instead of URL regexes.
@BYK
BYK merged commit 8dc7fac into main Oct 27, 2026
27 checks passed
@BYK
BYK deleted the fix/cli-cache-tiers branch October 27, 2026 19:07
sentry-junior Bot added a commit that referenced this pull request Oct 27, 2026
…tead

Matches #1681 as merged: the CLI has no separate detail tier, since it
would share the stable TTL. R2 eligibility on the hosted MCP becomes an
explicit URL allowlist owned by that store. Mark task group 2 done.

Co-Authored-By: BYK <burak.kaya@sentry.io>
BYK added a commit that referenced this pull request Oct 27, 2026
Moves the CLI's response cache policy into
`@sentry/toolkit-core/response-cache` so the MCP can use the same rules.
This is task 4.1 of the unify-sentry-api-layer proposal (#1669). Codecs,
the `CacheStore` interface, and the memory store (4.2–4.3) come in later
PRs.

What moved:

- `classifyUrl` and `FALLBACK_TTL_MS`: the fallback tiers from #1681,
unchanged. `volatile` is 60 seconds, `stable` is 5 minutes, and
`no-cache` covers autofix and root-cause polling.
- `normalizeUrl` and `buildCacheKey`: identity-scoped keys over the
method and the full URL, including the host and sorted query params.
- `computeInvalidationPrefixes`: `cli/src/lib/cache-keys.ts` and its
tests were moved as-is. Only the comments that named CLI functions
changed.

**Key derivation moves to WebCrypto.** `buildCacheKey` now uses
`crypto.subtle` HMAC-SHA256 instead of `node:crypto`, so it runs in
Workers and browsers. That makes it async; the call sites in
`response-cache.ts` were already async. A test checks that the output
matches `createHmac("sha256", identity)` byte for byte, so cache files
written by released CLIs still hit. An empty identity now throws instead
of producing a key that isn't scoped to anyone. The CLI never passes
one, because `getIdentityFingerprint()` falls back to `<anon>`.

**CLI changes:**

- `response-cache.ts` imports the policy. Its `buildCacheKey` wrapper,
which defaults to the active identity, is now async, and its tests await
it.
- `sentry-client.ts` imports `computeInvalidationPrefixes` from
toolkit-core.
- `classifyUrl`/`normalizeUrl` tests import them from toolkit-core
directly, so they aren't re-exported only for tests.

**One test change outside the cache tests.** WebCrypto signs on the
libuv threadpool, so parallel requests can finish their cache lookups in
either order. The `getLogs` batching test used to assume the 100-ID
batch reached `fetch` first. It now checks for one request of each size,
in any order. `Promise.all` still returns the batches in order, so
behavior is unchanged.

**Tests:** new `tiers.test.ts` and `keys.test.ts` cover the spec
scenarios:

- tiers: organization event, issue event, full trace, polling, and the
rule that no tier lasts more than 5 minutes
- keys: different identities, different hosts, query order,
`node:crypto` parity, and an empty identity

The invalidation tests moved with the module. Two spec scenarios are
tested in the CLI instead: token refresh keeping the same identity
(`getIdentityFingerprint`) and invalidation only touching the
requester's entries (the disk store).

**Checks:**

- `pnpm run tsc`, `pnpm run lint`, and `pnpm run docs:check` pass, and
all 431 toolkit-core tests pass.
- The full CLI unit suite has 6 local failures, all
filesystem-permission tests that fail on `main` too, because the sandbox
ignores read-only permissions. None touch the cache.

<!-- junior-request-attribution:start -->
via **BYK**.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:local%3Aweb%3A0ab4fc2bd5a2e23f2c25efcf -->

--

[View Junior Session in
Sentry](https://sentry.sentry.io/explore/conversations/local%3Aweb%3A0ab4fc2bd5a2e23f2c25efcf/?project=4510944073809921)

<!-- junior-session-footer:end -->

---------

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: BYK <burak.kaya@sentry.io>

This branch was previously deployed

1 inactive deployment
Preview — 31c5de5a Deployed Oct 27, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: medium PR risk score: medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant