fix(sdk): persist lease expiry for renewal

yoonhyunwoo committed Apr 10, 2026 at 22:24 UTC 200d1e2f2914304bb1c3e61549bc6d524a41b119
2 files changed +20 -13
sdk/api_client.go
+3
@@ -46,6 +46,7 @@ type apiClient struct {
46 rootCAPEM []byte
47 identity types.Identity
48 accessToken string
49 + expiresAt time.Time
50 metadata types.LeaseMetadata
51 resolvedPublicIP string
52 sniPort int
@@ -138,6 +139,7 @@ func (a *apiClient) registerLease(ctx context.Context, ttl time.Duration, udpEna
139
140 a.mu.Lock()
141 a.accessToken = resp.AccessToken
142 + a.expiresAt = resp.ExpiresAt
143 a.sniPort = sniPort
144 a.mu.Unlock()
145 return resp, nil
@@ -226,6 +228,7 @@ func (a *apiClient) renewLease(ctx context.Context, ttl time.Duration) error {
228 a.mu.Lock()
229 if a.accessToken == accessToken {
230 a.accessToken = resp.AccessToken
231 + a.expiresAt = resp.ExpiresAt
232 }
233 a.mu.Unlock()
234 return nil
sdk/listener.go
+17 -13
@@ -423,22 +423,26 @@ func (l *Listener) runRenewLoop(ctx context.Context) {
423 }
424
425 func (l *Listener) renewLease(ctx context.Context) error {
426 - requestCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
427 - err := l.api.renewLease(requestCtx, l.leaseTTL)
428 - cancel()
429 - if err == nil {
430 - return nil
431 - }
432 - if !errors.Is(err, &types.APIRequestError{Code: types.APIErrorCodeLeaseNotFound}) {
433 - return err
426 + l.api.mu.RLock()
427 + expiresAt := l.api.expiresAt
428 + l.api.mu.RUnlock()
429 +
430 + if time.Now().Before(expiresAt) {
431 + requestCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
432 + err := l.api.renewLease(requestCtx, l.leaseTTL)
433 + cancel()
434 +
435 + if err == nil {
436 + return nil
437 + }
438 + if !errors.Is(err, &types.APIRequestError{Code: types.APIErrorCodeLeaseNotFound}) {
439 + return err
440 + }
441 }
442
436 - requestCtx, cancel = context.WithTimeout(ctx, 10*time.Second)
443 + requestCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
444 defer cancel()
438 - if err := l.registerAndConfigure(requestCtx); err != nil {
439 - return err
440 - }
441 - return nil
445 + return l.registerAndConfigure(requestCtx)
446 }
447
448 func (l *Listener) registerAndConfigure(ctx context.Context) error {