diff --git a/gateway/rpc_storage_handler.go b/gateway/rpc_storage_handler.go index 5cc81bc5e06..55e4385ba97 100644 --- a/gateway/rpc_storage_handler.go +++ b/gateway/rpc_storage_handler.go @@ -798,6 +798,8 @@ func (r *RPCStorageHandler) CheckForReload(orgId string) bool { r.CheckForReload(orgId) } } else if !strings.Contains(err.Error(), "Cannot obtain response during") { + forcer := rpc.NewSyncForcer(r.Gw.StorageConnectionHandler, r.buildNodeInfo) + forcer.SetFirstConnection(true) log.Warning("[RPC STORE] RPC Reload Checker encountered unexpected error: ", err) } diff --git a/rpc/synchronization_forcer.go b/rpc/synchronization_forcer.go index a391d0f332f..07fd7bd0aaa 100644 --- a/rpc/synchronization_forcer.go +++ b/rpc/synchronization_forcer.go @@ -2,30 +2,55 @@ package rpc import ( "errors" + "sync" "github.com/TykTechnologies/tyk/apidef" "github.com/TykTechnologies/tyk/storage" ) type SyncronizerForcer struct { - store *storage.RedisCluster - getNodeDataFunc func() []byte + store *storage.RedisCluster + getNodeDataFunc func() []byte + isFirstConnection bool } +var ( + syncForcerInstance *SyncronizerForcer + syncForcerOnce sync.Once +) + // NewSyncForcer returns a new syncforcer with a connected redis with a key prefix synchronizer-group- for group synchronization control. func NewSyncForcer(controller *storage.ConnectionHandler, getNodeDataFunc func() []byte) *SyncronizerForcer { - sf := &SyncronizerForcer{} - sf.getNodeDataFunc = getNodeDataFunc - sf.store = &storage.RedisCluster{KeyPrefix: "synchronizer-group-", ConnectionHandler: controller} - sf.store.Connect() + syncForcerOnce.Do(func() { + sf := &SyncronizerForcer{} + sf.store = &storage.RedisCluster{KeyPrefix: "synchronizer-group-", ConnectionHandler: controller} + sf.store.Connect() + sf.getNodeDataFunc = getNodeDataFunc + sf.isFirstConnection = true + + syncForcerInstance = sf + }) + + if syncForcerInstance != nil { + syncForcerInstance.getNodeDataFunc = getNodeDataFunc + } + + return syncForcerInstance +} + +func (sf *SyncronizerForcer) SetFirstConnection(isFirstConnection bool) { + sf.isFirstConnection = isFirstConnection +} - return sf +func (sf *SyncronizerForcer) GetIsFirstConnection() bool { + return sf.isFirstConnection } // GroupLoginCallback checks if the groupID key exists in the storage to turn on/off ForceSync param. // If the the key doesn't exists in the storage, it creates it and set ForceSync to true func (sf *SyncronizerForcer) GroupLoginCallback(userKey string, groupID string) interface{} { - shouldForce := false + shouldForce := sf.isFirstConnection + sf.SetFirstConnection(false) _, err := sf.store.GetKey(groupID) if err != nil && errors.Is(err, storage.ErrKeyNotFound) {