forked from mirror/redis
Merge pull request #470 from go-redis/fix/remove-scanner
Remove Scanner in favor of ScanCmd.
This commit is contained in:
commit
b9cc17bae0
15
command.go
15
command.go
|
@ -683,12 +683,14 @@ type ScanCmd struct {
|
|||
|
||||
page []string
|
||||
cursor uint64
|
||||
|
||||
process func(cmd Cmder) error
|
||||
}
|
||||
|
||||
func NewScanCmd(args ...interface{}) *ScanCmd {
|
||||
cmd := newBaseCmd(args)
|
||||
func NewScanCmd(process func(cmd Cmder) error, args ...interface{}) *ScanCmd {
|
||||
return &ScanCmd{
|
||||
baseCmd: cmd,
|
||||
baseCmd: newBaseCmd(args),
|
||||
process: process,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -709,6 +711,13 @@ func (cmd *ScanCmd) readReply(cn *pool.Conn) error {
|
|||
return cmd.err
|
||||
}
|
||||
|
||||
// Iterator creates a new ScanIterator.
|
||||
func (cmd *ScanCmd) Iterator() *ScanIterator {
|
||||
return &ScanIterator{
|
||||
cmd: cmd,
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type ClusterNode struct {
|
||||
|
|
44
commands.go
44
commands.go
|
@ -71,10 +71,10 @@ type Cmdable interface {
|
|||
SortInterfaces(key string, sort Sort) *SliceCmd
|
||||
TTL(key string) *DurationCmd
|
||||
Type(key string) *StatusCmd
|
||||
Scan(cursor uint64, match string, count int64) Scanner
|
||||
SScan(key string, cursor uint64, match string, count int64) Scanner
|
||||
HScan(key string, cursor uint64, match string, count int64) Scanner
|
||||
ZScan(key string, cursor uint64, match string, count int64) Scanner
|
||||
Scan(cursor uint64, match string, count int64) *ScanCmd
|
||||
SScan(key string, cursor uint64, match string, count int64) *ScanCmd
|
||||
HScan(key string, cursor uint64, match string, count int64) *ScanCmd
|
||||
ZScan(key string, cursor uint64, match string, count int64) *ScanCmd
|
||||
Append(key, value string) *IntCmd
|
||||
BitCount(key string, bitCount *BitCount) *IntCmd
|
||||
BitOpAnd(destKey string, keys ...string) *IntCmd
|
||||
|
@ -515,7 +515,7 @@ func (c *cmdable) Type(key string) *StatusCmd {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func (c *cmdable) Scan(cursor uint64, match string, count int64) Scanner {
|
||||
func (c *cmdable) Scan(cursor uint64, match string, count int64) *ScanCmd {
|
||||
args := []interface{}{"scan", cursor}
|
||||
if match != "" {
|
||||
args = append(args, "match", match)
|
||||
|
@ -523,15 +523,12 @@ func (c *cmdable) Scan(cursor uint64, match string, count int64) Scanner {
|
|||
if count > 0 {
|
||||
args = append(args, "count", count)
|
||||
}
|
||||
cmd := NewScanCmd(args...)
|
||||
cmd := NewScanCmd(c.process, args...)
|
||||
c.process(cmd)
|
||||
return Scanner{
|
||||
client: c,
|
||||
ScanCmd: cmd,
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (c *cmdable) SScan(key string, cursor uint64, match string, count int64) Scanner {
|
||||
func (c *cmdable) SScan(key string, cursor uint64, match string, count int64) *ScanCmd {
|
||||
args := []interface{}{"sscan", key, cursor}
|
||||
if match != "" {
|
||||
args = append(args, "match", match)
|
||||
|
@ -539,15 +536,12 @@ func (c *cmdable) SScan(key string, cursor uint64, match string, count int64) Sc
|
|||
if count > 0 {
|
||||
args = append(args, "count", count)
|
||||
}
|
||||
cmd := NewScanCmd(args...)
|
||||
cmd := NewScanCmd(c.process, args...)
|
||||
c.process(cmd)
|
||||
return Scanner{
|
||||
client: c,
|
||||
ScanCmd: cmd,
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (c *cmdable) HScan(key string, cursor uint64, match string, count int64) Scanner {
|
||||
func (c *cmdable) HScan(key string, cursor uint64, match string, count int64) *ScanCmd {
|
||||
args := []interface{}{"hscan", key, cursor}
|
||||
if match != "" {
|
||||
args = append(args, "match", match)
|
||||
|
@ -555,15 +549,12 @@ func (c *cmdable) HScan(key string, cursor uint64, match string, count int64) Sc
|
|||
if count > 0 {
|
||||
args = append(args, "count", count)
|
||||
}
|
||||
cmd := NewScanCmd(args...)
|
||||
cmd := NewScanCmd(c.process, args...)
|
||||
c.process(cmd)
|
||||
return Scanner{
|
||||
client: c,
|
||||
ScanCmd: cmd,
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (c *cmdable) ZScan(key string, cursor uint64, match string, count int64) Scanner {
|
||||
func (c *cmdable) ZScan(key string, cursor uint64, match string, count int64) *ScanCmd {
|
||||
args := []interface{}{"zscan", key, cursor}
|
||||
if match != "" {
|
||||
args = append(args, "match", match)
|
||||
|
@ -571,12 +562,9 @@ func (c *cmdable) ZScan(key string, cursor uint64, match string, count int64) Sc
|
|||
if count > 0 {
|
||||
args = append(args, "count", count)
|
||||
}
|
||||
cmd := NewScanCmd(args...)
|
||||
cmd := NewScanCmd(c.process, args...)
|
||||
c.process(cmd)
|
||||
return Scanner{
|
||||
client: c,
|
||||
ScanCmd: cmd,
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
41
iterator.go
41
iterator.go
|
@ -2,30 +2,18 @@ package redis
|
|||
|
||||
import "sync"
|
||||
|
||||
type Scanner struct {
|
||||
client *cmdable
|
||||
*ScanCmd
|
||||
}
|
||||
|
||||
// Iterator creates a new ScanIterator.
|
||||
func (s Scanner) Iterator() *ScanIterator {
|
||||
return &ScanIterator{
|
||||
Scanner: s,
|
||||
}
|
||||
}
|
||||
|
||||
// ScanIterator is used to incrementally iterate over a collection of elements.
|
||||
// It's safe for concurrent use by multiple goroutines.
|
||||
type ScanIterator struct {
|
||||
mu sync.Mutex // protects Scanner and pos
|
||||
Scanner
|
||||
cmd *ScanCmd
|
||||
pos int
|
||||
}
|
||||
|
||||
// Err returns the last iterator error, if any.
|
||||
func (it *ScanIterator) Err() error {
|
||||
it.mu.Lock()
|
||||
err := it.ScanCmd.Err()
|
||||
err := it.cmd.Err()
|
||||
it.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
|
@ -36,37 +24,38 @@ func (it *ScanIterator) Next() bool {
|
|||
defer it.mu.Unlock()
|
||||
|
||||
// Instantly return on errors.
|
||||
if it.ScanCmd.Err() != nil {
|
||||
if it.cmd.Err() != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Advance cursor, check if we are still within range.
|
||||
if it.pos < len(it.ScanCmd.page) {
|
||||
if it.pos < len(it.cmd.page) {
|
||||
it.pos++
|
||||
return true
|
||||
}
|
||||
|
||||
for {
|
||||
// Return if there is no more data to fetch.
|
||||
if it.ScanCmd.cursor == 0 {
|
||||
if it.cmd.cursor == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
// Fetch next page.
|
||||
if it.ScanCmd._args[0] == "scan" {
|
||||
it.ScanCmd._args[1] = it.ScanCmd.cursor
|
||||
if it.cmd._args[0] == "scan" {
|
||||
it.cmd._args[1] = it.cmd.cursor
|
||||
} else {
|
||||
it.ScanCmd._args[2] = it.ScanCmd.cursor
|
||||
it.cmd._args[2] = it.cmd.cursor
|
||||
}
|
||||
it.client.process(it.ScanCmd)
|
||||
if it.ScanCmd.Err() != nil {
|
||||
|
||||
err := it.cmd.process(it.cmd)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
it.pos = 1
|
||||
|
||||
// Redis can occasionally return empty page
|
||||
if len(it.ScanCmd.page) > 0 {
|
||||
// Redis can occasionally return empty page.
|
||||
if len(it.cmd.page) > 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -76,8 +65,8 @@ func (it *ScanIterator) Next() bool {
|
|||
func (it *ScanIterator) Val() string {
|
||||
var v string
|
||||
it.mu.Lock()
|
||||
if it.ScanCmd.Err() == nil && it.pos > 0 && it.pos <= len(it.ScanCmd.page) {
|
||||
v = it.ScanCmd.page[it.pos-1]
|
||||
if it.cmd.Err() == nil && it.pos > 0 && it.pos <= len(it.cmd.page) {
|
||||
v = it.cmd.page[it.pos-1]
|
||||
}
|
||||
it.mu.Unlock()
|
||||
return v
|
||||
|
|
Loading…
Reference in New Issue