layer1: add namespace part helpers step 14

This commit is contained in:
Naeel
2026-04-26 10:05:12 +03:00
parent b3f99b2b6c
commit db4499d8c7
3 changed files with 64 additions and 2 deletions
@@ -0,0 +1,19 @@
# 2026-04-26 — NamespaceManager rewrite, step 14
## Цель шага
Добавить удобные helper-методы для part-state transitions.
## Что меняем
1. В manager interface добавляем:
- `MarkPartRegistering()`
- `MarkPartActive()`
- `MarkPartFailed()`
2. Реализуем их поверх `MarkPartState()`.
3. Добавляем unit tests.
## Что НЕ меняем
- не подключаем helpers к runtime reconcile;
- не трогаем watcher-ы и runtime components.
+20 -1
View File
@@ -19,6 +19,9 @@ type NamespaceManager interface {
SnapshotSubscribers() []string SnapshotSubscribers() []string
Upsert(event NamespaceEvent) NamespaceRecord Upsert(event NamespaceEvent) NamespaceRecord
MarkPartState(namespace string, part string, state NamespacePartState) (NamespaceRecord, bool) MarkPartState(namespace string, part string, state NamespacePartState) (NamespaceRecord, bool)
MarkPartRegistering(namespace string, part string) (NamespaceRecord, bool)
MarkPartActive(namespace string, part string) (NamespaceRecord, bool)
MarkPartFailed(namespace string, part string, err error) (NamespaceRecord, bool)
Remove(name string) bool Remove(name string) bool
} }
@@ -184,6 +187,22 @@ func (m *inMemoryNamespaceManager) MarkPartState(namespace string, part string,
return record.Clone(), true return record.Clone(), true
} }
func (m *inMemoryNamespaceManager) MarkPartRegistering(namespace string, part string) (NamespaceRecord, bool) {
return m.MarkPartState(namespace, part, NamespacePartState{State: NamespacePartStateRegistering})
}
func (m *inMemoryNamespaceManager) MarkPartActive(namespace string, part string) (NamespaceRecord, bool) {
return m.MarkPartState(namespace, part, NamespacePartState{State: NamespacePartStateActive})
}
func (m *inMemoryNamespaceManager) MarkPartFailed(namespace string, part string, err error) (NamespaceRecord, bool) {
lastError := ""
if err != nil {
lastError = err.Error()
}
return m.MarkPartState(namespace, part, NamespacePartState{State: NamespacePartStateFailed, LastError: lastError})
}
func (m *inMemoryNamespaceManager) Remove(name string) bool { func (m *inMemoryNamespaceManager) Remove(name string) bool {
m.mu.Lock() m.mu.Lock()
defer m.mu.Unlock() defer m.mu.Unlock()
@@ -219,4 +238,4 @@ func deriveNamespacePhase(record NamespaceRecord) NamespacePhase {
} }
return NamespacePhaseActive return NamespacePhaseActive
} }
+25 -1
View File
@@ -1,6 +1,7 @@
package utils package utils
import ( import (
"errors"
"reflect" "reflect"
"testing" "testing"
"time" "time"
@@ -159,6 +160,29 @@ func TestNamespaceManagerBootstrap(t *testing.T) {
} }
} }
func TestNamespaceManagerPartStateHelpers(t *testing.T) {
manager := NewNamespaceManager()
manager.Upsert(NamespaceEvent{Type: NamespaceEventAdd, Name: "tenant-a", Source: NamespaceSourceWatcher})
record, ok := manager.MarkPartRegistering("tenant-a", "router")
if !ok || record.Phase != NamespacePhaseRegistering {
t.Fatalf("expected registering helper to set registering phase")
}
record, ok = manager.MarkPartActive("tenant-a", "router")
if !ok || record.Phase != NamespacePhaseActive {
t.Fatalf("expected active helper to set active phase")
}
record, ok = manager.MarkPartFailed("tenant-a", "router", errors.New("boom"))
if !ok || record.Phase != NamespacePhaseFailed {
t.Fatalf("expected failed helper to set failed phase")
}
if record.RegisteredParts["router"].LastError != "boom" {
t.Fatalf("expected failed helper to persist error")
}
}
func TestNewBootstrappedNamespaceManager(t *testing.T) { func TestNewBootstrappedNamespaceManager(t *testing.T) {
resolver := &NamespaceResolver{ resolver := &NamespaceResolver{
FissionResourceNS: map[string]string{ FissionResourceNS: map[string]string{
@@ -178,4 +202,4 @@ func TestNewBootstrappedNamespaceManager(t *testing.T) {
if record.Source != NamespaceSourceEnv { if record.Source != NamespaceSourceEnv {
t.Fatalf("expected env source, got %s", record.Source) t.Fatalf("expected env source, got %s", record.Source)
} }
} }