authorgravatar for me@t3.ggTheo Browne <me@t3.gg> 2026-09-04 07:35:48-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-04 07:35:48-07:00
log246064993535e5d90107d3d7784ceef3cc883435
treed49420994334436782de1154cae53414d95dcce1
parentec8b2119c377f5c1dbe6235b221ef98eca31a96e
signature Signed by PGP key B5690EEEBB952194

perf(clients): avoid waiting to read cached relay tokens (#9691)


2 files changed, 124 insertions(+), 11 deletions(-)

packages/client-runtime/src/relay/managedRelay.test.ts+100-1
...@@ -1,5 +1,8 @@...@@ -1,5 +1,8 @@
1import { EnvironmentId } from "@t3tools/contracts";1import { EnvironmentId } from "@t3tools/contracts";
2import { RelayEnvironmentStatusScope } from "@t3tools/contracts/relay";2import {
3 RelayEnvironmentConnectScope,
4 RelayEnvironmentStatusScope,
5} from "@t3tools/contracts/relay";
3import { describe, expect, it } from "@effect/vitest";6import { describe, expect, it } from "@effect/vitest";
4import * as Duration from "effect/Duration";7import * as Duration from "effect/Duration";
5import * as Effect from "effect/Effect";8import * as Effect from "effect/Effect";
...@@ -190,6 +193,102 @@ describe("ManagedRelayClient", () => {...@@ -190,6 +193,102 @@ describe("ManagedRelayClient", () => {
190 }).pipe(Effect.provide(managedRelayTestLayer(fetchFn)));193 }).pipe(Effect.provide(managedRelayTestLayer(fetchFn)));
191 });194 });
192195
196 it.effect("uses a cached token while another scope waits for an exchange", () => {
197 const exchangeStarted = Promise.withResolvers<void>();
198 const releaseExchange = Promise.withResolvers<void>();
199 let tokenExchangeCount = 0;
200 const statusTokens: Array<string | null> = [];
201 let persistedTokens: ReadonlyArray<ManagedRelay.ManagedRelayAccessTokenCacheEntry> = [
202 {
203 accountId: "user-1",
204 clientId: "t3-mobile",
205 relayUrl: "https://relay.example.test",
206 thumbprint: "client-thumbprint",
207 scopes: [RelayEnvironmentStatusScope],
208 accessToken: "cached-status-token",
209 expiresAtMillis: Number.MAX_SAFE_INTEGER,
210 },
211 ];
212 const accessTokenStore: ManagedRelay.ManagedRelayAccessTokenStore = {
213 load: Effect.sync(() => persistedTokens),
214 save: (entries) =>
215 Effect.sync(() => {
216 persistedTokens = entries;
217 }),
218 clear: Effect.sync(() => {
219 persistedTokens = [];
220 }),
221 };
222 const fetchFn = ((input, init) => {
223 if (String(input).endsWith("/v1/client/dpop-token")) {
224 tokenExchangeCount += 1;
225 exchangeStarted.resolve();
226 return releaseExchange.promise.then(() =>
227 Response.json({
228 access_token: "expanded-scope-token",
229 issued_token_type: "urn:ietf:params:oauth:token-type:access_token",
230 token_type: "DPoP",
231 expires_in: 1_800,
232 scope: `${RelayEnvironmentStatusScope} ${RelayEnvironmentConnectScope}`,
233 }),
234 );
235 }
236 statusTokens.push(new Headers(init?.headers).get("authorization"));
237 return Promise.resolve(
238 Response.json({
239 environmentId: "env-1",
240 endpoint: {
241 httpBaseUrl: "https://desktop.example.test/",
242 wsBaseUrl: "wss://desktop.example.test/ws",
243 providerKind: "cloudflare_tunnel",
244 },
245 status: "online",
246 checkedAt: "2026-09-04T00:00:00.000Z",
247 }),
248 );
249 }) satisfies typeof globalThis.fetch;
250
251 return Effect.gen(function* () {
252 const relayClient = yield* ManagedRelay.ManagedRelayClient;
253 const statusInput = {
254 clerkToken: clerkToken("user-1", "session-1"),
255 scopes: [RelayEnvironmentStatusScope],
256 environmentId: EnvironmentId.make("env-1"),
257 } as const;
258 const expandedScopeInput = {
259 ...statusInput,
260 scopes: [RelayEnvironmentStatusScope, RelayEnvironmentConnectScope],
261 } as const;
262 const firstMiss = yield* relayClient
263 .getEnvironmentStatus(expandedScopeInput)
264 .pipe(Effect.forkChild);
265 yield* Effect.promise(() => exchangeStarted.promise);
266 const secondMiss = yield* relayClient
267 .getEnvironmentStatus(expandedScopeInput)
268 .pipe(Effect.forkChild);
269
270 const status = yield* relayClient.getEnvironmentStatus(statusInput);
271 expect(status.status).toBe("online");
272 expect(statusTokens).toEqual(["DPoP cached-status-token"]);
273
274 releaseExchange.resolve();
275 yield* Fiber.join(firstMiss);
276 yield* Fiber.join(secondMiss);
277 expect(tokenExchangeCount).toBe(1);
278 expect(persistedTokens.map((token) => token.accessToken)).toEqual([
279 "cached-status-token",
280 "expanded-scope-token",
281 ]);
282 yield* relayClient.resetTokenCache;
283 expect(persistedTokens).toEqual([]);
284 yield* relayClient.getEnvironmentStatus(expandedScopeInput);
285 expect(tokenExchangeCount).toBe(2);
286 }).pipe(
287 Effect.ensuring(Effect.sync(() => releaseExchange.resolve())),
288 Effect.provide(managedRelayTestLayer(fetchFn, undefined, accessTokenStore)),
289 );
290 });
291
193 it.effect("reuses a persisted token across runtimes and Clerk session token rotation", () => {292 it.effect("reuses a persisted token across runtimes and Clerk session token rotation", () => {
194 let tokenExchangeCount = 0;293 let tokenExchangeCount = 0;
195 let persistedTokens: ReadonlyArray<ManagedRelay.ManagedRelayAccessTokenCacheEntry> = [];294 let persistedTokens: ReadonlyArray<ManagedRelay.ManagedRelayAccessTokenCacheEntry> = [];
packages/client-runtime/src/relay/managedRelay.ts+24-10
...@@ -546,18 +546,32 @@ export const make = Effect.fn("ManagedRelayClient.make")(function* (...@@ -546,18 +546,32 @@ export const make = Effect.fn("ManagedRelayClient.make")(function* (
546 expiresAtMillis: nowMillis + response.expires_in * 1_000,546 expiresAtMillis: nowMillis + response.expires_in * 1_000,
547 } satisfies ManagedRelayAccessTokenCacheEntry;547 } satisfies ManagedRelayAccessTokenCacheEntry;
548 }548 }
549 const match = {
550 accountId: accountId.value,
551 clientId: options.clientId,
552 relayUrl,
553 thumbprint: input.thumbprint,
554 scopes: input.scopes,
555 nowMillis,
556 };
557 // Cache hits do not need to wait for an unrelated exchange or store write.
558 const cached = (yield* SynchronizedRef.get(cachedTokens)).find((token) =>
559 tokenMatches(token, match),
560 );
561 if (cached) {
562 yield* Effect.annotateCurrentSpan({
563 "relay.token_cache.result": "hit",
564 });
565 return cached;
566 }
549 return yield* SynchronizedRef.modifyEffect(cachedTokens, (tokens) =>567 return yield* SynchronizedRef.modifyEffect(cachedTokens, (tokens) =>
550 Effect.gen(function* () {568 Effect.gen(function* () {
551 const activeTokens = tokens.filter((token) => token.expiresAtMillis > nowMillis + 5_000);569 const lookupMillis = yield* Clock.currentTimeMillis;
570 const activeTokens = tokens.filter(
571 (token) => token.expiresAtMillis > lookupMillis + 5_000,
572 );
552 const cached = activeTokens.find((token) =>573 const cached = activeTokens.find((token) =>
553 tokenMatches(token, {574 tokenMatches(token, { ...match, nowMillis: lookupMillis }),
554 accountId: accountId.value,
555 clientId: options.clientId,
556 relayUrl,
557 thumbprint: input.thumbprint,
558 scopes: input.scopes,
559 nowMillis,
560 }),
561 );575 );
562 if (cached) {576 if (cached) {
563 yield* Effect.annotateCurrentSpan({577 yield* Effect.annotateCurrentSpan({
...@@ -576,7 +590,7 @@ export const make = Effect.fn("ManagedRelayClient.make")(function* (...@@ -576,7 +590,7 @@ export const make = Effect.fn("ManagedRelayClient.make")(function* (
576 thumbprint: input.thumbprint,590 thumbprint: input.thumbprint,
577 scopes: input.scopes,591 scopes: input.scopes,
578 accessToken: response.access_token,592 accessToken: response.access_token,
579 expiresAtMillis: nowMillis + response.expires_in * 1_000,593 expiresAtMillis: lookupMillis + response.expires_in * 1_000,
580 };594 };
581 const nextTokens = [...activeTokens, next];595 const nextTokens = [...activeTokens, next];
582 if (options.accessTokenStore) {596 if (options.accessTokenStore) {