From 675e3d7213d5857ca88ed27b4e80613ef0da7ff4 Mon Sep 17 00:00:00 2001 From: Marcel Fest Date: Tue, 18 Aug 2026 17:20:24 +0200 Subject: [PATCH] fix(race): again Signed-off-by: Marcel Fest --- pkg/endpoints/endpoints.go | 4 ++-- pkg/services/leader.go | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/pkg/endpoints/endpoints.go b/pkg/endpoints/endpoints.go index d2c8e30a..247184f4 100644 --- a/pkg/endpoints/endpoints.go +++ b/pkg/endpoints/endpoints.go @@ -290,8 +290,8 @@ func (p *Processor) startLeaderElection(svcCtx *servicecontext.Context, service default: leaseNamespace, serviceLease := lease.ServiceName(service) id := lease.NewID(p.config.LeaderElectionType, leaseNamespace, serviceLease) - // The lease is only dropped once its last service is gone, which races - // with this loop noticing its own service context is done. + // The lease is retired once its last service is gone, so an absent one means + // this loop has nothing left to elect for. l := p.leaseMgr.Get(id) if l == nil { return diff --git a/pkg/services/leader.go b/pkg/services/leader.go index 7674d87b..7a1fbd21 100644 --- a/pkg/services/leader.go +++ b/pkg/services/leader.go @@ -46,6 +46,14 @@ func (p *Processor) StartServicesLeaderElection(svcCtx *servicecontext.Context, return fmt.Errorf("no existing lease found for service %q with UID %q", service.Name, service.UID) } + // A cancelled service context means this call belongs to a torn-down incarnation of + // the service. Its replacement is built as Cancel -> Delete -> Add, so the lease + // fetched above may already be the replacement's. Registering on it here would let + // the cleanup goroutine below retire a lease that is still in use. + if err := svcCtx.Ctx.Err(); err != nil { + return fmt.Errorf("service context cancelled before election start: %w", err) + } + isNew := svcLease.Add(objectName) svcLease.Lock()