fix: increase default lease TTL to 2 minutes for improved stability

rabbitprincess committed May 9, 2026 at 00:12 UTC c4b5d04399d2f190ed381ae2f8a568c78364b803
3 files changed +36 -13
portal/lease.go
+1 -1
@@ -23,7 +23,7 @@ import (
23 )
24
25 const (
26 - defaultLeaseTTL = 30 * time.Second
26 + defaultLeaseTTL = 2 * time.Minute
27 defaultRegisterChallengeTTL = 2 * time.Minute
28 defaultRegisterChallengeOutstandingPerIP = 32
29 defaultPortReservationGrace = 5 * time.Minute
sdk/api_client.go
+1 -1
@@ -23,7 +23,7 @@ const (
23 defaultDialTimeout = 5 * time.Second
24 defaultRequestTimeout = 15 * time.Second
25 defaultHandshakeTimeout = 15 * time.Second
26 - defaultLeaseTTL = 30 * time.Second
26 + defaultLeaseTTL = 2 * time.Minute
27 defaultRenewBefore = 30 * time.Second
28 defaultReadyTarget = 2
29 defaultRetryWait = 3 * time.Second
sdk/listener.go
+34 -11
@@ -610,25 +610,23 @@ func (l *listener) openQUICBackhaulSession(ctx context.Context) (*quic.Conn, err
610 }
611
612 func (l *listener) runRenewLoop(ctx context.Context) error {
613 - leaseTTL := l.leaseTTL
614 - if leaseTTL <= 0 {
615 - leaseTTL = defaultLeaseTTL
616 - }
617 - interval := leaseTTL / 2
618 - if l.renewBefore > 0 && l.renewBefore < leaseTTL {
619 - interval = leaseTTL - l.renewBefore
620 - }
621 -
613 const wakeThreshold = 10 * time.Second
614
615 for {
616 + interval, err := l.renewDelay(time.Now())
617 + if err != nil {
618 + return err
619 + }
620 +
621 // Round(0) strips the monotonic clock reading so that
622 // time.Since uses wall-clock time. The monotonic clock
623 // freezes during macOS sleep, so without this the elapsed
624 // duration would equal the timer interval, not real time.
625 before := time.Now().Round(0)
630 - if !utils.SleepOrDone(ctx, interval) {
631 - return ctx.Err()
626 + if interval > 0 {
627 + if !utils.SleepOrDone(ctx, interval) {
628 + return ctx.Err()
629 + }
630 }
631 elapsed := time.Since(before)
632
@@ -666,6 +664,31 @@ func (l *listener) runRenewLoop(ctx context.Context) error {
664 }
665 }
666
667 +func (l *listener) renewDelay(now time.Time) (time.Duration, error) {
668 + lease, ok := l.leaseSnapshot()
669 + if !ok || lease.accessToken == "" || !now.Before(lease.expiresAt) {
670 + return 0, errLeaseRefreshRequired
671 + }
672 +
673 + leaseTTL := l.leaseTTL
674 + if leaseTTL <= 0 {
675 + leaseTTL = defaultLeaseTTL
676 + }
677 + renewBefore := l.renewBefore
678 + if renewBefore <= 0 || renewBefore >= leaseTTL {
679 + renewBefore = leaseTTL / 2
680 + }
681 + if renewBefore <= 0 {
682 + renewBefore = time.Second
683 + }
684 +
685 + renewAt := lease.expiresAt.Add(-renewBefore)
686 + if !now.Before(renewAt) {
687 + return 0, nil
688 + }
689 + return renewAt.Sub(now), nil
690 +}
691 +
692 func (l *listener) renewLease(ctx context.Context) error {
693 lease, ok := l.leaseSnapshot()
694 if !ok || lease.accessToken == "" || !time.Now().Before(lease.expiresAt) {