mirror of
https://github.com/gofiber/storage.git
synced 2025-10-04 16:22:52 +08:00
marge upstream main into current
This commit is contained in:
142
pebble/pebble.go
Normal file
142
pebble/pebble.go
Normal file
@@ -0,0 +1,142 @@
|
||||
package pebble
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/cockroachdb/pebble"
|
||||
)
|
||||
|
||||
type Storage struct {
|
||||
db *pebble.DB
|
||||
writeOptions *pebble.WriteOptions
|
||||
}
|
||||
|
||||
type CacheType struct {
|
||||
Data []byte `json:"data"`
|
||||
Created int64 `json:"created"`
|
||||
Expires int64 `json:"expires"`
|
||||
}
|
||||
|
||||
func New(config ...Config) *Storage {
|
||||
cfg := configDefault(config...)
|
||||
|
||||
if !isValid(cfg.Path) {
|
||||
panic(errors.New("invalid filepath"))
|
||||
}
|
||||
|
||||
db, err := pebble.Open(cfg.Path, &pebble.Options{})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return &Storage{
|
||||
db: db,
|
||||
writeOptions: cfg.WriteOptions,
|
||||
}
|
||||
}
|
||||
|
||||
// // Implement the logic to retrieve the value for the given key from the storage provider
|
||||
// // Return nil, nil if the key does not exist
|
||||
func (s *Storage) Get(key string) ([]byte, error) {
|
||||
if len(key) <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
data, closer, err := s.db.Get([]byte(key))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if data == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if err := closer.Close(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var cache CacheType
|
||||
err = json.Unmarshal(data, &cache)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
secs := time.Now().Unix()
|
||||
|
||||
if cache.Expires > 0 && cache.Expires <= secs {
|
||||
err = s.db.Delete([]byte(key), nil)
|
||||
return nil, err
|
||||
}
|
||||
return cache.Data, nil
|
||||
}
|
||||
|
||||
// // Implement the logic to store the given value for the given key in the storage provider
|
||||
// // Use the provided expiration value (0 means no expiration)
|
||||
// // Ignore empty key or value without returning an error
|
||||
func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
|
||||
if len(key) <= 0 || len(val) <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
cache := CacheType{Data: []byte(val), Created: time.Now().Unix(), Expires: 0}
|
||||
|
||||
if exp > 0 {
|
||||
cache.Expires = cache.Created + int64(exp.Seconds())
|
||||
}
|
||||
|
||||
jsonString, err := json.Marshal(cache)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.db.Set([]byte(key), jsonString, s.writeOptions)
|
||||
}
|
||||
|
||||
// // Implement the logic to delete the value for the given key from the storage provider
|
||||
// // Return no error if the key does not exist in the storage
|
||||
func (s *Storage) Delete(key string) error {
|
||||
if len(key) <= 0 {
|
||||
return nil
|
||||
}
|
||||
return s.db.Delete([]byte(key), s.writeOptions)
|
||||
}
|
||||
|
||||
func (s *Storage) Reset() error {
|
||||
return s.db.Flush()
|
||||
}
|
||||
|
||||
func (s *Storage) Close() error {
|
||||
return s.db.Close()
|
||||
}
|
||||
|
||||
// // Return database client
|
||||
func (s *Storage) Conn() *pebble.DB {
|
||||
return s.db
|
||||
}
|
||||
|
||||
func isValid(fp string) bool {
|
||||
// Check if file already exists
|
||||
if _, err := os.Stat(fp); err == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
// Attempt to create it
|
||||
var d []byte
|
||||
err := os.WriteFile(fp, d, 0600)
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
err = os.Remove(fp) // And delete it
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
Reference in New Issue
Block a user