From 73d0ab8b70f22cab78e92b2712cb8fd4da944848 Mon Sep 17 00:00:00 2001 From: Robin Date: Tue, 22 Aug 2023 12:56:46 +0200 Subject: [PATCH] fix(connect): Ensure Connect instance runs only once --- .web/docs/guide/config/reload.md | 9 ++++--- pkg/gate/connect.go | 45 ++++++++++++++++++++++++-------- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/.web/docs/guide/config/reload.md b/.web/docs/guide/config/reload.md index 5f8b40f5..ab0a8be2 100644 --- a/.web/docs/guide/config/reload.md +++ b/.web/docs/guide/config/reload.md @@ -1,6 +1,6 @@ # Auto Config Reload -_Gate watches your file for updates._ +_Gate watches your config file for updates._ --- @@ -36,6 +36,7 @@ This feature is always enabled by default, given that you have a config file. ## How to disable it -This can not be disabled. -If you feel like you need to disable it, please [open an issue]( -https://github.com/minekube/gate/issues/new?title=Disable%20auto%20config%20reload&body=I%20want%20to%20disable%20auto%20config%20reload%20because%20...). +Please note that the auto config reload feature cannot be disabled. +If you feel a compelling need to do so, please don't hesitate to [open an issue]( +https://github.com/minekube/gate/issues/new?title=Disable%20auto%20config%20reload&body=I%20want%20to%20disable%20auto%20config%20reload%20because%20...) +on our GitHub repository. diff --git a/pkg/gate/connect.go b/pkg/gate/connect.go index 01c13669..591bd1e5 100644 --- a/pkg/gate/connect.go +++ b/pkg/gate/connect.go @@ -1,7 +1,10 @@ package gate import ( + "bytes" "context" + "crypto/sha1" + "encoding/json" "sync" "github.com/go-logr/logr" @@ -26,29 +29,38 @@ func setupConnect( var ( mu sync.Mutex stopConnect context.CancelFunc - name string + // keep track of current config hash to avoid unnecessary restarts when config didn't change + currentConfigHash []byte ) trigger := func(c *config.Config) { - cfg := c.Connect - if cfg.Enabled && !c.Editions.Java.Enabled { + connect := c.Connect + if connect.Enabled && !c.Editions.Java.Enabled { log.Info("Connect is only supported for Java edition") return } + newConfigHash, err := jsonHash(connect) + if err != nil { + log.Error(err, "error hashing Connect config") + return + } + mu.Lock() defer mu.Unlock() - if (!cfg.Enabled && stopConnect != nil) || - (cfg.Enabled && (stopConnect == nil || cfg.Name != name)) { - if stopConnect != nil { - stopConnect() - stopConnect = nil - } + // check if config changed + if bytes.Equal(newConfigHash, currentConfigHash) { + return // no change } + currentConfigHash = newConfigHash - name = cfg.Name + // stop current Connect if running + if stopConnect != nil { + stopConnect() + stopConnect = nil + } - runnable, err := connectcfg.New(cfg, instance) + runnable, err := connectcfg.New(connect, instance) if err != nil { log.Error(err, "error setting up Connect") return @@ -58,6 +70,7 @@ func setupConnect( runCtx, stopConnect = context.WithCancel(ctx) go func() { + defer stopConnect() if err = runnable.Start(runCtx); err != nil { log.Error(err, "error with Connect") return @@ -76,3 +89,13 @@ func setupConnect( return nil })) } + +// jsonHash returns the sha1 hash of the JSON representation of v. +func jsonHash(v any) ([]byte, error) { + j, err := json.Marshal(v) + if err != nil { + return nil, err + } + h := sha1.Sum(j) + return h[:], nil +}