layer1: add namespace bootstrap step 11

This commit is contained in:
Naeel
2026-04-26 10:02:37 +03:00
parent 66a3dc2a3c
commit 42acce308f
3 changed files with 55 additions and 0 deletions
@@ -0,0 +1,18 @@
# 2026-04-26 — NamespaceManager rewrite, step 11
## Цель шага
Добавить bootstrap helper для массовой загрузки initial namespace set в manager.
## Что меняем
1. Добавляем `Bootstrap()` в manager interface и реализацию.
2. Метод принимает список namespace-ов и `NamespaceSource`.
3. Метод прогоняет namespaces через `Upsert()` как initial discovered set.
4. Добавляем unit tests на bootstrap.
## Что НЕ меняем
- не подключаем bootstrap к runtime startup path;
- не меняем watcher-ы;
- не трогаем resolver/SA/runtime.
+17
View File
@@ -14,6 +14,7 @@ type NamespaceManager interface {
Snapshot() []string
SnapshotRecords() []NamespaceRecord
Get(name string) (NamespaceRecord, bool)
Bootstrap(namespaces []string, source NamespaceSource, observedAt time.Time) []NamespaceRecord
Subscribe(subscriber NamespaceSubscriber)
SnapshotSubscribers() []string
Upsert(event NamespaceEvent) NamespaceRecord
@@ -40,6 +41,22 @@ func (m *inMemoryNamespaceManager) Subscribe(subscriber NamespaceSubscriber) {
m.subs[subscriber.Name()] = subscriber
}
func (m *inMemoryNamespaceManager) Bootstrap(namespaces []string, source NamespaceSource, observedAt time.Time) []NamespaceRecord {
records := make([]NamespaceRecord, 0, len(namespaces))
for _, namespace := range namespaces {
records = append(records, m.Upsert(NamespaceEvent{
Type: NamespaceEventAdd,
Name: namespace,
Source: source,
ObservedAt: observedAt,
}))
}
sort.Slice(records, func(i, j int) bool {
return records[i].Name < records[j].Name
})
return records
}
func (m *inMemoryNamespaceManager) SnapshotSubscribers() []string {
m.mu.RLock()
defer m.mu.RUnlock()
+20
View File
@@ -137,4 +137,24 @@ func TestNamespaceManagerMarkPartStateDerivesPhase(t *testing.T) {
if record.Phase != NamespacePhaseFailed {
t.Fatalf("expected phase failed, got %s", record.Phase)
}
}
func TestNamespaceManagerBootstrap(t *testing.T) {
manager := NewNamespaceManager()
now := time.Now().UTC()
records := manager.Bootstrap([]string{"tenant-b", "tenant-a"}, NamespaceSourceBackfill, now)
if len(records) != 2 {
t.Fatalf("expected 2 bootstrap records, got %d", len(records))
}
if !reflect.DeepEqual([]string{"tenant-a", "tenant-b"}, manager.Snapshot()) {
t.Fatalf("expected manager snapshot to contain bootstrapped namespaces")
}
record, ok := manager.Get("tenant-a")
if !ok {
t.Fatalf("expected tenant-a after bootstrap")
}
if record.Source != NamespaceSourceBackfill {
t.Fatalf("expected bootstrap source backfill, got %s", record.Source)
}
}