diff --git a/core/services/failover/manager.go b/core/services/failover/manager.go index ae997a5ad..8a9ea7e0b 100644 --- a/core/services/failover/manager.go +++ b/core/services/failover/manager.go @@ -87,7 +87,10 @@ type Manager struct { } type targetState struct { - name string + name string + // serving is the model that serves this target: its own name, or the + // model an alias points to. Model loading and eviction only know it. + serving string kind Kind warm bool state TargetState @@ -196,6 +199,7 @@ func (m *Manager) syncLocked() { continue } ts.kind = KindOf(tc) + ts.serving = tc.Name if t.Warm && ts.kind == KindLocal { ts.warm = true } @@ -224,9 +228,9 @@ func (m *Manager) syncLocked() { m.recomputeLocked(ch, "") } var warm []string - for name, ts := range m.targets { - if ts.warm { - warm = append(warm, name) + for _, ts := range m.targets { + if ts.warm && ts.serving != "" && !slices.Contains(warm, ts.serving) { + warm = append(warm, ts.serving) } } sort.Strings(warm) diff --git a/core/services/failover/manager_test.go b/core/services/failover/manager_test.go index 75a773f04..b74e32920 100644 --- a/core/services/failover/manager_test.go +++ b/core/services/failover/manager_test.go @@ -248,6 +248,18 @@ var _ = Describe("Manager", func() { Expect(m.WarmTargets()).To(Equal([]string{"b"})) }) + It("reports the model an alias target serves from as warm, not the alias", func() { + var got []string + m = New(src, WithClock(clock), WithOnWarmChanged(func(w []string) { got = w })) + // The preloader and the eviction guard work on loaded model names; an + // alias is never loaded under its own name. + src.Put(config.ModelConfig{Name: "al", Alias: "b"}) + src.Put(chainCfg("chain", nil, t("a"), warmT("al"))) + m.Sync() + Expect(got).To(Equal([]string{"b"})) + Expect(m.WarmTargets()).To(Equal([]string{"b"})) + }) + It("closes a subscription on cancel", func() { events, cancel := m.Subscribe(1) cancel()