add context support to more storages

This commit is contained in:
Muhammed Efe Cetin
2025-06-25 14:13:21 +03:00
parent 85ffd9d133
commit 75b43b2ac4
8 changed files with 312 additions and 63 deletions

View File

@@ -1,6 +1,7 @@
package badger package badger
import ( import (
"context"
"time" "time"
"github.com/dgraph-io/badger/v3" "github.com/dgraph-io/badger/v3"
@@ -72,6 +73,12 @@ func (s *Storage) Get(key string) ([]byte, error) {
return data, err return data, err
} }
// GetWithContext gets value by key.
// Note: This method is not used in the current implementation, but is included to satisfy the Storage interface.
func (s *Storage) GetWithContext(ctx context.Context, key string) ([]byte, error) {
return s.Get(key)
}
// Set key with value // Set key with value
func (s *Storage) Set(key string, val []byte, exp time.Duration) error { func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
// Ain't Nobody Got Time For That // Ain't Nobody Got Time For That
@@ -88,6 +95,12 @@ func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
}) })
} }
// SetWithContext sets key with value.
// Note: This method is not used in the current implementation, but is included to satisfy the Storage interface.
func (s *Storage) SetWithContext(ctx context.Context, key string, val []byte, exp time.Duration) error {
return s.Set(key, val, exp)
}
// Delete key by key // Delete key by key
func (s *Storage) Delete(key string) error { func (s *Storage) Delete(key string) error {
// Ain't Nobody Got Time For That // Ain't Nobody Got Time For That
@@ -99,11 +112,23 @@ func (s *Storage) Delete(key string) error {
}) })
} }
// DeleteWithContext deletes key by key.
// Note: This method is not used in the current implementation, but is included to satisfy the Storage interface.
func (s *Storage) DeleteWithContext(ctx context.Context, key string) error {
return s.Delete(key)
}
// Reset all keys // Reset all keys
func (s *Storage) Reset() error { func (s *Storage) Reset() error {
return s.db.DropAll() return s.db.DropAll()
} }
// ResetWithContext resets all keys.
// Note: This method is not used in the current implementation, but is included to satisfy the Storage interface.
func (s *Storage) ResetWithContext(ctx context.Context) error {
return s.db.DropAll()
}
// Close the memory storage // Close the memory storage
func (s *Storage) Close() error { func (s *Storage) Close() error {
s.done <- struct{}{} s.done <- struct{}{}

View File

@@ -1,6 +1,7 @@
package bbolt package bbolt
import ( import (
"context"
"time" "time"
"github.com/gofiber/utils/v2" "github.com/gofiber/utils/v2"
@@ -62,6 +63,11 @@ func (s *Storage) Get(key string) ([]byte, error) {
return value, err return value, err
} }
// GetWithContext gets value by key (dummy context support)
func (s *Storage) GetWithContext(ctx context.Context, key string) ([]byte, error) {
return s.Get(key)
}
// Set key with value // Set key with value
func (s *Storage) Set(key string, value []byte, exp time.Duration) error { func (s *Storage) Set(key string, value []byte, exp time.Duration) error {
if len(key) <= 0 || len(value) <= 0 { if len(key) <= 0 || len(value) <= 0 {
@@ -70,11 +76,15 @@ func (s *Storage) Set(key string, value []byte, exp time.Duration) error {
return s.conn.Update(func(tx *bbolt.Tx) error { return s.conn.Update(func(tx *bbolt.Tx) error {
b := tx.Bucket(utils.UnsafeBytes(s.bucket)) b := tx.Bucket(utils.UnsafeBytes(s.bucket))
return b.Put(utils.UnsafeBytes(key), value) return b.Put(utils.UnsafeBytes(key), value)
}) })
} }
// SetWithContext sets key with value (dummy context support)
func (s *Storage) SetWithContext(ctx context.Context, key string, value []byte, exp time.Duration) error {
return s.Set(key, value, exp)
}
// Delete entry by key // Delete entry by key
func (s *Storage) Delete(key string) error { func (s *Storage) Delete(key string) error {
if len(key) <= 0 { if len(key) <= 0 {
@@ -83,28 +93,36 @@ func (s *Storage) Delete(key string) error {
return s.conn.Update(func(tx *bbolt.Tx) error { return s.conn.Update(func(tx *bbolt.Tx) error {
b := tx.Bucket(utils.UnsafeBytes(s.bucket)) b := tx.Bucket(utils.UnsafeBytes(s.bucket))
return b.Delete(utils.UnsafeBytes(key)) return b.Delete(utils.UnsafeBytes(key))
}) })
} }
// DeleteWithContext deletes key by key (dummy context support)
func (s *Storage) DeleteWithContext(ctx context.Context, key string) error {
return s.Delete(key)
}
// Reset all entries // Reset all entries
func (s *Storage) Reset() error { func (s *Storage) Reset() error {
return s.conn.Update(func(tx *bbolt.Tx) error { return s.conn.Update(func(tx *bbolt.Tx) error {
b := tx.Bucket(utils.UnsafeBytes(s.bucket)) b := tx.Bucket(utils.UnsafeBytes(s.bucket))
return b.ForEach(func(k, _ []byte) error { return b.ForEach(func(k, _ []byte) error {
return b.Delete(k) return b.Delete(k)
}) })
}) })
} }
// ResetWithContext resets all entries (dummy context support)
func (s *Storage) ResetWithContext(ctx context.Context) error {
return s.Reset()
}
// Close the database // Close the database
func (s *Storage) Close() error { func (s *Storage) Close() error {
return s.conn.Close() return s.conn.Close()
} }
// Return database client // Conn returns the database client
func (s *Storage) Conn() *bbolt.DB { func (s *Storage) Conn() *bbolt.DB {
return s.conn return s.conn
} }

View File

@@ -1,6 +1,7 @@
package memcache package memcache
import ( import (
"context"
"strings" "strings"
"sync" "sync"
"time" "time"
@@ -68,10 +69,13 @@ func (s *Storage) Get(key string) ([]byte, error) {
return item.Value, nil return item.Value, nil
} }
// Set key with value // GetWithContext gets value by key (dummy context support)
func (s *Storage) GetWithContext(ctx context.Context, key string) ([]byte, error) {
return s.Get(key)
}
// Set key with value // Set key with value
func (s *Storage) Set(key string, val []byte, exp time.Duration) error { func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
// Ain't Nobody Got Time For That
if len(key) <= 0 || len(val) <= 0 { if len(key) <= 0 || len(val) <= 0 {
return nil return nil
} }
@@ -87,20 +91,34 @@ func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
return err return err
} }
// SetWithContext sets key with value (dummy context support)
func (s *Storage) SetWithContext(ctx context.Context, key string, val []byte, exp time.Duration) error {
return s.Set(key, val, exp)
}
// Delete key by key // Delete key by key
func (s *Storage) Delete(key string) error { func (s *Storage) Delete(key string) error {
// Ain't Nobody Got Time For That
if len(key) <= 0 { if len(key) <= 0 {
return nil return nil
} }
return s.db.Delete(key) return s.db.Delete(key)
} }
// DeleteWithContext deletes key by key (dummy context support)
func (s *Storage) DeleteWithContext(ctx context.Context, key string) error {
return s.Delete(key)
}
// Reset all keys // Reset all keys
func (s *Storage) Reset() error { func (s *Storage) Reset() error {
return s.db.DeleteAll() return s.db.DeleteAll()
} }
// ResetWithContext resets all keys (dummy context support)
func (s *Storage) ResetWithContext(ctx context.Context) error {
return s.Reset()
}
// Close the database // Close the database
func (s *Storage) Close() error { func (s *Storage) Close() error {
return nil return nil
@@ -111,7 +129,7 @@ func (s *Storage) acquireItem() *mc.Item {
return s.items.Get().(*mc.Item) return s.items.Get().(*mc.Item)
} }
// Release item from pool // Release item back to pool
func (s *Storage) releaseItem(item *mc.Item) { func (s *Storage) releaseItem(item *mc.Item) {
if item != nil { if item != nil {
item.Key = "" item.Key = ""

View File

@@ -1,6 +1,7 @@
package memory package memory
import ( import (
"context"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@@ -18,8 +19,7 @@ type Storage struct {
type entry struct { type entry struct {
data []byte data []byte
// max value is 4294967295 -> Sun Feb 07 2106 06:28:15 GMT+0000 expiry uint32 // max value is 4294967295 -> Sun Feb 07 2106 06:28:15 GMT+0000
expiry uint32
} }
// New creates a new memory storage // New creates a new memory storage
@@ -49,16 +49,20 @@ func (s *Storage) Get(key string) ([]byte, error) {
s.mux.RLock() s.mux.RLock()
v, ok := s.db[key] v, ok := s.db[key]
s.mux.RUnlock() s.mux.RUnlock()
if !ok || v.expiry != 0 && v.expiry <= atomic.LoadUint32(&internal.Timestamp) { if !ok || (v.expiry != 0 && v.expiry <= atomic.LoadUint32(&internal.Timestamp)) {
return nil, nil return nil, nil
} }
return v.data, nil return v.data, nil
} }
// GetWithContext gets value by key (dummy context support)
func (s *Storage) GetWithContext(ctx context.Context, key string) ([]byte, error) {
return s.Get(key)
}
// Set key with value // Set key with value
func (s *Storage) Set(key string, val []byte, exp time.Duration) error { func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
// Ain't Nobody Got Time For That
if len(key) <= 0 || len(val) <= 0 { if len(key) <= 0 || len(val) <= 0 {
return nil return nil
} }
@@ -75,9 +79,13 @@ func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
return nil return nil
} }
// SetWithContext sets value by key (dummy context support)
func (s *Storage) SetWithContext(ctx context.Context, key string, val []byte, exp time.Duration) error {
return s.Set(key, val, exp)
}
// Delete key by key // Delete key by key
func (s *Storage) Delete(key string) error { func (s *Storage) Delete(key string) error {
// Ain't Nobody Got Time For That
if len(key) <= 0 { if len(key) <= 0 {
return nil return nil
} }
@@ -87,6 +95,11 @@ func (s *Storage) Delete(key string) error {
return nil return nil
} }
// DeleteWithContext deletes key (dummy context support)
func (s *Storage) DeleteWithContext(ctx context.Context, key string) error {
return s.Delete(key)
}
// Reset all keys // Reset all keys
func (s *Storage) Reset() error { func (s *Storage) Reset() error {
ndb := make(map[string]entry) ndb := make(map[string]entry)
@@ -96,6 +109,11 @@ func (s *Storage) Reset() error {
return nil return nil
} }
// ResetWithContext resets all keys (dummy context support)
func (s *Storage) ResetWithContext(ctx context.Context) error {
return s.Reset()
}
// Close the memory storage // Close the memory storage
func (s *Storage) Close() error { func (s *Storage) Close() error {
s.done <- struct{}{} s.done <- struct{}{}
@@ -122,8 +140,6 @@ func (s *Storage) gc() {
} }
s.mux.RUnlock() s.mux.RUnlock()
s.mux.Lock() s.mux.Lock()
// Double-checked locking.
// We might have replaced the item in the meantime.
for i := range expired { for i := range expired {
v := s.db[expired[i]] v := s.db[expired[i]]
if v.expiry != 0 && v.expiry <= ts { if v.expiry != 0 && v.expiry <= ts {
@@ -135,14 +151,14 @@ func (s *Storage) gc() {
} }
} }
// Return database client // Conn returns database client
func (s *Storage) Conn() map[string]entry { func (s *Storage) Conn() map[string]entry {
s.mux.RLock() s.mux.RLock()
defer s.mux.RUnlock() defer s.mux.RUnlock()
return s.db return s.db
} }
// Return all the keys // Keys returns all the keys
func (s *Storage) Keys() ([][]byte, error) { func (s *Storage) Keys() ([][]byte, error) {
s.mux.RLock() s.mux.RLock()
defer s.mux.RUnlock() defer s.mux.RUnlock()
@@ -154,13 +170,11 @@ func (s *Storage) Keys() ([][]byte, error) {
ts := atomic.LoadUint32(&internal.Timestamp) ts := atomic.LoadUint32(&internal.Timestamp)
keys := make([][]byte, 0, len(s.db)) keys := make([][]byte, 0, len(s.db))
for key, v := range s.db { for key, v := range s.db {
// Filter out the expired keys
if v.expiry == 0 || v.expiry > ts { if v.expiry == 0 || v.expiry > ts {
keys = append(keys, []byte(key)) keys = append(keys, []byte(key))
} }
} }
// Double check if no valid keys were found
if len(keys) == 0 { if len(keys) == 0 {
return nil, nil return nil, nil
} }

View File

@@ -1,6 +1,7 @@
package mockstorage package mockstorage
import ( import (
"context"
"errors" "errors"
"sync" "sync"
"time" "time"
@@ -27,9 +28,13 @@ type Entry struct {
// CustomFuncs allows injecting custom behaviors for testing. // CustomFuncs allows injecting custom behaviors for testing.
type CustomFuncs struct { type CustomFuncs struct {
GetFunc func(key string) ([]byte, error) GetFunc func(key string) ([]byte, error)
GetWithContext func(ctx context.Context, key string) ([]byte, error)
SetFunc func(key string, val []byte, exp time.Duration) error SetFunc func(key string, val []byte, exp time.Duration) error
SetWithContext func(ctx context.Context, key string, val []byte, exp time.Duration) error
DeleteFunc func(key string) error DeleteFunc func(key string) error
DeleteWithContext func(ctx context.Context, key string) error
ResetFunc func() error ResetFunc func() error
ResetWithContext func(ctx context.Context) error
CloseFunc func() error CloseFunc func() error
ConnFunc func() map[string]Entry ConnFunc func() map[string]Entry
KeysFunc func() ([][]byte, error) KeysFunc func() ([][]byte, error)
@@ -39,18 +44,9 @@ type CustomFuncs struct {
func New(config ...Config) *Storage { func New(config ...Config) *Storage {
s := &Storage{ s := &Storage{
data: make(map[string]Entry), data: make(map[string]Entry),
custom: &CustomFuncs{ custom: &CustomFuncs{}, // default no-op
GetFunc: nil,
SetFunc: nil,
DeleteFunc: nil,
ResetFunc: nil,
CloseFunc: nil,
ConnFunc: nil,
KeysFunc: nil,
},
} }
// If a config is provided and it has CustomFuncs, use them
if len(config) > 0 && config[0].CustomFuncs != nil { if len(config) > 0 && config[0].CustomFuncs != nil {
s.custom = config[0].CustomFuncs s.custom = config[0].CustomFuncs
} }
@@ -78,7 +74,15 @@ func (s *Storage) Get(key string) ([]byte, error) {
return e.Value, nil return e.Value, nil
} }
// Set sets the value for a given key with an expiration time. // GetWithContext retrieves value by key using a context (functional or fallback)
func (s *Storage) GetWithContext(ctx context.Context, key string) ([]byte, error) {
if s.custom.GetWithContext != nil {
return s.custom.GetWithContext(ctx, key)
}
return s.Get(key)
}
// Set sets the value for a given key with expiration.
func (s *Storage) Set(key string, val []byte, exp time.Duration) error { func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
if s.custom.SetFunc != nil { if s.custom.SetFunc != nil {
return s.custom.SetFunc(key, val, exp) return s.custom.SetFunc(key, val, exp)
@@ -96,6 +100,14 @@ func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
return nil return nil
} }
// SetWithContext sets value using context.
func (s *Storage) SetWithContext(ctx context.Context, key string, val []byte, exp time.Duration) error {
if s.custom.SetWithContext != nil {
return s.custom.SetWithContext(ctx, key, val, exp)
}
return s.Set(key, val, exp)
}
// Delete removes a key from the storage. // Delete removes a key from the storage.
func (s *Storage) Delete(key string) error { func (s *Storage) Delete(key string) error {
if s.custom.DeleteFunc != nil { if s.custom.DeleteFunc != nil {
@@ -104,12 +116,19 @@ func (s *Storage) Delete(key string) error {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
delete(s.data, key) delete(s.data, key)
return nil return nil
} }
// Reset clears all keys from the storage. // DeleteWithContext deletes key using context.
func (s *Storage) DeleteWithContext(ctx context.Context, key string) error {
if s.custom.DeleteWithContext != nil {
return s.custom.DeleteWithContext(ctx, key)
}
return s.Delete(key)
}
// Reset clears all keys.
func (s *Storage) Reset() error { func (s *Storage) Reset() error {
if s.custom.ResetFunc != nil { if s.custom.ResetFunc != nil {
return s.custom.ResetFunc() return s.custom.ResetFunc()
@@ -117,22 +136,27 @@ func (s *Storage) Reset() error {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
s.data = make(map[string]Entry) s.data = make(map[string]Entry)
return nil return nil
} }
// Close closes the storage (no-op for mock). // ResetWithContext resets storage using context.
func (s *Storage) ResetWithContext(ctx context.Context) error {
if s.custom.ResetWithContext != nil {
return s.custom.ResetWithContext(ctx)
}
return s.Reset()
}
// Close closes the mock storage (no-op).
func (s *Storage) Close() error { func (s *Storage) Close() error {
if s.custom.CloseFunc != nil { if s.custom.CloseFunc != nil {
return s.custom.CloseFunc() return s.custom.CloseFunc()
} }
// No resources to clean up in mock
return nil return nil
} }
// Conn returns the internal data map (for testing purposes). // Conn returns internal map.
func (s *Storage) Conn() map[string]Entry { func (s *Storage) Conn() map[string]Entry {
if s.custom.ConnFunc != nil { if s.custom.ConnFunc != nil {
return s.custom.ConnFunc() return s.custom.ConnFunc()
@@ -148,7 +172,7 @@ func (s *Storage) Conn() map[string]Entry {
return copyData return copyData
} }
// Keys returns all keys in the storage. // Keys returns all keys.
func (s *Storage) Keys() ([][]byte, error) { func (s *Storage) Keys() ([][]byte, error) {
if s.custom.KeysFunc != nil { if s.custom.KeysFunc != nil {
return s.custom.KeysFunc() return s.custom.KeysFunc()
@@ -164,7 +188,7 @@ func (s *Storage) Keys() ([][]byte, error) {
return keys, nil return keys, nil
} }
// SetCustomFuncs allows setting custom function implementations. // SetCustomFuncs allows runtime injection of function implementations.
func (s *Storage) SetCustomFuncs(custom *CustomFuncs) { func (s *Storage) SetCustomFuncs(custom *CustomFuncs) {
s.custom = custom s.custom = custom
} }

View File

@@ -2,6 +2,7 @@ package mockstorage
import ( import (
"bytes" "bytes"
"context"
"errors" "errors"
"testing" "testing"
"time" "time"
@@ -274,3 +275,111 @@ func TestStorageConnAndKeys(t *testing.T) {
t.Errorf("Keys() = %v, want %v", keys, [][]byte{[]byte("key1")}) t.Errorf("Keys() = %v, want %v", keys, [][]byte{[]byte("key1")})
} }
} }
func TestGetWithContext(t *testing.T) {
store := New()
// fallback to Get
_ = store.Set("key1", []byte("val1"), 0)
val, err := store.GetWithContext(context.Background(), "key1")
if err != nil || !bytes.Equal(val, []byte("val1")) {
t.Errorf("GetWithContext fallback failed: got %v, err %v", val, err)
}
// custom override
store.SetCustomFuncs(&CustomFuncs{
GetWithContext: func(ctx context.Context, key string) ([]byte, error) {
if key == "override" {
return []byte("ctx-value"), nil
}
return nil, errors.New("not found")
},
})
val, err = store.GetWithContext(context.TODO(), "override")
if err != nil || !bytes.Equal(val, []byte("ctx-value")) {
t.Errorf("GetWithContext custom failed: got %v, err %v", val, err)
}
}
func TestSetWithContext(t *testing.T) {
store := New()
// fallback to Set
err := store.SetWithContext(context.TODO(), "key2", []byte("val2"), 0)
if err != nil {
t.Errorf("SetWithContext fallback failed: %v", err)
}
val, _ := store.Get("key2")
if !bytes.Equal(val, []byte("val2")) {
t.Errorf("SetWithContext fallback mismatch: got %v", val)
}
// custom override
store.SetCustomFuncs(&CustomFuncs{
SetWithContext: func(ctx context.Context, key string, val []byte, exp time.Duration) error {
if key == "readonly" {
return errors.New("forbidden")
}
return nil
},
})
err = store.SetWithContext(context.TODO(), "readonly", []byte("fail"), 0)
if err == nil || err.Error() != "forbidden" {
t.Errorf("SetWithContext custom override failed: err=%v", err)
}
}
func TestDeleteWithContext(t *testing.T) {
store := New()
// fallback to Delete
_ = store.Set("key3", []byte("val3"), 0)
err := store.DeleteWithContext(context.TODO(), "key3")
if err != nil {
t.Errorf("DeleteWithContext fallback failed: %v", err)
}
val, err := store.Get("key3")
if err == nil {
t.Errorf("expected deletion, but got value: %v", val)
}
// custom override
store.SetCustomFuncs(&CustomFuncs{
DeleteWithContext: func(ctx context.Context, key string) error {
if key == "undeletable" {
return errors.New("blocked")
}
return nil
},
})
err = store.DeleteWithContext(context.TODO(), "undeletable")
if err == nil || err.Error() != "blocked" {
t.Errorf("DeleteWithContext custom override failed: err=%v", err)
}
}
func TestResetWithContext(t *testing.T) {
store := New()
// fallback to Reset
_ = store.Set("key4", []byte("val4"), 0)
err := store.ResetWithContext(context.TODO())
if err != nil {
t.Errorf("ResetWithContext fallback failed: %v", err)
}
val, err := store.Get("key4")
if err == nil {
t.Errorf("expected reset to remove key, but got value: %v", val)
}
// custom override
store.SetCustomFuncs(&CustomFuncs{
ResetWithContext: func(ctx context.Context) error {
return errors.New("custom reset error")
},
})
err = store.ResetWithContext(context.Background())
if err == nil || err.Error() != "custom reset error" {
t.Errorf("ResetWithContext custom override failed: err=%v", err)
}
}

View File

@@ -1,6 +1,7 @@
package pebble package pebble
import ( import (
"context"
"encoding/json" "encoding/json"
"errors" "errors"
"log" "log"
@@ -39,8 +40,7 @@ func New(config ...Config) *Storage {
} }
} }
// // Implement the logic to retrieve the value for the given key from the storage provider // Get retrieves the value by key.
// // Return nil, nil if the key does not exist
func (s *Storage) Get(key string) ([]byte, error) { func (s *Storage) Get(key string) ([]byte, error) {
if len(key) <= 0 { if len(key) <= 0 {
return nil, nil return nil, nil
@@ -60,7 +60,6 @@ func (s *Storage) Get(key string) ([]byte, error) {
var cache CacheType var cache CacheType
err = json.Unmarshal(data, &cache) err = json.Unmarshal(data, &cache)
if err != nil { if err != nil {
return nil, nil return nil, nil
} }
@@ -71,18 +70,26 @@ func (s *Storage) Get(key string) ([]byte, error) {
err = s.db.Delete([]byte(key), nil) err = s.db.Delete([]byte(key), nil)
return nil, err return nil, err
} }
return cache.Data, nil return cache.Data, nil
} }
// // Implement the logic to store the given value for the given key in the storage provider // GetWithContext retrieves value by key (dummy context support)
// // Use the provided expiration value (0 means no expiration) func (s *Storage) GetWithContext(ctx context.Context, key string) ([]byte, error) {
// // Ignore empty key or value without returning an error return s.Get(key)
}
// Set stores the given value with optional expiration
func (s *Storage) Set(key string, val []byte, exp time.Duration) error { func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
if len(key) <= 0 || len(val) <= 0 { if len(key) <= 0 || len(val) <= 0 {
return nil return nil
} }
cache := CacheType{Data: []byte(val), Created: time.Now().Unix(), Expires: 0} cache := CacheType{
Data: val,
Created: time.Now().Unix(),
Expires: 0,
}
if exp > 0 { if exp > 0 {
cache.Expires = cache.Created + int64(exp.Seconds()) cache.Expires = cache.Created + int64(exp.Seconds())
@@ -95,8 +102,12 @@ func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
return s.db.Set([]byte(key), jsonString, s.writeOptions) return s.db.Set([]byte(key), jsonString, s.writeOptions)
} }
// // Implement the logic to delete the value for the given key from the storage provider // SetWithContext sets value by key (dummy context support)
// // Return no error if the key does not exist in the storage func (s *Storage) SetWithContext(ctx context.Context, key string, val []byte, exp time.Duration) error {
return s.Set(key, val, exp)
}
// Delete removes a value by key
func (s *Storage) Delete(key string) error { func (s *Storage) Delete(key string) error {
if len(key) <= 0 { if len(key) <= 0 {
return nil return nil
@@ -104,26 +115,36 @@ func (s *Storage) Delete(key string) error {
return s.db.Delete([]byte(key), s.writeOptions) return s.db.Delete([]byte(key), s.writeOptions)
} }
// DeleteWithContext deletes key (dummy context support)
func (s *Storage) DeleteWithContext(ctx context.Context, key string) error {
return s.Delete(key)
}
// Reset flushes the DB
func (s *Storage) Reset() error { func (s *Storage) Reset() error {
return s.db.Flush() return s.db.Flush()
} }
// ResetWithContext resets storage (dummy context support)
func (s *Storage) ResetWithContext(ctx context.Context) error {
return s.Reset()
}
// Close closes the database
func (s *Storage) Close() error { func (s *Storage) Close() error {
return s.db.Close() return s.db.Close()
} }
// // Return database client // Conn returns the database client
func (s *Storage) Conn() *pebble.DB { func (s *Storage) Conn() *pebble.DB {
return s.db return s.db
} }
func isValid(fp string) bool { func isValid(fp string) bool {
// Check if file already exists
if _, err := os.Stat(fp); err == nil { if _, err := os.Stat(fp); err == nil {
return true return true
} }
// Attempt to create it
var d []byte var d []byte
err := os.WriteFile(fp, d, 0o600) err := os.WriteFile(fp, d, 0o600)
if err != nil { if err != nil {

View File

@@ -1,6 +1,7 @@
package ristretto package ristretto
import ( import (
"context"
"time" "time"
"github.com/dgraph-io/ristretto" "github.com/dgraph-io/ristretto"
@@ -52,6 +53,11 @@ func (s *Storage) Get(key string) ([]byte, error) {
return buf, nil return buf, nil
} }
// GetWithContext gets the value by key (dummy context support)
func (s *Storage) GetWithContext(ctx context.Context, key string) ([]byte, error) {
return s.Get(key)
}
// Set stores the given value for the given key along // Set stores the given value for the given key along
// with an expiration value, time.Time{} means no expiration. // with an expiration value, time.Time{} means no expiration.
// Empty key or value will be ignored without an error. // Empty key or value will be ignored without an error.
@@ -66,8 +72,12 @@ func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
return nil return nil
} }
// SetWithContext sets value by key (dummy context support)
func (s *Storage) SetWithContext(ctx context.Context, key string, val []byte, exp time.Duration) error {
return s.Set(key, val, exp)
}
// Delete deletes the value for the given key. // Delete deletes the value for the given key.
// It returns no error if the storage does not contain the key,
func (s *Storage) Delete(key string) error { func (s *Storage) Delete(key string) error {
if len(key) <= 0 { if len(key) <= 0 {
return nil return nil
@@ -76,12 +86,22 @@ func (s *Storage) Delete(key string) error {
return nil return nil
} }
// Reset resets the storage and delete all keys. // DeleteWithContext deletes key (dummy context support)
func (s *Storage) DeleteWithContext(ctx context.Context, key string) error {
return s.Delete(key)
}
// Reset resets the storage and deletes all keys.
func (s *Storage) Reset() error { func (s *Storage) Reset() error {
s.cache.Clear() s.cache.Clear()
return nil return nil
} }
// ResetWithContext resets storage (dummy context support)
func (s *Storage) ResetWithContext(ctx context.Context) error {
return s.Reset()
}
// Close closes the storage and will stop any running garbage // Close closes the storage and will stop any running garbage
// collectors and open connections. // collectors and open connections.
func (s *Storage) Close() error { func (s *Storage) Close() error {
@@ -89,7 +109,7 @@ func (s *Storage) Close() error {
return nil return nil
} }
// Return database client // Conn returns the database client
func (s *Storage) Conn() *ristretto.Cache { func (s *Storage) Conn() *ristretto.Cache {
return s.cache return s.cache
} }