forked from faabiosr/cachego
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bolt.go
134 lines (105 loc) · 2.64 KB
/
bolt.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
132
133
134
// Package bolt providers a cache driver that stores the cache using BoltDB.
package bolt
import (
"encoding/json"
"errors"
"time"
bt "go.etcd.io/bbolt"
"github.com/faabiosr/cachego"
)
var boltBucket = []byte("cachego")
type (
bolt struct {
db *bt.DB
}
boltContent struct {
Duration int64 `json:"duration"`
Data string `json:"data,omitempty"`
}
)
// New creates an instance of BoltDB cache
func New(db *bt.DB) cachego.Cache {
return &bolt{db}
}
func (b *bolt) read(key string) (*boltContent, error) {
var value []byte
err := b.db.View(func(tx *bt.Tx) error {
if bucket := tx.Bucket(boltBucket); bucket != nil {
value = bucket.Get([]byte(key))
return nil
}
return errors.New("bucket not found")
})
if err != nil {
return nil, err
}
content := &boltContent{}
if err := json.Unmarshal(value, content); err != nil {
return nil, err
}
if content.Duration == 0 {
return content, nil
}
if content.Duration <= time.Now().Unix() {
_ = b.Delete(key)
return nil, cachego.ErrCacheExpired
}
return content, nil
}
// Contains checks if the cached key exists into the BoltDB storage
func (b *bolt) Contains(key string) bool {
_, err := b.read(key)
return err == nil
}
// Delete the cached key from BoltDB storage
func (b *bolt) Delete(key string) error {
return b.db.Update(func(tx *bt.Tx) error {
if bucket := tx.Bucket(boltBucket); bucket != nil {
return bucket.Delete([]byte(key))
}
return errors.New("bucket not found")
})
}
// Fetch retrieves the cached value from key of the BoltDB storage
func (b *bolt) Fetch(key string) (string, error) {
content, err := b.read(key)
if err != nil {
return "", err
}
return content.Data, nil
}
// FetchMulti retrieve multiple cached values from keys of the BoltDB storage
func (b *bolt) FetchMulti(keys []string) map[string]string {
result := make(map[string]string)
for _, key := range keys {
if value, err := b.Fetch(key); err == nil {
result[key] = value
}
}
return result
}
// Flush removes all cached keys of the BoltDB storage
func (b *bolt) Flush() error {
return b.db.Update(func(tx *bt.Tx) error {
return tx.DeleteBucket(boltBucket)
})
}
// Save a value in BoltDB storage by key
func (b *bolt) Save(key string, value string, lifeTime time.Duration) error {
duration := int64(0)
if lifeTime > 0 {
duration = time.Now().Unix() + int64(lifeTime.Seconds())
}
content := &boltContent{duration, value}
data, err := json.Marshal(content)
if err != nil {
return err
}
return b.db.Update(func(tx *bt.Tx) error {
bucket, err := tx.CreateBucketIfNotExists(boltBucket)
if err != nil {
return err
}
return bucket.Put([]byte(key), data)
})
}