Skip to content

Commit 67d856a

Browse files
committed
fix(manager): optimize token durationToRenewal calculation
I observed the durationToRenewal was significantly slower than before due to changes done to cover the unnecessary precision. Using Milliseconds as the TTL is sufficient and significantly faster.
1 parent 0edba99 commit 67d856a

11 files changed

+133
-95
lines changed

credentials_provider_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ func TestCredentialsProviderWithMockIdentityProvider(t *testing.T) {
117117
"test-token",
118118
time.Now().Add(time.Hour),
119119
time.Now(),
120-
int64(time.Hour),
120+
time.Hour.Milliseconds(),
121121
),
122122
}
123123

@@ -159,7 +159,7 @@ func TestCredentialsProviderWithMockIdentityProvider(t *testing.T) {
159159
"test-token",
160160
time.Now().Add(time.Hour),
161161
time.Now(),
162-
int64(time.Hour),
162+
time.Hour.Milliseconds(),
163163
),
164164
}
165165

@@ -219,7 +219,7 @@ func TestCredentialsProviderWithMockIdentityProvider(t *testing.T) {
219219
"initial-token",
220220
time.Now().Add(time.Hour),
221221
time.Now(),
222-
int64(time.Hour),
222+
time.Hour.Milliseconds(),
223223
),
224224
}
225225

@@ -253,7 +253,7 @@ func TestCredentialsProviderWithMockIdentityProvider(t *testing.T) {
253253
"updated-token",
254254
time.Now().Add(time.Hour),
255255
time.Now(),
256-
int64(time.Hour),
256+
time.Hour.Milliseconds(),
257257
)
258258
tm.lock.Unlock()
259259

@@ -329,7 +329,7 @@ func TestCredentialsProviderSubscribe(t *testing.T) {
329329
rawTokenString,
330330
time.Now().Add(tokenExpiration),
331331
time.Now(),
332-
int64(tokenExpiration),
332+
tokenExpiration.Milliseconds(),
333333
)
334334

335335
listener := &mockCredentialsListener{
@@ -386,7 +386,7 @@ func TestCredentialsProviderSubscribe(t *testing.T) {
386386
rawTokenString,
387387
time.Now().Add(tokenExpiration),
388388
time.Now(),
389-
int64(tokenExpiration),
389+
tokenExpiration.Milliseconds(),
390390
)
391391
mtm := &mockTokenManager{done: make(chan struct{})}
392392
// Set the token manager factory in the options
@@ -514,7 +514,7 @@ func TestCredentialsProviderSubscribe(t *testing.T) {
514514
rawTokenString,
515515
time.Now().Add(tokenExpiration),
516516
time.Now(),
517-
int64(tokenExpiration),
517+
tokenExpiration.Milliseconds(),
518518
)
519519
// Set the token manager factory in the options
520520
options := opts

entraid_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func (m *fakeTokenManager) GetToken(forceRefresh bool) (*token.Token, error) {
4848
rawTokenString,
4949
time.Now().Add(tokenExpiration),
5050
time.Now(),
51-
int64(tokenExpiration.Seconds()),
51+
tokenExpiration.Milliseconds(),
5252
)
5353
}
5454
return m.token, m.err

manager/defaults.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package manager
33
import (
44
"errors"
55
"fmt"
6-
"math"
76
"net"
87
"os"
98
"time"
@@ -177,6 +176,6 @@ func (*defaultIdentityProviderResponseParser) ParseResponse(response shared.Iden
177176
rawToken,
178177
expiresOn,
179178
now,
180-
int64(math.Ceil(time.Until(expiresOn).Seconds())),
179+
time.Until(expiresOn).Milliseconds(),
181180
), nil
182181
}

manager/entraid_manager.go

Lines changed: 82 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -238,30 +238,99 @@ func (e *entraidTokenManager) stop() (err error) {
238238
// If the token is nil, it returns 0.
239239
// If the time till expiration is less than the lower bound duration, it returns 0 to renew the token now.
240240
func (e *entraidTokenManager) durationToRenewal(t *token.Token) time.Duration {
241+
return e.durationToRenewalV5(t)
242+
/*
243+
if t == nil {
244+
return 0
245+
}
246+
now := time.Now().UTC()
247+
248+
expirationRefreshTime := t.ReceivedAt().Add(time.Duration(float64(t.TTL()) * float64(time.Millisecond) * e.expirationRefreshRatio))
249+
timeTillExpiration := time.Until(t.ExpirationOn())
250+
251+
// if the expirationRefreshTime is in the past, return 0 to renew the token NOW
252+
if expirationRefreshTime.Before(now) {
253+
return 0
254+
}
255+
256+
// if the timeTillExpiration is less than the lower bound (or 0), return 0 to renew the token NOW
257+
if timeTillExpiration <= e.lowerBoundDuration || timeTillExpiration <= 0 {
258+
return 0
259+
}
260+
261+
// Calculate the time to renew the token based on the expiration refresh ratio
262+
duration := time.Until(expirationRefreshTime)
263+
264+
// if the duration will take us past the lower bound, return the duration to lower bound
265+
if timeTillExpiration-e.lowerBoundDuration < duration {
266+
return timeTillExpiration - e.lowerBoundDuration
267+
}
268+
269+
// return the calculated duration
270+
return duration
271+
*/
272+
}
273+
274+
// durationToRenewalV5 is an ultra-optimized version that uses minimal operations
275+
// and integer math for maximum performance, matching the logic of durationToRenewal.
276+
// It calculates the duration until the next token renewal based on:
277+
// 1. The token's TTL (in milliseconds) and expiration refresh ratio
278+
// 2. The lower bound duration for refresh
279+
// 3. The current time and token's expiration time
280+
func (e *entraidTokenManager) durationToRenewalV5(t *token.Token) time.Duration {
281+
// Fast path: nil token check
241282
if t == nil {
242283
return 0
243284
}
244-
expirationRefreshTime := t.ReceivedAt().Add(time.Duration(float64(t.TTL()) * float64(time.Second) * e.expirationRefreshRatio))
245-
timeTillExpiration := time.Until(t.ExpirationOn())
246-
now := time.Now().UTC()
247285

248-
if expirationRefreshTime.Before(now) {
286+
// Get current time in milliseconds (UTC)
287+
nowMillis := time.Now().UTC().UnixMilli()
288+
289+
// Get expiration time in milliseconds
290+
expMillis := t.ExpirationOn().UnixMilli()
291+
292+
// Fast path: token already expired
293+
if expMillis <= nowMillis {
294+
return 0
295+
}
296+
297+
// Calculate time until expiration in milliseconds
298+
timeTillExpiration := expMillis - nowMillis
299+
300+
// Get lower bound in milliseconds
301+
lowerBoundMillis := e.lowerBoundDuration.Milliseconds()
302+
303+
// Fast path: time until expiration is less than lower bound
304+
if timeTillExpiration <= lowerBoundMillis {
249305
return 0
250306
}
251307

252-
// if the timeTillExpiration is less than the lower bound (or 0), return 0 to renew the token NOW
253-
if timeTillExpiration <= e.lowerBoundDuration || timeTillExpiration <= 0 {
308+
// Calculate refresh time using integer math:
309+
// 1. TTL is already in milliseconds
310+
// 2. Multiply by refresh ratio (as integer percentage)
311+
// 3. Add to received time
312+
ttlMillis := t.TTL() // Already in milliseconds
313+
refreshRatioInt := int64(e.expirationRefreshRatio * 100) // Convert to integer percentage
314+
refreshMillis := (ttlMillis * refreshRatioInt) / 100 // Integer division for ratio
315+
refreshTimeMillis := t.ReceivedAt().UnixMilli() + refreshMillis
316+
317+
// Calculate time until refresh
318+
timeUntilRefresh := refreshTimeMillis - nowMillis
319+
320+
// Fast path: refresh time is in the past
321+
if timeUntilRefresh <= 0 {
254322
return 0
255323
}
256324

257-
// Calculate the time to renew the token based on the expiration refresh ratio
258-
duration := time.Until(expirationRefreshTime)
325+
// Convert to time.Duration for final calculations
326+
timeUntilRefreshDur := time.Duration(timeUntilRefresh) * time.Millisecond
327+
timeTillExpirationDur := time.Duration(timeTillExpiration) * time.Millisecond
259328

260-
// if the duration will take us past the lower bound, return the duration to lower bound
261-
if timeTillExpiration-e.lowerBoundDuration < duration {
262-
return timeTillExpiration - e.lowerBoundDuration
329+
// If refresh would occur after lower bound, use time until lower bound
330+
if timeTillExpirationDur-e.lowerBoundDuration < timeUntilRefreshDur {
331+
return timeTillExpirationDur - e.lowerBoundDuration
263332
}
264333

265-
// return the calculated duration
266-
return duration
334+
// Otherwise use time until refresh
335+
return timeUntilRefreshDur
267336
}

manager/manager_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ var testTokenValid = token.New(
6161
"test",
6262
time.Now().Add(time.Hour),
6363
time.Now(),
64-
int64(time.Hour.Seconds()),
64+
time.Hour.Milliseconds(),
6565
)
6666

6767
func newTestJWTToken(expiresOn time.Time) string {

0 commit comments

Comments
 (0)