fix: align admin behavior and Kratos integrations
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// 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]
|
||||
}
|
||||
|
||||
type runtimeSnapshot struct {
|
||||
data *Data
|
||||
admin *AdminBackend
|
||||
}
|
||||
|
||||
func NewRuntime(data *Data, admin *AdminBackend) *Runtime {
|
||||
runtime := &Runtime{}
|
||||
runtime.Replace(data, admin)
|
||||
return runtime
|
||||
}
|
||||
|
||||
func cloneData(value *Data) *Data {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
return proto.Clone(value).(*Data)
|
||||
}
|
||||
|
||||
func cloneAdmin(value *AdminBackend) *AdminBackend {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
return proto.Clone(value).(*AdminBackend)
|
||||
}
|
||||
|
||||
func (r *Runtime) Replace(data *Data, admin *AdminBackend) {
|
||||
r.snapshot.Store(&runtimeSnapshot{data: cloneData(data), admin: cloneAdmin(admin)})
|
||||
}
|
||||
|
||||
func (r *Runtime) Data() *Data {
|
||||
snapshot := r.snapshot.Load()
|
||||
if snapshot == nil {
|
||||
return nil
|
||||
}
|
||||
return cloneData(snapshot.data)
|
||||
}
|
||||
|
||||
func (r *Runtime) Admin() *AdminBackend {
|
||||
snapshot := r.snapshot.Load()
|
||||
if snapshot == nil {
|
||||
return nil
|
||||
}
|
||||
return cloneAdmin(snapshot.admin)
|
||||
}
|
||||
|
||||
func (r *Runtime) Values() (*Data, *AdminBackend) {
|
||||
snapshot := r.snapshot.Load()
|
||||
if snapshot == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return cloneData(snapshot.data), cloneAdmin(snapshot.admin)
|
||||
}
|
||||
|
||||
func (r *Runtime) ConfigPath() string {
|
||||
snapshot := r.snapshot.Load()
|
||||
if snapshot == nil || snapshot.admin == nil {
|
||||
return ""
|
||||
}
|
||||
return snapshot.admin.ConfigPath
|
||||
}
|
||||
|
||||
func (r *Runtime) UpdateDatabase(database *Data_Database) {
|
||||
for {
|
||||
current := r.snapshot.Load()
|
||||
var data *Data
|
||||
var admin *AdminBackend
|
||||
if current != nil {
|
||||
data = cloneData(current.data)
|
||||
admin = cloneAdmin(current.admin)
|
||||
}
|
||||
if data == nil {
|
||||
data = &Data{}
|
||||
}
|
||||
data.Database = proto.Clone(database).(*Data_Database)
|
||||
next := &runtimeSnapshot{data: data, admin: admin}
|
||||
if r.snapshot.CompareAndSwap(current, next) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user