mirror of
https://github.com/yusing/godoxy.git
synced 2026-03-21 16:49:03 +01:00
feat(route): implement PreferOver method for deterministic route replacement
This commit is contained in:
@@ -497,6 +497,45 @@ func (r *Route) DisplayName() string {
|
||||
return r.Homepage.Name
|
||||
}
|
||||
|
||||
// PreferOver implements pool.Preferable to resolve duplicate route keys deterministically.
|
||||
// Preference policy:
|
||||
// - Prefer routes with rules over routes without rules.
|
||||
// - If rules tie, prefer non-docker routes (explicit config) over docker-discovered routes.
|
||||
// - Otherwise, prefer the new route to preserve existing semantics.
|
||||
func (r *Route) PreferOver(other any) bool {
|
||||
// Try to get the underlying *Route of the other value
|
||||
var or *Route
|
||||
switch v := other.(type) {
|
||||
case *Route:
|
||||
or = v
|
||||
case *ReveseProxyRoute:
|
||||
or = v.Route
|
||||
case *FileServer:
|
||||
or = v.Route
|
||||
case *StreamRoute:
|
||||
or = v.Route
|
||||
default:
|
||||
// Unknown type, allow replacement
|
||||
return true
|
||||
}
|
||||
|
||||
// Prefer routes that have rules
|
||||
if len(r.Rules) > 0 && len(or.Rules) == 0 {
|
||||
return true
|
||||
}
|
||||
if len(r.Rules) == 0 && len(or.Rules) > 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
// Prefer explicit (non-docker) over docker auto-discovered
|
||||
if (r.Container == nil) != (or.Container == nil) {
|
||||
return r.Container == nil
|
||||
}
|
||||
|
||||
// Default: allow replacement
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *Route) ContainerInfo() *types.Container {
|
||||
return r.Container
|
||||
}
|
||||
|
||||
@@ -14,6 +14,12 @@ type (
|
||||
name string
|
||||
disableLog atomic.Bool
|
||||
}
|
||||
// Preferable allows an object to express deterministic replacement preference
|
||||
// when multiple objects with the same key are added to the pool.
|
||||
// If new.PreferOver(old) returns true, the new object replaces the old one.
|
||||
Preferable interface {
|
||||
PreferOver(other any) bool
|
||||
}
|
||||
Object interface {
|
||||
Key() string
|
||||
Name() string
|
||||
@@ -37,12 +43,18 @@ func (p *Pool[T]) Name() string {
|
||||
}
|
||||
|
||||
func (p *Pool[T]) Add(obj T) {
|
||||
p.checkExists(obj.Key())
|
||||
p.m.Store(obj.Key(), obj)
|
||||
p.logAction("added", obj)
|
||||
p.AddKey(obj.Key(), obj)
|
||||
}
|
||||
|
||||
func (p *Pool[T]) AddKey(key string, obj T) {
|
||||
if cur, exists := p.m.Load(key); exists {
|
||||
if newPref, ok := any(obj).(Preferable); ok {
|
||||
if !newPref.PreferOver(cur) {
|
||||
// keep existing
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
p.checkExists(key)
|
||||
p.m.Store(key, obj)
|
||||
p.logAction("added", obj)
|
||||
|
||||
Reference in New Issue
Block a user