Skip to content

Commit ffb0c21

Browse files
authored
feature: implement drivers (#1)
* New Drivers * Fix typo repo name * BuntDB layer
1 parent 30b1d0f commit ffb0c21

File tree

5 files changed

+426
-1
lines changed

5 files changed

+426
-1
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ require (
1010

1111
require (
1212
github.com/tidwall/btree v0.6.1 // indirect
13-
github.com/tidwall/gjson v1.10.2 // indirect
13+
github.com/tidwall/gjson v1.11.0 // indirect
1414
github.com/tidwall/grect v0.1.3 // indirect
1515
github.com/tidwall/match v1.1.1 // indirect
1616
github.com/tidwall/pretty v1.2.0 // indirect

v1/cache/drivers/buntdb/buntdb.go

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
package buntdblayer
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"os"
7+
"path"
8+
"time"
9+
10+
"github.com/rs/zerolog"
11+
"github.com/thiagozs/go-cache/v1/cache/drivers"
12+
"github.com/thiagozs/go-utils/files"
13+
"github.com/tidwall/buntdb"
14+
)
15+
16+
type BuntDBLayerRepo interface {
17+
WriteKeyVal(key string, val string) error
18+
WriteKeyValTTL(key string, val string, ttlSeconds int) error
19+
DeleteKey(key string) (string, error)
20+
WriteKeyValAsJSON(key string, val interface{}) error
21+
WriteKeyValAsJSONTTL(key string, val interface{}, ttlSeconds int) error
22+
GetVal(key string) (string, error)
23+
}
24+
25+
type buntdblayer struct {
26+
db *buntdb.DB
27+
file string
28+
folder string
29+
ttl int
30+
log zerolog.Logger
31+
}
32+
33+
func NewBuntDB(opts ...drivers.Options) (BuntDBLayerRepo, error) {
34+
mts := &drivers.OptionsCfg{}
35+
for _, op := range opts {
36+
err := op(mts)
37+
if err != nil {
38+
return nil, err
39+
}
40+
}
41+
return newInstance(mts.GetFolder(), mts.GetFileName(),
42+
mts.GetTTL(), mts.GetLogDebug(), mts.GetLogDisable())
43+
}
44+
45+
func newInstance(folder, file string, ttl int,
46+
logDebug bool, logDisable bool) (BuntDBLayerRepo, error) {
47+
48+
zerolog.SetGlobalLevel(zerolog.InfoLevel)
49+
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
50+
log := zerolog.New(os.Stderr).With().Timestamp().Logger()
51+
52+
if logDebug {
53+
log.Info().Bool("debug", true).Msg("log debug")
54+
zerolog.SetGlobalLevel(zerolog.DebugLevel)
55+
}
56+
57+
if logDisable {
58+
zerolog.SetGlobalLevel(zerolog.Disabled)
59+
}
60+
61+
pathFile := fmt.Sprintf("%s/%s", folder, file)
62+
63+
log.Info().Str("path_file", pathFile).Msg("file database")
64+
if !files.FileExists(pathFile) {
65+
if err := files.MkdirAll(path.Dir(pathFile)); err != nil {
66+
log.Info().Err(err).Msg("fail create a directory")
67+
return nil, err
68+
}
69+
}
70+
71+
db, err := buntdb.Open(pathFile)
72+
if err != nil {
73+
log.Info().Err(err).Msg("could not open data file path")
74+
return nil, err
75+
}
76+
return &buntdblayer{
77+
db: db,
78+
folder: folder,
79+
file: file,
80+
ttl: ttl,
81+
log: log,
82+
}, nil
83+
}
84+
85+
func (d *buntdblayer) GetVal(key string) (string, error) {
86+
var value string
87+
err := d.db.View(func(tx *buntdb.Tx) error {
88+
val, err := tx.Get(key)
89+
if err != nil {
90+
d.log.Debug().Err(err).Msg("GetVal")
91+
return err
92+
}
93+
value = val
94+
return nil
95+
})
96+
return value, err
97+
}
98+
99+
func (d *buntdblayer) DeleteKey(key string) (string, error) {
100+
var value string
101+
err := d.db.Update(func(tx *buntdb.Tx) error {
102+
val, err := tx.Delete(key)
103+
if err != nil {
104+
d.log.Debug().Err(err).Msg("DeleteKey")
105+
return err
106+
}
107+
value = val
108+
return nil
109+
})
110+
return value, err
111+
}
112+
113+
func (d *buntdblayer) WriteKeyVal(key string, val string) error {
114+
err := d.db.Update(func(tx *buntdb.Tx) error {
115+
_, _, err := tx.Set(key, val, nil)
116+
d.log.Debug().Err(err).Msg("WriteKeyVal")
117+
return err
118+
})
119+
if err != nil {
120+
return err
121+
}
122+
return nil
123+
}
124+
125+
func (d *buntdblayer) WriteKeyValTTL(key string, val string, ttlSeconds int) error {
126+
if ttlSeconds == 0 {
127+
d.log.Debug().Int("ttl_seconds", d.ttl).Msg("WriteKeyValTTL")
128+
ttlSeconds = d.ttl
129+
}
130+
err := d.db.Update(func(tx *buntdb.Tx) error {
131+
_, _, err := tx.Set(key, val, &buntdb.SetOptions{Expires: true, TTL: time.Second * time.Duration(ttlSeconds)})
132+
d.log.Debug().Str("method", "update").Err(err).Msg("WriteKeyValTTL")
133+
return err
134+
})
135+
if err != nil {
136+
d.log.Debug().Err(err).Msg("WriteKeyValTTL")
137+
return err
138+
}
139+
return nil
140+
}
141+
142+
func (d *buntdblayer) WriteKeyValAsJSON(key string, val interface{}) error {
143+
valueAsJSON, err := json.Marshal(val)
144+
if err != nil {
145+
d.log.Debug().Str("method", "json.Marshal").Err(err).Msg("WriteKeyValAsJSON")
146+
return err
147+
}
148+
return d.WriteKeyVal(key, string(valueAsJSON))
149+
}
150+
151+
func (d *buntdblayer) WriteKeyValAsJSONTTL(key string, val interface{}, ttlSeconds int) error {
152+
valueAsJSON, err := json.Marshal(val)
153+
if err != nil {
154+
d.log.Debug().Str("method", "json.Marshal").Err(err).Msg("WriteKeyValAsJSONTTL")
155+
return err
156+
}
157+
return d.WriteKeyValTTL(key, string(valueAsJSON), ttlSeconds)
158+
}

v1/cache/drivers/drivers.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package drivers
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/thiagozs/go-cache/v1/cache/drivers/buntdblayer"
7+
"github.com/thiagozs/go-cache/v1/cache/drivers/redislayer"
8+
)
9+
10+
type Driver int
11+
12+
const (
13+
BUNTDB Driver = iota
14+
REDIS
15+
)
16+
17+
func (d Driver) String() string {
18+
return []string{"buntdb", "redis"}[d]
19+
}
20+
21+
type Drivers struct {
22+
db DriverPort
23+
}
24+
25+
type DriverPort interface {
26+
WriteKeyVal(key string, val string) error
27+
WriteKeyValTTL(key string, val string, ttlSeconds int) error
28+
DeleteKey(key string) (string, error)
29+
WriteKeyValAsJSON(key string, val interface{}) error
30+
WriteKeyValAsJSONTTL(key string, val interface{}, ttlSeconds int) error
31+
GetVal(key string) (string, error)
32+
}
33+
34+
func NewDriver(driver Driver, opts ...Options) (DriverPort, error) {
35+
switch driver {
36+
case BUNTDB:
37+
return buntdblayer.NewBuntDB(opts...), nil
38+
case REDIS:
39+
return redislayer.NewRedis(opts...), nil
40+
}
41+
return &Drivers{}, fmt.Errorf("unknown driver type: %s", driver.String())
42+
}
43+
44+
func (d *Drivers) WriteKeyVal(key string, val string) error {
45+
return d.db.WriteKeyVal(key, val)
46+
}
47+
48+
func (d *Drivers) WriteKeyValTTL(key string, val string, ttlSeconds int) error {
49+
return d.db.WriteKeyValTTL(key, val, ttlSeconds)
50+
}
51+
52+
func (d *Drivers) DeleteKey(key string) (string, error) {
53+
return d.db.DeleteKey(key)
54+
}
55+
56+
func (d *Drivers) WriteKeyValAsJSON(key string, val interface{}) error {
57+
return d.db.WriteKeyValAsJSON(key, val)
58+
}
59+
60+
func (d *Drivers) WriteKeyValAsJSONTTL(key string, val interface{}, ttlSeconds int) error {
61+
return d.db.WriteKeyValAsJSONTTL(key, val, ttlSeconds)
62+
}
63+
64+
func (d *Drivers) GetVal(key string) (string, error) {
65+
return d.db.GetVal(key)
66+
}

v1/cache/drivers/options.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package drivers
2+
3+
type Options func(o *OptionsCfg) error
4+
5+
type OptionsCfg struct {
6+
fileName string
7+
folder string
8+
path string
9+
ttl int
10+
logDebug bool
11+
logDisable bool
12+
host string
13+
password string
14+
user string
15+
port int
16+
}
17+
18+
func OptFileName(filename string) Options {
19+
return func(o *OptionsCfg) error {
20+
o.fileName = filename
21+
return nil
22+
}
23+
}
24+
25+
func OptFolder(folder string) Options {
26+
return func(o *OptionsCfg) error {
27+
o.folder = folder
28+
return nil
29+
}
30+
}
31+
32+
func OptPath(path string) Options {
33+
return func(o *OptionsCfg) error {
34+
o.path = path
35+
return nil
36+
}
37+
}
38+
39+
func OptTTL(sec int) Options {
40+
return func(o *OptionsCfg) error {
41+
o.ttl = sec
42+
return nil
43+
}
44+
}
45+
46+
func OptLogDebug(value bool) Options {
47+
return func(o *OptionsCfg) error {
48+
o.logDebug = value
49+
return nil
50+
}
51+
}
52+
53+
func OptLogDisable(value bool) Options {
54+
return func(o *OptionsCfg) error {
55+
o.logDisable = value
56+
return nil
57+
}
58+
}
59+
60+
func OptHost(host string) Options {
61+
return func(o *OptionsCfg) error {
62+
o.host = host
63+
return nil
64+
}
65+
}
66+
67+
func OptPassword(password string) Options {
68+
return func(o *OptionsCfg) error {
69+
o.password = password
70+
return nil
71+
}
72+
}
73+
74+
func OptUser(user string) Options {
75+
return func(o *OptionsCfg) error {
76+
o.user = user
77+
return nil
78+
}
79+
}
80+
81+
func OptPort(port int) Options {
82+
return func(o *OptionsCfg) error {
83+
o.port = port
84+
return nil
85+
}
86+
}
87+
88+
// ------------- getters
89+
90+
func (o *OptionsCfg) GetFileName() string {
91+
return o.fileName
92+
}
93+
94+
func (o *OptionsCfg) GetFolder() string {
95+
return o.folder
96+
}
97+
98+
func (o *OptionsCfg) GetPath() string {
99+
return o.path
100+
}
101+
102+
func (o *OptionsCfg) GetTTL() int {
103+
return o.ttl
104+
}
105+
106+
func (o *OptionsCfg) GetLogDebug() bool {
107+
return o.logDebug
108+
}
109+
110+
func (o *OptionsCfg) GetLogDisable() bool {
111+
return o.logDisable
112+
}
113+
114+
func (o *OptionsCfg) GetHost() string {
115+
return o.host
116+
}
117+
118+
func (o *OptionsCfg) GetPassword() string {
119+
return o.password
120+
}
121+
122+
func (o *OptionsCfg) GetUser() string {
123+
return o.user
124+
}
125+
126+
func (o *OptionsCfg) GetPort() int {
127+
return o.port
128+
}

0 commit comments

Comments
 (0)