95 lines
1.9 KiB
Go
95 lines
1.9 KiB
Go
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
|
|
}
|
|
}
|
|
}
|