Update split SDK to 6.0.2 to fix sync bug (#17060)
* Update split SDK to 6.0.2 to fix sync bug * Vendor and tidy
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
fa2ecad0a9
Коммит
aba00a3cfd
207
vendor/github.com/splitio/go-split-commons/v3/synchronizer/manager.go
сгенерированный
поставляемый
Обычный файл
207
vendor/github.com/splitio/go-split-commons/v3/synchronizer/manager.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,207 @@
|
||||
package synchronizer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/conf"
|
||||
"github.com/splitio/go-split-commons/v3/push"
|
||||
"github.com/splitio/go-split-commons/v3/service"
|
||||
"github.com/splitio/go-split-commons/v3/storage"
|
||||
"github.com/splitio/go-toolkit/v4/backoff"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
"github.com/splitio/go-toolkit/v4/struct/traits/lifecycle"
|
||||
)
|
||||
|
||||
const (
|
||||
// Ready represents ready
|
||||
Ready = iota
|
||||
// StreamingReady ready
|
||||
StreamingReady
|
||||
// Error represents some error in SSE streaming
|
||||
Error
|
||||
)
|
||||
|
||||
// Operation mode constants
|
||||
const (
|
||||
Streaming = iota
|
||||
Polling
|
||||
)
|
||||
|
||||
// Manager interface
|
||||
type Manager interface {
|
||||
Start()
|
||||
Stop()
|
||||
IsRunning() bool
|
||||
}
|
||||
|
||||
// ManagerImpl struct
|
||||
type ManagerImpl struct {
|
||||
synchronizer Synchronizer
|
||||
logger logging.LoggerInterface
|
||||
config conf.AdvancedConfig
|
||||
pushManager push.Manager
|
||||
managerStatus chan int
|
||||
streamingStatus chan int64
|
||||
operationMode int32
|
||||
lifecycle lifecycle.Manager
|
||||
backoff backoff.Interface
|
||||
}
|
||||
|
||||
// NewSynchronizerManager creates new sync manager
|
||||
func NewSynchronizerManager(
|
||||
synchronizer Synchronizer,
|
||||
logger logging.LoggerInterface,
|
||||
config conf.AdvancedConfig,
|
||||
authClient service.AuthClient,
|
||||
splitStorage storage.SplitStorage,
|
||||
managerStatus chan int,
|
||||
) (*ManagerImpl, error) {
|
||||
if managerStatus == nil || cap(managerStatus) < 1 {
|
||||
return nil, errors.New("Status channel cannot be nil nor having capacity")
|
||||
}
|
||||
|
||||
manager := &ManagerImpl{
|
||||
backoff: backoff.New(),
|
||||
synchronizer: synchronizer,
|
||||
logger: logger,
|
||||
config: config,
|
||||
managerStatus: managerStatus,
|
||||
}
|
||||
manager.lifecycle.Setup()
|
||||
if config.StreamingEnabled {
|
||||
streamingStatus := make(chan int64, 1000)
|
||||
pushManager, err := push.NewManager(logger, synchronizer, &config, streamingStatus, authClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
manager.pushManager = pushManager
|
||||
manager.streamingStatus = streamingStatus
|
||||
}
|
||||
|
||||
return manager, nil
|
||||
}
|
||||
|
||||
// IsRunning returns true if is in Streaming or Polling
|
||||
func (s *ManagerImpl) IsRunning() bool {
|
||||
return s.lifecycle.IsRunning()
|
||||
}
|
||||
|
||||
// Start starts synchronization through Split
|
||||
func (s *ManagerImpl) Start() {
|
||||
if !s.lifecycle.BeginInitialization() {
|
||||
s.logger.Info("Manager is already running, skipping start")
|
||||
return
|
||||
}
|
||||
|
||||
// It's safe to drain the channel here, since it's guaranteed that the manager status is "starting"
|
||||
// push manager is still stopped
|
||||
for len(s.managerStatus) > 0 {
|
||||
<-s.managerStatus
|
||||
}
|
||||
err := s.synchronizer.SyncAll(false)
|
||||
if err != nil {
|
||||
defer s.lifecycle.ShutdownComplete()
|
||||
s.managerStatus <- Error
|
||||
return
|
||||
}
|
||||
|
||||
if !s.lifecycle.InitializationComplete() {
|
||||
defer s.lifecycle.ShutdownComplete()
|
||||
return
|
||||
}
|
||||
s.logger.Debug("SyncAll Ready")
|
||||
s.managerStatus <- Ready
|
||||
s.synchronizer.StartPeriodicDataRecording()
|
||||
|
||||
if !s.config.StreamingEnabled {
|
||||
s.logger.Info("SDK initialized in polling mode")
|
||||
s.startPolling()
|
||||
go func() { // create a goroutine that stops everything (the same way the streaming status watcher would)
|
||||
<-s.lifecycle.ShutdownRequested()
|
||||
s.stop()
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
||||
// Start streaming
|
||||
s.logger.Info("SDK Initialized in streaming mode")
|
||||
s.pushManager.Start()
|
||||
go s.pushStatusWatcher()
|
||||
}
|
||||
|
||||
func (s *ManagerImpl) stop() {
|
||||
if s.pushManager != nil {
|
||||
s.pushManager.Stop()
|
||||
}
|
||||
s.synchronizer.StopPeriodicFetching()
|
||||
s.synchronizer.StopPeriodicDataRecording()
|
||||
s.lifecycle.ShutdownComplete()
|
||||
}
|
||||
|
||||
// Stop stop synchronizaation through Split
|
||||
func (s *ManagerImpl) Stop() {
|
||||
if !s.lifecycle.BeginShutdown() {
|
||||
s.logger.Info("sync manager not yet running, skipping shutdown.")
|
||||
return
|
||||
}
|
||||
|
||||
s.logger.Info("Stopping all synchronization tasks")
|
||||
s.lifecycle.AwaitShutdownComplete()
|
||||
}
|
||||
|
||||
func (s *ManagerImpl) pushStatusWatcher() {
|
||||
defer s.stop()
|
||||
for {
|
||||
select {
|
||||
case <-s.lifecycle.ShutdownRequested():
|
||||
return
|
||||
case status := <-s.streamingStatus:
|
||||
switch status {
|
||||
case push.StatusUp:
|
||||
s.stopPolling()
|
||||
s.logger.Info("streaming up and running")
|
||||
s.enableStreaming()
|
||||
s.synchronizer.SyncAll(true)
|
||||
case push.StatusDown:
|
||||
s.logger.Info("streaming down, switchin to polling")
|
||||
s.synchronizer.SyncAll(false)
|
||||
s.pauseStreaming()
|
||||
s.startPolling()
|
||||
case push.StatusRetryableError:
|
||||
howLong := s.backoff.Next()
|
||||
s.logger.Error("retryable error in streaming subsystem. Switching to polling and retrying in ", howLong, " seconds")
|
||||
s.pushManager.Stop()
|
||||
s.synchronizer.SyncAll(false)
|
||||
s.startPolling()
|
||||
time.Sleep(howLong)
|
||||
s.pushManager.Start()
|
||||
case push.StatusNonRetryableError:
|
||||
s.logger.Error("non retryable error in streaming subsystem. Switching to polling until next SDK initialization")
|
||||
s.pushManager.Stop()
|
||||
s.synchronizer.SyncAll(false)
|
||||
s.startPolling()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ManagerImpl) startPolling() {
|
||||
atomic.StoreInt32(&s.operationMode, Polling)
|
||||
s.synchronizer.StartPeriodicFetching()
|
||||
}
|
||||
|
||||
func (s *ManagerImpl) stopPolling() {
|
||||
s.synchronizer.StopPeriodicFetching()
|
||||
}
|
||||
|
||||
func (s *ManagerImpl) pauseStreaming() {
|
||||
s.pushManager.StartWorkers()
|
||||
}
|
||||
|
||||
func (s *ManagerImpl) enableStreaming() {
|
||||
s.pushManager.StartWorkers()
|
||||
atomic.StoreInt32(&s.operationMode, Streaming)
|
||||
s.backoff.Reset()
|
||||
}
|
||||
Ссылка в новой задаче
Block a user