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 {
|
type NamespaceManager interface {
|
||||||
Snapshot() []string
|
Snapshot() []string
|
||||||
SnapshotRecords() []NamespaceRecord
|
SnapshotRecords() []NamespaceRecord
|
||||||
|
Summary() NamespaceManagerSummary
|
||||||
Get(name string) (NamespaceRecord, bool)
|
Get(name string) (NamespaceRecord, bool)
|
||||||
Bootstrap(namespaces []string, source NamespaceSource, observedAt time.Time) []NamespaceRecord
|
Bootstrap(namespaces []string, source NamespaceSource, observedAt time.Time) []NamespaceRecord
|
||||||
BootstrapAndDispatch(ctx context.Context, namespaces []string, source NamespaceSource, observedAt time.Time) ([]NamespaceRecord, error)
|
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) {
|
func (m *inMemoryNamespaceManager) Subscribe(subscriber NamespaceSubscriber) {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
|||||||
@@ -73,6 +73,12 @@ type NamespaceEvent struct {
|
|||||||
ObservedAt time.Time
|
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 {
|
func NewNamespaceEvent(eventType NamespaceEventType, name string, labels map[string]string, source NamespaceSource, observedAt time.Time) NamespaceEvent {
|
||||||
return NamespaceEvent{
|
return NamespaceEvent{
|
||||||
Type: eventType,
|
Type: eventType,
|
||||||
|
|||||||
@@ -154,3 +154,10 @@ func TestNamespaceRemovalStrategyValues(t *testing.T) {
|
|||||||
t.Fatalf("unexpected dispatch-remove strategy value")
|
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 {
|
if record.Name != "tenant-a" || record.Phase != NamespacePhaseDiscovered {
|
||||||
t.Fatalf("unexpected record returned: %+v", record)
|
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) {
|
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) {
|
func TestNamespaceManagerDispatchAdd(t *testing.T) {
|
||||||
manager := NewNamespaceManager()
|
manager := NewNamespaceManager()
|
||||||
manager.Upsert(NamespaceEvent{Type: NamespaceEventAdd, Name: "tenant-a", Source: NamespaceSourceWatcher})
|
manager.Upsert(NamespaceEvent{Type: NamespaceEventAdd, Name: "tenant-a", Source: NamespaceSourceWatcher})
|
||||||
|
|||||||
Reference in New Issue
Block a user