This commit is contained in:
2026-08-15 01:12:04 +08:00
parent f63acae353
commit 6698e59c3a
45 changed files with 725 additions and 415 deletions
+37 -3
View File
@@ -1,6 +1,7 @@
package conf
import (
"sync"
"sync/atomic"
"google.golang.org/protobuf/proto"
@@ -9,7 +10,10 @@ import (
// Runtime owns the active immutable configuration snapshot. Callers always
// receive clones so a config file reload cannot race with request handling.
type Runtime struct {
snapshot atomic.Pointer[runtimeSnapshot]
snapshot atomic.Pointer[runtimeSnapshot]
mu sync.RWMutex
nextID uint64
listeners map[uint64]func(*Data, *AdminBackend)
}
type runtimeSnapshot struct {
@@ -18,7 +22,7 @@ type runtimeSnapshot struct {
}
func NewRuntime(data *Data, admin *AdminBackend) *Runtime {
runtime := &Runtime{}
runtime := &Runtime{listeners: make(map[uint64]func(*Data, *AdminBackend))}
runtime.Replace(data, admin)
return runtime
}
@@ -38,7 +42,37 @@ func cloneAdmin(value *AdminBackend) *AdminBackend {
}
func (r *Runtime) Replace(data *Data, admin *AdminBackend) {
r.snapshot.Store(&runtimeSnapshot{data: cloneData(data), admin: cloneAdmin(admin)})
data = cloneData(data)
admin = cloneAdmin(admin)
r.snapshot.Store(&runtimeSnapshot{data: data, admin: admin})
r.mu.RLock()
listeners := make([]func(*Data, *AdminBackend), 0, len(r.listeners))
for _, listener := range r.listeners {
listeners = append(listeners, listener)
}
r.mu.RUnlock()
for _, listener := range listeners {
listener(cloneData(data), cloneAdmin(admin))
}
}
// Subscribe registers a callback invoked after every successful runtime
// configuration replacement. It is used by long-lived clients such as the
// logger and other long-lived clients that must follow runtime config changes.
func (r *Runtime) Subscribe(listener func(*Data, *AdminBackend)) func() {
if listener == nil {
return func() {}
}
r.mu.Lock()
r.nextID++
id := r.nextID
r.listeners[id] = listener
r.mu.Unlock()
return func() {
r.mu.Lock()
delete(r.listeners, id)
r.mu.Unlock()
}
}
func (r *Runtime) Data() *Data {