Use Redis SCAN command in db.Do().
diff --git a/database/database.go b/database/database.go
index e15339a..5e4ef6b 100644
--- a/database/database.go
+++ b/database/database.go
@@ -714,7 +714,6 @@
type PackageInfo struct {
PDoc *doc.Package
- Pkgs []Package
Score float64
Kind string
Size int
@@ -724,48 +723,62 @@
func (db *Database) Do(f func(*PackageInfo) error) error {
c := db.Pool.Get()
defer c.Close()
- keys, err := redis.Values(c.Do("KEYS", "pkg:*"))
- if err != nil {
- return err
- }
- for _, key := range keys {
- values, err := redis.Values(c.Do("HMGET", key, "gob", "score", "kind", "path", "terms", "synopis"))
+ cursor := 0
+ c.Send("SCAN", cursor, "MATCH", "pkg:*")
+ c.Flush()
+ for {
+ // Recieve previous SCAN.
+ values, err := redis.Values(c.Receive())
if err != nil {
return err
}
-
- var (
- pi PackageInfo
- p []byte
- path string
- terms string
- synopsis string
- )
-
- if _, err := redis.Scan(values, &p, &pi.Score, &pi.Kind, &path, &terms, &synopsis); err != nil {
+ var keys [][]byte
+ if _, err := redis.Scan(values, &cursor, &keys); err != nil {
return err
}
-
- if p == nil {
- continue
+ if cursor == 0 {
+ break
}
-
- pi.Size = len(path) + len(p) + len(terms) + len(synopsis)
-
- p, err = snappy.Decode(nil, p)
- if err != nil {
- return fmt.Errorf("snappy decoding %s: %v", path, err)
+ for _, key := range keys {
+ c.Send("HMGET", key, "gob", "score", "kind", "path", "terms", "synopis")
}
+ c.Send("SCAN", cursor, "MATCH", "pkg:*")
+ c.Flush()
+ for _ = range keys {
+ values, err := redis.Values(c.Receive())
+ if err != nil {
+ return err
+ }
- if err := gob.NewDecoder(bytes.NewReader(p)).Decode(&pi.PDoc); err != nil {
- return fmt.Errorf("gob decoding %s: %v", path, err)
- }
- pi.Pkgs, err = db.getSubdirs(c, pi.PDoc.ImportPath, pi.PDoc)
- if err != nil {
- return fmt.Errorf("get subdirs %s: %v", path, err)
- }
- if err := f(&pi); err != nil {
- return fmt.Errorf("func %s: %v", path, err)
+ var (
+ pi PackageInfo
+ p []byte
+ path string
+ terms string
+ synopsis string
+ )
+
+ if _, err := redis.Scan(values, &p, &pi.Score, &pi.Kind, &path, &terms, &synopsis); err != nil {
+ return err
+ }
+
+ if p == nil {
+ continue
+ }
+
+ pi.Size = len(path) + len(p) + len(terms) + len(synopsis)
+
+ p, err = snappy.Decode(nil, p)
+ if err != nil {
+ return fmt.Errorf("snappy decoding %s: %v", path, err)
+ }
+
+ if err := gob.NewDecoder(bytes.NewReader(p)).Decode(&pi.PDoc); err != nil {
+ return fmt.Errorf("gob decoding %s: %v", path, err)
+ }
+ if err := f(&pi); err != nil {
+ return fmt.Errorf("func %s: %v", path, err)
+ }
}
}
return nil