-
Notifications
You must be signed in to change notification settings - Fork 15
/
cache.go
131 lines (120 loc) · 2.74 KB
/
cache.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package main
import (
"bytes"
"compress/gzip"
"github.com/garyburd/redigo/redis"
"io/ioutil"
"log"
"strings"
"time"
)
const (
gCacheKeyPrefix = "mas:"
gUrlCacheKeyPrefix = "url:"
)
var (
// minimize cache key length
gUrlKeyReplacer = strings.NewReplacer(
"http://", "",
"api.xiami.com/web?v=2.0&app_key=1&r=", "xiami:",
"/detail&", "_",
"music.163.com", "163",
"/api", "",
)
gRedisPool = &redis.Pool{
MaxIdle: 3,
IdleTimeout: 240 * time.Second,
Dial: func() (redis.Conn, error) {
c, err := redis.Dial("tcp", *gFlagRedisAddr)
if nil != err {
log.Printf("failed to connect to redis server %s: %s", *gFlagRedisAddr, err)
return nil, err
}
return c, err
},
TestOnBorrow: func(c redis.Conn, t time.Time) error {
_, err := c.Do("PING")
if nil != err {
log.Printf("failed to ping redis server %s: %s", *gFlagRedisAddr, err)
}
return err
},
}
)
func GenUrlCacheKey(url string) string {
if "" == url {
log.Println("failed to generate url cache key: url is empty")
return ""
}
return gCacheKeyPrefix + gUrlCacheKeyPrefix + gUrlKeyReplacer.Replace(url)
}
func GetCache(key string, decompress bool) []byte {
if "" == key {
return nil
}
// get from redis cache
redisConn := gRedisPool.Get()
defer redisConn.Close()
value, err := redisConn.Do("GET", key)
if nil != err {
log.Printf("failed to get from redis server %s: %s", *gFlagRedisAddr, err)
return nil
}
if nil == value {
return nil
}
valueBytes := value.([]byte)
if !decompress {
return valueBytes
}
// decompress value
buff := bytes.NewBuffer(valueBytes)
gzipRdr, err := gzip.NewReader(buff)
if nil != err {
log.Printf("failed to decompress cached value: %s", err)
return nil
}
defer gzipRdr.Close()
valueBytes, err = ioutil.ReadAll(gzipRdr)
if nil != err {
log.Printf("failed to read cached value: %s", err)
return nil
}
return valueBytes
}
func SetCache(key string, value []byte, expires time.Duration, compress bool) bool {
if "" == key {
return false
}
var err error
if compress {
// compress value
var buff bytes.Buffer
gzipWtr := gzip.NewWriter(&buff)
_, err = gzipWtr.Write(value)
if nil != err {
log.Printf("failed to compress value: %s", err)
return false
}
err = gzipWtr.Close()
if nil != err {
log.Printf("failed to compress value: %s", err)
return false
}
value = buff.Bytes()
}
// save value in redis cache
redisConn := gRedisPool.Get()
defer redisConn.Close()
if expires != 0 {
_, err = redisConn.Do("SETEX", key, expires.Seconds(), value)
} else {
// no expiration if expires is 0
_, err = redisConn.Do("SET", key, value)
}
if nil != err {
log.Printf("failed to send value to redis server %s: %s", *gFlagRedisAddr, err)
return false
}
return true
}