layer1: add namespace manager summary
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
# 2026-04-26 — NamespaceManager rewrite, step 45
|
||||
|
||||
## Цель шага
|
||||
|
||||
Подготовить компактный status/debug surface для `NamespaceManager`.
|
||||
|
||||
## Что меняем
|
||||
|
||||
1. Добавляем `NamespaceManagerSummary`.
|
||||
2. В `NamespaceManager` добавляем `Summary()`.
|
||||
3. Summary считает:
|
||||
- общее число namespace-ов;
|
||||
- число по phase;
|
||||
- список subscriber-ов.
|
||||
4. Добавляем unit tests.
|
||||
|
||||
## Что НЕ меняем
|
||||
|
||||
- не публикуем summary наружу через HTTP;
|
||||
- не меняем watcher behavior.
|
||||
@@ -59,6 +59,7 @@ func (s NamespaceSubscriberFuncs) OnNamespaceResync(ctx context.Context, record
|
||||
type NamespaceManager interface {
|
||||
Snapshot() []string
|
||||
SnapshotRecords() []NamespaceRecord
|
||||
Summary() NamespaceManagerSummary
|
||||
Get(name string) (NamespaceRecord, bool)
|
||||
Bootstrap(namespaces []string, source NamespaceSource, observedAt time.Time) []NamespaceRecord
|
||||
BootstrapAndDispatch(ctx context.Context, namespaces []string, source NamespaceSource, observedAt time.Time) ([]NamespaceRecord, error)
|
||||
@@ -240,6 +241,19 @@ func StartManagedNamespaceWatcher(ctx context.Context, logger *zap.Logger, compo
|
||||
})
|
||||
}
|
||||
|
||||
func (m *inMemoryNamespaceManager) Summary() NamespaceManagerSummary {
|
||||
records := m.SnapshotRecords()
|
||||
summary := NamespaceManagerSummary{
|
||||
TotalNamespaces: len(records),
|
||||
PhaseCounts: make(map[NamespacePhase]int),
|
||||
Subscribers: m.SnapshotSubscribers(),
|
||||
}
|
||||
for _, record := range records {
|
||||
summary.PhaseCounts[record.Phase]++
|
||||
}
|
||||
return summary
|
||||
}
|
||||
|
||||
func (m *inMemoryNamespaceManager) Subscribe(subscriber NamespaceSubscriber) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
@@ -73,6 +73,12 @@ type NamespaceEvent struct {
|
||||
ObservedAt time.Time
|
||||
}
|
||||
|
||||
type NamespaceManagerSummary struct {
|
||||
TotalNamespaces int
|
||||
PhaseCounts map[NamespacePhase]int
|
||||
Subscribers []string
|
||||
}
|
||||
|
||||
func NewNamespaceEvent(eventType NamespaceEventType, name string, labels map[string]string, source NamespaceSource, observedAt time.Time) NamespaceEvent {
|
||||
return NamespaceEvent{
|
||||
Type: eventType,
|
||||
|
||||
@@ -154,3 +154,10 @@ func TestNamespaceRemovalStrategyValues(t *testing.T) {
|
||||
t.Fatalf("unexpected dispatch-remove strategy value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamespaceManagerSummaryZeroValue(t *testing.T) {
|
||||
summary := NamespaceManagerSummary{}
|
||||
if summary.TotalNamespaces != 0 {
|
||||
t.Fatalf("expected zero total namespaces")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,10 @@ func TestNamespaceManagerSnapshotAndGet(t *testing.T) {
|
||||
if record.Name != "tenant-a" || record.Phase != NamespacePhaseDiscovered {
|
||||
t.Fatalf("unexpected record returned: %+v", record)
|
||||
}
|
||||
summary := manager.Summary()
|
||||
if summary.TotalNamespaces != 2 {
|
||||
t.Fatalf("expected summary total namespaces to be 2, got %d", summary.TotalNamespaces)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamespaceManagerUpsertIncrementsGeneration(t *testing.T) {
|
||||
@@ -448,6 +452,29 @@ func TestPrepareManagedNamespaceWatcher(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamespaceManagerSummary(t *testing.T) {
|
||||
manager := NewNamespaceManager()
|
||||
manager.Upsert(NamespaceEvent{Type: NamespaceEventAdd, Name: "tenant-a", Source: NamespaceSourceWatcher})
|
||||
manager.Upsert(NamespaceEvent{Type: NamespaceEventAdd, Name: "tenant-b", Source: NamespaceSourceWatcher})
|
||||
_, _ = manager.MarkPartRegistering("tenant-a", "router")
|
||||
manager.Upsert(NamespaceEvent{Type: NamespaceEventRemove, Name: "tenant-b", Source: NamespaceSourceWatcher})
|
||||
manager.Subscribe(&testNamespaceSubscriber{name: "router"})
|
||||
|
||||
summary := manager.Summary()
|
||||
if summary.TotalNamespaces != 2 {
|
||||
t.Fatalf("expected total namespaces 2, got %d", summary.TotalNamespaces)
|
||||
}
|
||||
if summary.PhaseCounts[NamespacePhaseRegistering] != 1 {
|
||||
t.Fatalf("expected one registering namespace")
|
||||
}
|
||||
if summary.PhaseCounts[NamespacePhaseRemoved] != 1 {
|
||||
t.Fatalf("expected one removed namespace")
|
||||
}
|
||||
if !reflect.DeepEqual([]string{"router"}, summary.Subscribers) {
|
||||
t.Fatalf("expected router subscriber in summary")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamespaceManagerDispatchAdd(t *testing.T) {
|
||||
manager := NewNamespaceManager()
|
||||
manager.Upsert(NamespaceEvent{Type: NamespaceEventAdd, Name: "tenant-a", Source: NamespaceSourceWatcher})
|
||||
|
||||
Reference in New Issue
Block a user