Repository navigation
feat(toolkit-core): Let a request scope bypass cached reads - #1720
Merged
Merged
Conversation
Add a `fresh` hook to the API transport. While it returns true, GETs skip the cache lookup and go to the network, and the response still replaces the cached entry, so later reads see it. Hosts back the hook with request-scoped state, such as AsyncLocalStorage around a tool call. Implements #1669 task 5.3. Co-Authored-By: BYK <burak.kaya@sentry.io>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
sentry-junior Bot
added a commit
that referenced
this pull request
Oct 29, 2026
5.3 is in review in #1720, and 6.1 is stacked on it. Co-Authored-By: BYK <burak.kaya@sentry.io>
BYK
approved these changes
Oct 29, 2026
BYK
enabled auto-merge (squash)
October 29, 2026 12:18
This was referenced Oct 29, 2026
BYK
added a commit
that referenced
this pull request
Oct 29, 2026
This PR sends every MCP request to the Sentry API through the shared transport, and moves retries out of `SentryApiService` into it. It is task **6.1** of #1669 (`unify-sentry-api-layer`) and builds on the shared transport (#1719) and the fresh-read hook (#1720). ### What changed - **One transport:** `SentryApiService` sends every request through `createApiTransport` from `@sentry/toolkit-core/api-transport`, using the MCP's existing `REQUEST_RETRY_POLICY`. That includes `@sentry/api` operations, which already go through `request()`. - **One retry layer:** `SentryApiService` no longer has its own retry loop or network-failure bookkeeping. The shared transport retries a 429 for any method, and a 500/502/503/504 or a network failure for GET and HEAD. `SentryApiService` still parses the final error response, so `ApiRateLimitError.retryAfterMs` is still read from `Retry-After` or `X-Sentry-Rate-Limit-Reset`. - **Transport options:** `credentials` and `timeoutMs` on `createApiTransport` are now optional. Without a `CredentialProvider`, the transport keeps the `Authorization` header the request already has, never refreshes, and skips the cache, because cache entries are tied to a credential. The MCP uses it this way, and still sets no timeout, as before. - **Abort reason:** an abort while a request is in flight now rejects with the caller's `signal.reason`, instead of being treated as a retryable network failure. An earlier revision also added a host-supplied `fetch` option to `McpServerOptions` and `ServerContext`. That is gone: per the revised #1669 plan, the shared API layer moves into toolkit-core and then `@sentry/api`, and the CLI passing its fetch to `sentry mcp` is deferred. ### Intentional behavior changes - **`allowStatuses`:** a status a caller lists there is now returned only after the transport has finished retrying it. Before, it came back on the first attempt. Today's callers only list 404 and 400, which are never retried, so they see no difference. - **Abort during a retry wait:** if the caller's signal aborts while the transport is waiting to retry, the abort error is rethrown as-is. It is no longer wrapped as a connection failure. ### Relation to #1669 - Done: 5.0 (#1673, #1710), 5.1 and 5.2 (#1719), 5.3 (#1720). - This PR: 6.1. - Next: consolidate the MCP's `SentryApiService` and the CLI's API modules into one browser-safe API client in toolkit-core, stacked on this PR. ### Verification - New `mcp-core` tests: - A GET that is rate-limited on every attempt reaches the API at most `maxRetries + 1` times. - An in-flight abort rejects with the caller's reason, after one attempt. - New `toolkit-core` tests: - Without credentials, the request's own `Authorization` is kept. - Without credentials, the cache is never consulted. - An in-flight abort keeps the caller's reason. - Suites: | Package | Result | | --- | --- | | `toolkit-core` | 273 pass | | `mcp-core` | 1,899 pass, 6 skipped | | `mcp-server` | 87 pass | | `mcp-cloudflare` | 443 pass | - `tsc --noEmit` passes for `toolkit-core`, `mcp-core`, `mcp-server`, `mcp-cloudflare`, and `cli`. `oxlint` and `oxfmt --check` are clean on the changed files. - Test changes: - Hand-built response mocks in `client.test.ts` gained a `status`, because the transport reads it to decide on a retry. - Header assertions in `client.test.ts` and `mcp-handler.test.ts` now read through `Headers`, because the transport passes a `Headers` object. <!-- junior-request-attribution:start --> via **BYK**. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:agent%3Aa6eddc0161cff61914454da9f74fcdf1 --> -- [View Junior Session in Sentry](https://sentry.sentry.io/explore/conversations/agent%3Aa6eddc0161cff61914454da9f74fcdf1/?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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This adds a request-scoped fresh-read bypass to the shared API transport in
@sentry/toolkit-core/api-transport. It is task 5.3 of #1669 (unify-sentry-api-layer) and builds on the shared transport from #1719.What's shared
createApiTransportaccepts a new optionalfresh?(): booleanhook. While the hook returns true:A host backs the hook with request-scoped state, for example
AsyncLocalStoragearound a single MCP tool call that asked forfresh: true. That keeps the bypass to one call rather than the whole process. This is the transport side of the MCP'sfreshinput planned in 6.3.Behavior changes
None for current callers. The hook is optional, and no host sets it yet. The CLI's
--freshflag keeps its existing process-wide bypass incli/src/lib/response-cache.ts, with reads skipped and writes kept as before. This PR leaves that unchanged.Relation to #1669
fetchtoMcpServerOptionsand routes allSentryApiServiceand@sentry/apirequests through it.SentryApiServicedrops its own retry loop, so retries happen in the shared transport only.Verification
skips the cache in a fresh scope and replaces the entry. It stores v1, then reads in a fresh scope and gets v2 from the network. Once the fresh scope ends, the next read is a cache hit for v2.toolkit-core: 21 files and 270 tests pass.test/lib/sentry-client*,test/lib/response-cache*,test/lib/api): 49 files and 1,049 tests pass.tsc --noEmitpasses fortoolkit-coreandcli.oxlint,oxfmt --checkandast-grep scanare clean on the changed files.via BYK.
--
View Junior Session in Sentry