From d3568d9c350ce77180f389bbece3e74c1f6e1f96 Mon Sep 17 00:00:00 2001 From: yusing Date: Thu, 5 Jun 2025 01:16:53 +0800 Subject: [PATCH] fix: conflict error on load-balanced and excluded routes --- internal/route/common.go | 3 +++ internal/route/reverse_proxy.go | 10 ++++++---- internal/route/route.go | 19 +++++++++++++++++-- internal/utils/pool/pool.go | 15 +++++++++++++++ 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/internal/route/common.go b/internal/route/common.go index 01c22b0..8a6c663 100644 --- a/internal/route/common.go +++ b/internal/route/common.go @@ -6,6 +6,9 @@ import ( ) func checkExists(r routes.Route) gperr.Error { + if r.UseLoadBalance() { // skip checking for load balanced routes + return nil + } var ( existing routes.Route ok bool diff --git a/internal/route/reverse_proxy.go b/internal/route/reverse_proxy.go index f614cf8..88bbd19 100755 --- a/internal/route/reverse_proxy.go +++ b/internal/route/reverse_proxy.go @@ -192,16 +192,18 @@ func (r *ReveseProxyRoute) addToLoadBalancer(parent task.Parent) { _ = lb.Start(parent) // always return nil linked = &ReveseProxyRoute{ Route: &Route{ - Alias: cfg.Link, + Alias: cfg.Link + "-loadbalancer", Homepage: r.Homepage, }, HealthMon: lb, loadBalancer: lb, handler: lb, } - routes.HTTP.Add(linked) - r.task.OnFinished("entrypoint_remove_route", func() { - routes.HTTP.Del(linked) + routes.HTTP.AddKey(cfg.Link, linked) + routes.All.AddKey(cfg.Link, linked) + r.task.OnFinished("remove_loadbalancer_route", func() { + routes.HTTP.DelKey(cfg.Link) + routes.All.DelKey(cfg.Link) }) } r.loadBalancer = lb diff --git a/internal/route/route.go b/internal/route/route.go index 09a382c..684a4db 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -66,7 +66,7 @@ type ( LisURL *net.URL `json:"lurl,omitempty"` ProxyURL *net.URL `json:"purl,omitempty"` - Excluded bool `json:"excluded"` + Excluded *bool `json:"excluded"` impl routes.Route isValidated bool @@ -233,7 +233,8 @@ func (r *Route) Validate() gperr.Error { } r.impl = impl - r.Excluded = r.ShouldExclude() + excluded := r.ShouldExclude() + r.Excluded = &excluded return nil } @@ -326,6 +327,14 @@ func (r *Route) Name() string { // Key implements pool.Object. func (r *Route) Key() string { + if r.UseLoadBalance() || r.ShouldExclude() { + // for excluded routes and load balanced routes, use provider:alias[-container_id[:8]] as key to make them unique. + if r.Container != nil { + return r.Provider + ":" + r.Alias + "-" + r.Container.ContainerID[:8] + } + return r.Provider + ":" + r.Alias + } + // we need to use alias as key for non-excluded routes because it's being used for subdomain / fqdn lookup for http routes. return r.Alias } @@ -394,6 +403,12 @@ func (r *Route) IsZeroPort() bool { } func (r *Route) ShouldExclude() bool { + if r.lastError != nil { + return true + } + if r.Excluded != nil { + return *r.Excluded + } if r.Container != nil { switch { case r.Container.IsExcluded: diff --git a/internal/utils/pool/pool.go b/internal/utils/pool/pool.go index 2056b70..a029af9 100644 --- a/internal/utils/pool/pool.go +++ b/internal/utils/pool/pool.go @@ -39,6 +39,14 @@ func (p *Pool[T]) Add(obj T) { } } +func (p *Pool[T]) AddKey(key string, obj T) { + p.checkExists(key) + p.m.Store(key, obj) + if !p.disableLog { + log.Info().Msgf("%s: added %s", p.name, obj.Name()) + } +} + func (p *Pool[T]) AddIfNotExists(obj T) (actual T, added bool) { actual, loaded := p.m.LoadOrStore(obj.Key(), obj) return actual, !loaded @@ -51,6 +59,13 @@ func (p *Pool[T]) Del(obj T) { } } +func (p *Pool[T]) DelKey(key string) { + p.m.Delete(key) + if !p.disableLog { + log.Info().Msgf("%s: removed %s", p.name, key) + } +} + func (p *Pool[T]) Get(key string) (T, bool) { return p.m.Load(key) }