Skip to content

Commit 7f57aa9

Browse files
t3dotggclaude
andcommitted
fix(client-runtime): socket token renewal survives a wall-clock jump
Co-Authored-By: Claude Opus 5.5 <[email protected]>
1 parent 9b4d773 commit 7f57aa9

1 file changed

Lines changed: 7 additions & 5 deletions

File tree

  • packages/client-runtime/src/authorization

‎packages/client-runtime/src/authorization/service.ts‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -541,17 +541,19 @@ export const make = Effect.gen(function* () {
541541
// Untraced: a span here would stay open for the socket's lifetime. Each renewal has its own.
542542
renewDpopBeforeExpiry: Effect.fnUntraced(function* (input) {
543543
let expiresAtEpochMs = input.expiresAtEpochMs;
544-
while (true) {
545-
const now = yield* Clock.currentTimeMillis;
544+
let now = yield* Clock.currentTimeMillis;
545+
// Past expiry the server has closed the socket.
546+
while (now < expiresAtEpochMs) {
546547
// getDpopToken reuses a cached token until it is within the skew of expiry.
548+
// The floor keeps a wall-clock jump from turning this into a tight loop.
547549
yield* Effect.sleep(
548-
Math.max(0, expiresAtEpochMs - DPOP_ACCESS_TOKEN_REFRESH_SKEW_MS - now),
550+
Math.max(1_000, expiresAtEpochMs - DPOP_ACCESS_TOKEN_REFRESH_SKEW_MS - now),
549551
);
550552
const { token } = yield* getDpopToken({
551553
expectedEnvironmentId: input.expectedEnvironmentId,
552554
}).pipe(Effect.withSpan("environment.authorization.renewSocket"), withRelayClientTracing);
553-
if (token.expiresAtEpochMs <= expiresAtEpochMs) return;
554-
expiresAtEpochMs = token.expiresAtEpochMs;
555+
expiresAtEpochMs = Math.max(expiresAtEpochMs, token.expiresAtEpochMs);
556+
now = yield* Clock.currentTimeMillis;
555557
}
556558
}),
557559
});

0 commit comments

Comments
 (0)