Skip to content

Commit

Permalink
add support cache for query
Browse files Browse the repository at this point in the history
  • Loading branch information
acoshift committed Apr 6, 2017
1 parent fdaf31e commit 75aba57
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 9 deletions.
4 changes: 2 additions & 2 deletions cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
// Cache interface
type Cache interface {
Get(*datastore.Key, interface{}) error
GetMulti([]*datastore.Key, []interface{}) error
GetMulti([]*datastore.Key, interface{}) error
Set(*datastore.Key, interface{}) error
SetMulti([]*datastore.Key, []interface{}) error
SetMulti([]*datastore.Key, interface{}) error
Del(*datastore.Key) error
DelMulti([]*datastore.Key) error
}
Expand Down
41 changes: 38 additions & 3 deletions cache/redis/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package redis
import (
"bytes"
"encoding/gob"
"reflect"
"time"

"cloud.google.com/go/datastore"
Expand Down Expand Up @@ -45,7 +46,25 @@ func (cache *Cache) Get(key *datastore.Key, dst interface{}) error {
}

// GetMulti gets multi data
func (cache *Cache) GetMulti(keys []*datastore.Key, dst []interface{}) error {
func (cache *Cache) GetMulti(keys []*datastore.Key, dst interface{}) error {
db := cache.Pool.Get()
defer db.Close()
for _, key := range keys {
db.Send("GET", cache.Prefix+key.String())
}
err := db.Flush()
if err != nil {
return err
}
for i := range keys {
b, err := redis.Bytes(db.Receive())
if err != nil {
return err
}
if len(b) > 0 {
decode(b, reflect.Indirect(reflect.ValueOf(dst)).Index(i).Interface())
}
}
return nil
}

Expand All @@ -67,7 +86,21 @@ func (cache *Cache) Set(key *datastore.Key, src interface{}) error {

// SetMulti sets data
func (cache *Cache) SetMulti(keys []*datastore.Key, src interface{}) error {
return nil
db := cache.Pool.Get()
defer db.Close()
db.Send("MULTI")
for i, key := range keys {
b, err := encode(reflect.Indirect(reflect.ValueOf(src)).Index(i).Interface())
if err != nil {
return err
}
if cache.TTL > 0 {
db.Send("SETEX", cache.Prefix+key.String(), int(cache.TTL/time.Second), b)
}
db.Send("SET", cache.Prefix+key.String(), b)
}
_, err := db.Do("EXEC")
return err
}

// Del dels data
Expand All @@ -82,8 +115,10 @@ func (cache *Cache) Del(key *datastore.Key) error {
func (cache *Cache) DelMulti(keys []*datastore.Key) error {
db := cache.Pool.Get()
defer db.Close()
db.Send("MULTI")
for _, key := range keys {
db.Send("DEL", cache.Prefix+key.String())
}
return db.Flush()
_, err := db.Do("EXEC")
return err
}
26 changes: 26 additions & 0 deletions get.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,32 @@ func (client *Client) GetByKeys(ctx context.Context, keys []*datastore.Key, dst
dst = rs.Interface()
}

if client.Cache != nil {
err := client.Cache.GetMulti(keys, dst)
if err == nil {
nfKeys := []*datastore.Key{}
nfMap := []int{}
rf := valueOf(dst)
for i := 0; i < rf.Len(); i++ {
if rf.Index(i).IsNil() {
nfKeys = append(nfKeys, keys[i])
nfMap = append(nfMap, i)
}
}
l := len(nfKeys)
nfDstRf := reflect.MakeSlice(rf.Type(), l, l)
err := client.GetMulti(ctx, keys, nfDstRf.Interface())
for i, k := range nfMap {
rf.Index(k).Set(nfDstRf.Index(i))
}
SetKeys(keys, dst)
if err != nil {
return err
}
return nil
}
}

err := client.GetMulti(ctx, keys, dst)
SetKeys(keys, dst)
if err != nil {
Expand Down
10 changes: 6 additions & 4 deletions query.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ func (client *Client) Query(ctx context.Context, kind string, dst interface{}, q
for _, setter := range qs {
q = setter(q)
}
q = q.KeysOnly()

_, err := client.GetAll(ctx, q, dst)
keys, err := client.GetAll(ctx, q, nil)
if err != nil {
return err
}
return nil
return client.GetByKeys(ctx, keys, dst)
}

// QueryFirst run Get to get the first result
Expand All @@ -31,12 +32,13 @@ func (client *Client) QueryFirst(ctx context.Context, kind string, dst interface
for _, setter := range qs {
q = setter(q)
}
q = q.Limit(1).KeysOnly()

_, err := client.Run(ctx, q).Next(dst)
key, err := client.Run(ctx, q).Next(nil)
if err != nil {
return err
}
return nil
return client.GetByKey(ctx, key, dst)
}

// QueryKeys queries only key
Expand Down

0 comments on commit 75aba57

Please sign in to comment.