-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcache.go
More file actions
137 lines (123 loc) · 3.81 KB
/
cache.go
File metadata and controls
137 lines (123 loc) · 3.81 KB
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
135
136
137
// Package cache provides a lightweight engine for storing key/value pairs.
package cache
import (
"fmt"
"os"
"path/filepath"
"time"
"github.com/Defacto2/helper"
"github.com/rosedblabs/rosedb/v2"
)
type Cache int // Cache is the type of storage engine.
const (
PouetVote Cache = iota // data cache for the Pouet website, API requests
PouetProduction // data cache for invalid Pouet productions, API requests
DemozooProduction // data cache for invalid Demozoo productions, API requests
Test // test cache
)
// String returns the name of the cache.
func (c Cache) String() string {
return [...]string{
"pouet",
"pouetproduction",
"demozooproduction",
"test",
}[c]
}
const (
ExpiredAt = 7 * 24 * time.Hour // The expiry time for storage engine entries.
SubDir = "cacheDB" // The name of the storage engine subdirectory.
)
// Path returns the absolute path to the storage engine directory.
// If the directory does not exist it will be created.
func (c Cache) Path() (string, error) {
tmp := filepath.Join(os.TempDir(), SubDir, c.String())
if _, err := os.Stat(tmp); err != nil && !os.IsNotExist(err) {
return "", fmt.Errorf("cache path %s: %w", tmp, err)
} else if err == nil {
return tmp, nil
}
err := os.MkdirAll(tmp, helper.DirWriteReadRead)
if err != nil {
return "", fmt.Errorf("cache path, make directory %w", err)
}
return tmp, nil
}
// Write writes a key/value pair to the storage engine.
// The key/value pair will be deleted after the ttl time duration has elapsed.
// If ttl is 0 then the key/value pair will immediately expire.
func (c Cache) Write(key, value string, ttl time.Duration) error {
var err error
options := rosedb.DefaultOptions
options.DirPath, err = c.Path()
if err != nil {
return fmt.Errorf("cache write %w", err)
}
cacheDB, err := rosedb.Open(options)
if err != nil {
return fmt.Errorf("cache write open rosedb %w", err)
}
defer func() { _ = cacheDB.Close() }()
if err := cacheDB.PutWithTTL([]byte(key), []byte(value), ttl); err != nil {
return fmt.Errorf("cache write save to rosedb %w", err)
}
return nil
}
// WriteNoExpire writes a key/value pair to the storage engine.
// The key/value pair will not expire.
func (c Cache) WriteNoExpire(key, value string) error {
var err error
options := rosedb.DefaultOptions
options.DirPath, err = c.Path()
if err != nil {
return fmt.Errorf("cache write no expire %w", err)
}
cacheDB, err := rosedb.Open(options)
if err != nil {
return fmt.Errorf("cache write no expire open rosedb %w", err)
}
defer func() { _ = cacheDB.Close() }()
if err := cacheDB.Put([]byte(key), []byte(value)); err != nil {
return fmt.Errorf("cache write no expire save to rosedb %w", err)
}
return nil
}
// Read returns value from the storage engine.
func (c Cache) Read(id string) (string, error) {
path, err := c.Path()
if err != nil {
return "", fmt.Errorf("cache read %w", err)
}
options := rosedb.DefaultOptions
options.DirPath = path
cacheDB, err := rosedb.Open(options)
if err != nil {
return "", fmt.Errorf("cache read open rosedb %w", err)
}
defer func() { _ = cacheDB.Close() }()
key := []byte(id)
value, err := cacheDB.Get(key)
if err != nil {
return "", fmt.Errorf("cache read from rosedb %q: %w", key, err)
}
return string(value), nil
}
// Delete deletes a key/value pair from the storage engine.
func (c Cache) Delete(id string) error {
path, err := c.Path()
if err != nil {
return fmt.Errorf("cache delete %w", err)
}
options := rosedb.DefaultOptions
options.DirPath = path
cacheDB, err := rosedb.Open(options)
if err != nil {
return fmt.Errorf("cache delete open rosedb %w", err)
}
defer func() { _ = cacheDB.Close() }()
key := []byte(id)
if err := cacheDB.Delete(key); err != nil {
return fmt.Errorf("cache delete %q: %w", key, err)
}
return nil
}