mirror of
https://github.com/openimsdk/open-im-server.git
synced 2025-04-05 19:57:51 +08:00
107 lines
2.3 KiB
Go
107 lines
2.3 KiB
Go
package etcd
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"os/exec"
|
|
"runtime"
|
|
"sync"
|
|
"syscall"
|
|
|
|
"github.com/openimsdk/tools/errs"
|
|
"github.com/openimsdk/tools/log"
|
|
"github.com/openimsdk/tools/utils/datautil"
|
|
clientv3 "go.etcd.io/etcd/client/v3"
|
|
)
|
|
|
|
var (
|
|
ShutDowns []func() error
|
|
)
|
|
|
|
func RegisterShutDown(shutDown ...func() error) {
|
|
ShutDowns = append(ShutDowns, shutDown...)
|
|
}
|
|
|
|
type ConfigManager struct {
|
|
client *clientv3.Client
|
|
watchConfigNames []string
|
|
lock sync.Mutex
|
|
}
|
|
|
|
func BuildKey(s string) string {
|
|
return ConfigKeyPrefix + s
|
|
}
|
|
|
|
func NewConfigManager(client *clientv3.Client, configNames []string) *ConfigManager {
|
|
return &ConfigManager{
|
|
client: client,
|
|
watchConfigNames: datautil.Batch(func(s string) string { return BuildKey(s) }, append(configNames, RestartKey))}
|
|
}
|
|
|
|
func (c *ConfigManager) Watch(ctx context.Context) {
|
|
chans := make([]clientv3.WatchChan, 0, len(c.watchConfigNames))
|
|
for _, name := range c.watchConfigNames {
|
|
chans = append(chans, c.client.Watch(ctx, name, clientv3.WithPrefix()))
|
|
}
|
|
|
|
doWatch := func(watchChan clientv3.WatchChan) {
|
|
for watchResp := range watchChan {
|
|
if watchResp.Err() != nil {
|
|
log.ZError(ctx, "watch err", errs.Wrap(watchResp.Err()))
|
|
continue
|
|
}
|
|
for _, event := range watchResp.Events {
|
|
if event.IsModify() {
|
|
if datautil.Contain(string(event.Kv.Key), c.watchConfigNames...) {
|
|
c.lock.Lock()
|
|
err := restartServer(ctx)
|
|
if err != nil {
|
|
log.ZError(ctx, "restart server err", err)
|
|
}
|
|
c.lock.Unlock()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for _, ch := range chans {
|
|
go doWatch(ch)
|
|
}
|
|
}
|
|
|
|
func restartServer(ctx context.Context) error {
|
|
exePath, err := os.Executable()
|
|
if err != nil {
|
|
return errs.New("get executable path fail").Wrap()
|
|
}
|
|
|
|
args := os.Args
|
|
env := os.Environ()
|
|
|
|
cmd := exec.Command(exePath, args[1:]...)
|
|
cmd.Env = env
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
cmd.Stdin = os.Stdin
|
|
|
|
if runtime.GOOS != "windows" {
|
|
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
|
}
|
|
log.ZInfo(ctx, "shutdown server")
|
|
for _, f := range ShutDowns {
|
|
if err = f(); err != nil {
|
|
log.ZError(ctx, "shutdown fail", err)
|
|
}
|
|
}
|
|
|
|
log.ZInfo(ctx, "restart server")
|
|
err = cmd.Start()
|
|
if err != nil {
|
|
return errs.New("restart server fail").Wrap()
|
|
}
|
|
log.ZInfo(ctx, "cmd start over")
|
|
|
|
os.Exit(0)
|
|
return nil
|
|
}
|