github.com/msales/pkg/v3@v3.24.0/redisx/client.go (about) 1 package redisx 2 3 import ( 4 "github.com/go-redis/redis" 5 ) 6 7 // ScanIterator represents a generic redis scan iterator that works on both 8 // redis Client and ClusterClient 9 type ScanIterator interface { 10 Val() string 11 Next() bool 12 Err() error 13 } 14 15 // ClusterClient represents a redis ClusterClient 16 type ClusterClient interface { 17 ForEachMaster(fn func(client *redis.Client) error) error 18 } 19 20 // ScanCmd represents redis ScanCmd 21 type ScanCmd interface { 22 Iterator() ScanIterator 23 } 24 25 // NewScanIterator returns a scan operator regarding redis client type 26 func NewScanIterator(c interface{}, cursor uint64, match string, count int64) (ScanIterator, error) { 27 _, isCluster := c.(ClusterClient) 28 29 if !isCluster { 30 return c.(redis.Cmdable).Scan(cursor, match, count).Iterator(), nil 31 } 32 33 iterators := make([]ScanIterator, 0) 34 err := c.(ClusterClient).ForEachMaster(func(client *redis.Client) error { 35 iterators = append(iterators, client.Scan(cursor, match, count).Iterator()) 36 37 return nil 38 }) 39 40 if err != nil { 41 return nil, err 42 } 43 44 return &ClusterScanIterator{ 45 curr: 0, 46 iterators: iterators, 47 }, nil 48 } 49 50 // ClusterScanIterator represents redis cluster scan iterator 51 type ClusterScanIterator struct { 52 iterators []ScanIterator 53 54 curr int 55 } 56 57 // Val returns current value pointed by the iterator 58 func (cs *ClusterScanIterator) Val() string { 59 return cs.getCurrentIterator().Val() 60 } 61 62 // Next returns true if there is at least one more value in iterator 63 func (cs *ClusterScanIterator) Next() bool { 64 i := cs.getCurrentIterator() 65 66 if i.Next() { 67 return true 68 } 69 70 for cs.nextIterator() { 71 i = cs.getCurrentIterator() 72 73 if i.Next() { 74 return true 75 } 76 } 77 78 return false 79 } 80 81 // Err returns an error for iterator 82 func (cs *ClusterScanIterator) Err() error { 83 return cs.getCurrentIterator().Err() 84 } 85 86 func (cs *ClusterScanIterator) getCurrentIterator() ScanIterator { 87 return cs.iterators[0] 88 } 89 90 func (cs *ClusterScanIterator) nextIterator() bool { 91 cs.iterators = cs.iterators[1:] 92 93 return len(cs.iterators) > 0 94 }