Просмотр исходного кода

refactor(account): share token freshness helper (#20591)

Kit Langton 5 месяцев назад
Родитель
Сommit
916afb5220

+ 6 - 2
packages/opencode/src/account/index.ts

@@ -120,6 +120,10 @@ class TokenRefreshRequest extends Schema.Class<TokenRefreshRequest>("TokenRefres
 
 const clientId = "opencode-cli"
 const eagerRefreshThreshold = Duration.minutes(5)
+const eagerRefreshThresholdMs = Duration.toMillis(eagerRefreshThreshold)
+
+const isTokenFresh = (tokenExpiry: number | null, now: number) =>
+  tokenExpiry != null && tokenExpiry > now + eagerRefreshThresholdMs
 
 const mapAccountServiceError =
   (message = "Account service operation failed") =>
@@ -219,7 +223,7 @@ export namespace Account {
 
           const account = maybeAccount.value
           const now = yield* Clock.currentTimeMillis
-          if (account.token_expiry && account.token_expiry > now + Duration.toMillis(eagerRefreshThreshold)) {
+          if (isTokenFresh(account.token_expiry, now)) {
             return account.access_token
           }
 
@@ -229,7 +233,7 @@ export namespace Account {
 
       const resolveToken = Effect.fnUntraced(function* (row: AccountRow) {
         const now = yield* Clock.currentTimeMillis
-        if (row.token_expiry && row.token_expiry > now + Duration.toMillis(eagerRefreshThreshold)) {
+        if (isTokenFresh(row.token_expiry, now)) {
           return row.access_token
         }
 

+ 7 - 4
packages/opencode/test/account/service.test.ts

@@ -18,6 +18,9 @@ const truncate = Layer.effectDiscard(
 
 const it = testEffect(Layer.merge(AccountRepo.layer, truncate))
 
+const insideEagerRefreshWindow = Duration.toMillis(Duration.minutes(1))
+const outsideEagerRefreshWindow = Duration.toMillis(Duration.minutes(10))
+
 const live = (client: HttpClient.HttpClient) =>
   Account.layer.pipe(Layer.provide(Layer.succeed(HttpClient.HttpClient, client)))
 
@@ -63,7 +66,7 @@ it.live("orgsByAccount groups orgs per account", () =>
         url: "https://one.example.com",
         accessToken: AccessToken.make("at_1"),
         refreshToken: RefreshToken.make("rt_1"),
-        expiry: Date.now() + 10 * 60_000,
+        expiry: Date.now() + outsideEagerRefreshWindow,
         orgID: Option.none(),
       }),
     )
@@ -75,7 +78,7 @@ it.live("orgsByAccount groups orgs per account", () =>
         url: "https://two.example.com",
         accessToken: AccessToken.make("at_2"),
         refreshToken: RefreshToken.make("rt_2"),
-        expiry: Date.now() + 10 * 60_000,
+        expiry: Date.now() + outsideEagerRefreshWindow,
         orgID: Option.none(),
       }),
     )
@@ -159,7 +162,7 @@ it.live("token refreshes before expiry when inside the eager refresh window", ()
         url: "https://one.example.com",
         accessToken: AccessToken.make("at_old"),
         refreshToken: RefreshToken.make("rt_old"),
-        expiry: Date.now() + 60_000,
+        expiry: Date.now() + insideEagerRefreshWindow,
         orgID: Option.none(),
       }),
     )
@@ -267,7 +270,7 @@ it.live("config sends the selected org header", () =>
         url: "https://one.example.com",
         accessToken: AccessToken.make("at_1"),
         refreshToken: RefreshToken.make("rt_1"),
-        expiry: Date.now() + 10 * 60_000,
+        expiry: Date.now() + outsideEagerRefreshWindow,
         orgID: Option.none(),
       }),
     )