mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
为`gcfg`添加配置文件变更自定义回调,实现了`WatcherAdapter`接口,以下是`AdapterFile`的用法
test.yaml
```
b: "b"
```
```
package main
import (
"fmt"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcfg"
"github.com/gogf/gf/v2/os/gctx"
)
func main() {
ctx := gctx.New()
file, _ := gcfg.NewAdapterFile("test.yaml")
file.Data(ctx)
file.AddWatcher("test", func() {
value := file.MustGet(ctx, "b")
fmt.Println(value.String())
})
server := g.Server()
server.Run()
}
```
使用`g`和默认配置文件
```
file := g.Cfg().GetAdapter().(*gcfg.AdapterFile)
file.AddWatcher("test", func() {
})
file := g.Cfg().GetAdapter().(*gcfg.AdapterFile)
file.RemoveWatcher("test")
```
注意:由于`gf`的`AdapterFile`使用的监听到文件变化删除缓存下一次重新初始化的懒加载方案,所有除了默认加载的`config.xxx`文件外,自定义的配置文件像`test.yaml`之类的都需要在`AddWatcher`前主动读取一次数据进行初始化监听(
`g.Cfg("test").Data(ctx)`)
---------
Co-authored-by: hailaz <739476267@qq.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Hunk Zhu <hunk@joy999.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
107 lines
3.5 KiB
Go
107 lines
3.5 KiB
Go
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
//
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
// If a copy of the MIT was not distributed with this file,
|
|
// You can obtain one at https://github.com/gogf/gf.
|
|
|
|
package gcfg
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/gogf/gf/v2/container/gvar"
|
|
"github.com/gogf/gf/v2/encoding/gjson"
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
|
)
|
|
|
|
var (
|
|
// Compile-time checking for interface implementation.
|
|
_ Adapter = (*AdapterContent)(nil)
|
|
_ WatcherAdapter = (*AdapterContent)(nil)
|
|
)
|
|
|
|
// AdapterContent implements interface Adapter using content.
|
|
// The configuration content supports the coding types as package `gjson`.
|
|
type AdapterContent struct {
|
|
jsonVar *gvar.Var // The pared JSON object for configuration content, type: *gjson.Json.
|
|
watchers *WatcherRegistry // Watchers for watching file changes.
|
|
}
|
|
|
|
// NewAdapterContent returns a new configuration management object using custom content.
|
|
// The parameter `content` specifies the default configuration content for reading.
|
|
func NewAdapterContent(content ...string) (*AdapterContent, error) {
|
|
a := &AdapterContent{
|
|
jsonVar: gvar.New(nil, true),
|
|
watchers: NewWatcherRegistry(),
|
|
}
|
|
if len(content) > 0 {
|
|
if err := a.SetContent(content[0]); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return a, nil
|
|
}
|
|
|
|
// SetContent sets customized configuration content for specified `file`.
|
|
// The `file` is unnecessary param, default is DefaultConfigFile.
|
|
func (a *AdapterContent) SetContent(content string) error {
|
|
j, err := gjson.LoadContent([]byte(content), true)
|
|
if err != nil {
|
|
return gerror.Wrap(err, `load configuration content failed`)
|
|
}
|
|
a.jsonVar.Set(j)
|
|
adapterCtx := NewAdapterContentCtx().WithOperation(OperationSet).WithContent(content)
|
|
a.notifyWatchers(adapterCtx.Ctx)
|
|
return nil
|
|
}
|
|
|
|
// Available checks and returns the backend configuration service is available.
|
|
// The optional parameter `resource` specifies certain configuration resource.
|
|
//
|
|
// Note that this function does not return error as it just does simply check for
|
|
// backend configuration service.
|
|
func (a *AdapterContent) Available(ctx context.Context, resource ...string) (ok bool) {
|
|
return !a.jsonVar.IsNil()
|
|
}
|
|
|
|
// Get retrieves and returns value by specified `pattern` in current resource.
|
|
// Pattern like:
|
|
// "x.y.z" for map item.
|
|
// "x.0.y" for slice item.
|
|
func (a *AdapterContent) Get(ctx context.Context, pattern string) (value any, err error) {
|
|
if a.jsonVar.IsNil() {
|
|
return nil, nil
|
|
}
|
|
return a.jsonVar.Val().(*gjson.Json).Get(pattern).Val(), nil
|
|
}
|
|
|
|
// Data retrieves and returns all configuration data in current resource as map.
|
|
// Note that this function may lead lots of memory usage if configuration data is too large,
|
|
// you can implement this function if necessary.
|
|
func (a *AdapterContent) Data(ctx context.Context) (data map[string]any, err error) {
|
|
if a.jsonVar.IsNil() {
|
|
return nil, nil
|
|
}
|
|
return a.jsonVar.Val().(*gjson.Json).Var().Map(), nil
|
|
}
|
|
|
|
// AddWatcher adds a watcher for the specified configuration file.
|
|
func (a *AdapterContent) AddWatcher(name string, fn func(ctx context.Context)) {
|
|
a.watchers.Add(name, fn)
|
|
}
|
|
|
|
// RemoveWatcher removes the watcher for the specified configuration file.
|
|
func (a *AdapterContent) RemoveWatcher(name string) {
|
|
a.watchers.Remove(name)
|
|
}
|
|
|
|
// GetWatcherNames returns all watcher names.
|
|
func (a *AdapterContent) GetWatcherNames() []string {
|
|
return a.watchers.GetNames()
|
|
}
|
|
|
|
// notifyWatchers notifies all watchers.
|
|
func (a *AdapterContent) notifyWatchers(ctx context.Context) {
|
|
a.watchers.Notify(ctx)
|
|
}
|