7f8e3192cd
* Allow common redis and leveldb connections Prevents multiple reopening of redis and leveldb connections to the same place by sharing connections. Further allows for more configurable redis connection type using the redisURI and a leveldbURI scheme. Signed-off-by: Andrew Thornton <art27@cantab.net> * add unit-test Signed-off-by: Andrew Thornton <art27@cantab.net> * as per @lunny Signed-off-by: Andrew Thornton <art27@cantab.net> * add test Signed-off-by: Andrew Thornton <art27@cantab.net> * Update modules/cache/cache_redis.go * Update modules/queue/queue_disk.go * Update modules/cache/cache_redis.go * Update modules/cache/cache_redis.go * Update modules/queue/unique_queue_disk.go * Update modules/queue/queue_disk.go * Update modules/queue/unique_queue_disk.go * Update modules/session/redis.go Co-authored-by: techknowlogick <techknowlogick@gitea.io> Co-authored-by: Lauris BH <lauris@nix.lv>
76 lines
1.4 KiB
Go
76 lines
1.4 KiB
Go
package redis
|
|
|
|
import (
|
|
"sync"
|
|
)
|
|
|
|
// 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
|
|
cmd *ScanCmd
|
|
pos int
|
|
}
|
|
|
|
// Err returns the last iterator error, if any.
|
|
func (it *ScanIterator) Err() error {
|
|
it.mu.Lock()
|
|
err := it.cmd.Err()
|
|
it.mu.Unlock()
|
|
return err
|
|
}
|
|
|
|
// Next advances the cursor and returns true if more values can be read.
|
|
func (it *ScanIterator) Next() bool {
|
|
it.mu.Lock()
|
|
defer it.mu.Unlock()
|
|
|
|
// Instantly return on errors.
|
|
if it.cmd.Err() != nil {
|
|
return false
|
|
}
|
|
|
|
// Advance cursor, check if we are still within range.
|
|
if it.pos < len(it.cmd.page) {
|
|
it.pos++
|
|
return true
|
|
}
|
|
|
|
for {
|
|
// Return if there is no more data to fetch.
|
|
if it.cmd.cursor == 0 {
|
|
return false
|
|
}
|
|
|
|
// Fetch next page.
|
|
if it.cmd.args[0] == "scan" {
|
|
it.cmd.args[1] = it.cmd.cursor
|
|
} else {
|
|
it.cmd.args[2] = it.cmd.cursor
|
|
}
|
|
|
|
err := it.cmd.process(it.cmd)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
it.pos = 1
|
|
|
|
// Redis can occasionally return empty page.
|
|
if len(it.cmd.page) > 0 {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
// Val returns the key/field at the current cursor position.
|
|
func (it *ScanIterator) Val() string {
|
|
var v string
|
|
it.mu.Lock()
|
|
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
|
|
}
|