github.com/annwntech/go-micro/v2@v2.9.5/util/sync/sync.go (about) 1 // Package syncs will sync multiple stores 2 package sync 3 4 import ( 5 "fmt" 6 "sync" 7 "time" 8 9 "github.com/ef-ds/deque" 10 "github.com/annwntech/go-micro/v2/store" 11 "github.com/pkg/errors" 12 ) 13 14 // Sync implements a sync in for stores 15 type Sync interface { 16 // Implements the store interface 17 store.Store 18 // Force a full sync 19 Sync() error 20 } 21 22 type syncStore struct { 23 storeOpts store.Options 24 syncOpts Options 25 pendingWrites []*deque.Deque 26 pendingWriteTickers []*time.Ticker 27 sync.RWMutex 28 } 29 30 // NewSync returns a new Sync 31 func NewSync(opts ...Option) Sync { 32 c := &syncStore{} 33 for _, o := range opts { 34 o(&c.syncOpts) 35 } 36 if c.syncOpts.SyncInterval == 0 { 37 c.syncOpts.SyncInterval = 1 * time.Minute 38 } 39 if c.syncOpts.SyncMultiplier == 0 { 40 c.syncOpts.SyncMultiplier = 5 41 } 42 return c 43 } 44 45 func (c *syncStore) Close() error { 46 return nil 47 } 48 49 // Init initialises the storeOptions 50 func (c *syncStore) Init(opts ...store.Option) error { 51 for _, o := range opts { 52 o(&c.storeOpts) 53 } 54 if len(c.syncOpts.Stores) == 0 { 55 return errors.New("the sync has no stores") 56 } 57 if c.storeOpts.Context == nil { 58 return errors.New("please provide a context to the sync. Cancelling the context signals that the sync is being disposed and syncs the sync") 59 } 60 for _, s := range c.syncOpts.Stores { 61 if err := s.Init(); err != nil { 62 return errors.Wrapf(err, "Store %s failed to Init()", s.String()) 63 } 64 } 65 c.pendingWrites = make([]*deque.Deque, len(c.syncOpts.Stores)-1) 66 c.pendingWriteTickers = make([]*time.Ticker, len(c.syncOpts.Stores)-1) 67 for i := 0; i < len(c.pendingWrites); i++ { 68 c.pendingWrites[i] = deque.New() 69 c.pendingWrites[i].Init() 70 c.pendingWriteTickers[i] = time.NewTicker(c.syncOpts.SyncInterval * time.Duration(intpow(c.syncOpts.SyncMultiplier, int64(i)))) 71 } 72 go c.syncManager() 73 return nil 74 } 75 76 // Options returns the sync's store options 77 func (c *syncStore) Options() store.Options { 78 return c.storeOpts 79 } 80 81 // String returns a printable string describing the sync 82 func (c *syncStore) String() string { 83 backends := make([]string, len(c.syncOpts.Stores)) 84 for i, s := range c.syncOpts.Stores { 85 backends[i] = s.String() 86 } 87 return fmt.Sprintf("sync %v", backends) 88 } 89 90 func (c *syncStore) List(opts ...store.ListOption) ([]string, error) { 91 return c.syncOpts.Stores[0].List(opts...) 92 } 93 94 func (c *syncStore) Read(key string, opts ...store.ReadOption) ([]*store.Record, error) { 95 return c.syncOpts.Stores[0].Read(key, opts...) 96 } 97 98 func (c *syncStore) Write(r *store.Record, opts ...store.WriteOption) error { 99 return c.syncOpts.Stores[0].Write(r, opts...) 100 } 101 102 // Delete removes a key from the sync 103 func (c *syncStore) Delete(key string, opts ...store.DeleteOption) error { 104 return c.syncOpts.Stores[0].Delete(key, opts...) 105 } 106 107 func (c *syncStore) Sync() error { 108 return nil 109 } 110 111 type internalRecord struct { 112 key string 113 value []byte 114 expiresAt time.Time 115 }