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