Skip to content

Commit 0283906

Browse files
committed
fix: add rwlock for file to ensure thread-safe
1 parent 89077fa commit 0283906

File tree

1 file changed

+34
-11
lines changed

1 file changed

+34
-11
lines changed

file/file.go

+34-11
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import (
55
"crypto/sha256"
66
"encoding/hex"
77
"encoding/json"
8-
"errors"
98
"fmt"
109
"io/ioutil"
1110
"os"
1211
"path/filepath"
12+
"sync"
1313
"time"
1414

1515
"github.com/faabiosr/cachego"
@@ -18,6 +18,7 @@ import (
1818
type (
1919
file struct {
2020
dir string
21+
sync.RWMutex
2122
}
2223

2324
fileContent struct {
@@ -30,7 +31,7 @@ const perm = 0o666
3031

3132
// New creates an instance of File cache
3233
func New(dir string) cachego.Cache {
33-
return &file{dir}
34+
return &file{dir: dir}
3435
}
3536

3637
func (f *file) createName(key string) string {
@@ -42,6 +43,9 @@ func (f *file) createName(key string) string {
4243
}
4344

4445
func (f *file) read(key string) (*fileContent, error) {
46+
f.RLock()
47+
defer f.RUnlock()
48+
4549
value, err := ioutil.ReadFile(f.createName(key))
4650
if err != nil {
4751
return nil, err
@@ -56,22 +60,28 @@ func (f *file) read(key string) (*fileContent, error) {
5660
return content, nil
5761
}
5862

59-
if content.Duration <= time.Now().Unix() {
60-
_ = f.Delete(key)
61-
return nil, errors.New("cache expired")
62-
}
63-
6463
return content, nil
6564
}
6665

6766
// Contains checks if the cached key exists into the File storage
6867
func (f *file) Contains(key string) bool {
69-
_, err := f.read(key)
70-
return err == nil
68+
content, err := f.read(key)
69+
if err != nil {
70+
return false
71+
}
72+
73+
if f.isExpired(content) {
74+
_ = f.Delete(key)
75+
return false
76+
}
77+
return true
7178
}
7279

7380
// Delete the cached key from File storage
7481
func (f *file) Delete(key string) error {
82+
f.Lock()
83+
defer f.Unlock()
84+
7585
_, err := os.Stat(f.createName(key))
7686
if err != nil && os.IsNotExist(err) {
7787
return nil
@@ -87,9 +97,18 @@ func (f *file) Fetch(key string) (string, error) {
8797
return "", err
8898
}
8999

100+
if f.isExpired(content) {
101+
_ = f.Delete(key)
102+
return "", cachego.ErrCacheExpired
103+
}
104+
90105
return content.Data, nil
91106
}
92107

108+
func (f *file) isExpired(content *fileContent) bool {
109+
return content.Duration > 0 && content.Duration <= time.Now().Unix()
110+
}
111+
93112
// FetchMulti retrieve multiple cached values from keys of the File storage
94113
func (f *file) FetchMulti(keys []string) map[string]string {
95114
result := make(map[string]string)
@@ -105,6 +124,9 @@ func (f *file) FetchMulti(keys []string) map[string]string {
105124

106125
// Flush removes all cached keys of the File storage
107126
func (f *file) Flush() error {
127+
f.Lock()
128+
defer f.Unlock()
129+
108130
dir, err := os.Open(f.dir)
109131
if err != nil {
110132
return err
@@ -125,14 +147,15 @@ func (f *file) Flush() error {
125147

126148
// Save a value in File storage by key
127149
func (f *file) Save(key string, value string, lifeTime time.Duration) error {
128-
duration := int64(0)
150+
f.Lock()
151+
defer f.Unlock()
129152

153+
duration := int64(0)
130154
if lifeTime > 0 {
131155
duration = time.Now().Unix() + int64(lifeTime.Seconds())
132156
}
133157

134158
content := &fileContent{duration, value}
135-
136159
data, err := json.Marshal(content)
137160
if err != nil {
138161
return err

0 commit comments

Comments
 (0)