mirror of
https://github.com/gofiber/storage.git
synced 2025-09-29 22:02:21 +08:00
added garbage collector
This commit is contained in:
@@ -62,6 +62,7 @@ Password: "root",
|
|||||||
Access: "full",
|
Access: "full",
|
||||||
Scope: "all",
|
Scope: "all",
|
||||||
DefaultTable: "fiber_storage",
|
DefaultTable: "fiber_storage",
|
||||||
|
GCInterval: time.Second * 10,
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -92,6 +93,9 @@ Scope string
|
|||||||
|
|
||||||
// The default table used to store key-value records
|
// The default table used to store key-value records
|
||||||
DefaultTable string
|
DefaultTable string
|
||||||
|
|
||||||
|
// Optional. Default is 10 * time.Second
|
||||||
|
GCInterval time.Duration
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -108,5 +112,6 @@ Password: "root",
|
|||||||
Access: "full",
|
Access: "full",
|
||||||
Scope: "all",
|
Scope: "all",
|
||||||
DefaultTable: "fiber_storage",
|
DefaultTable: "fiber_storage",
|
||||||
|
GCInterval: time.Second * 10,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@@ -3,6 +3,7 @@ package surrealdb
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config holds the configuration required to initialize and connect to a SurrealDB instance.
|
// Config holds the configuration required to initialize and connect to a SurrealDB instance.
|
||||||
@@ -41,6 +42,9 @@ type Config struct {
|
|||||||
|
|
||||||
// The default table used to store key-value records
|
// The default table used to store key-value records
|
||||||
DefaultTable string
|
DefaultTable string
|
||||||
|
|
||||||
|
// Optional. Default is 10 * time.Second
|
||||||
|
GCInterval time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
var ConfigDefault = Config{
|
var ConfigDefault = Config{
|
||||||
@@ -52,6 +56,7 @@ var ConfigDefault = Config{
|
|||||||
Access: "full",
|
Access: "full",
|
||||||
Scope: "all",
|
Scope: "all",
|
||||||
DefaultTable: "fiber_storage",
|
DefaultTable: "fiber_storage",
|
||||||
|
GCInterval: time.Second * 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
func configDefault(config ...Config) Config {
|
func configDefault(config ...Config) Config {
|
||||||
@@ -100,5 +105,9 @@ func configDefault(config ...Config) Config {
|
|||||||
log.Printf("Warning: ConnectionString %s doesn't start with ws://, wss://, http:// or https://", cfg.ConnectionString)
|
log.Printf("Warning: ConnectionString %s doesn't start with ws://, wss://, http:// or https://", cfg.ConnectionString)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if int(cfg.GCInterval.Seconds()) <= 0 {
|
||||||
|
cfg.GCInterval = ConfigDefault.GCInterval
|
||||||
|
}
|
||||||
|
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
@@ -10,8 +10,10 @@ import (
|
|||||||
|
|
||||||
// Storage interface that is implemented by storage providers
|
// Storage interface that is implemented by storage providers
|
||||||
type Storage struct {
|
type Storage struct {
|
||||||
db *surrealdb.DB
|
db *surrealdb.DB
|
||||||
table string
|
table string
|
||||||
|
stopGC chan struct{}
|
||||||
|
interval time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// model represents a key-value storage record used in SurrealDB.
|
// model represents a key-value storage record used in SurrealDB.
|
||||||
@@ -54,10 +56,15 @@ func New(config ...Config) *Storage {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Storage{
|
storage := &Storage{
|
||||||
db: db,
|
db: db,
|
||||||
table: cfg.DefaultTable,
|
table: cfg.DefaultTable,
|
||||||
|
stopGC: make(chan struct{}),
|
||||||
|
interval: cfg.GCInterval,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
go storage.gc()
|
||||||
|
return storage
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) Get(key string) ([]byte, error) {
|
func (s *Storage) Get(key string) ([]byte, error) {
|
||||||
@@ -113,6 +120,7 @@ func (s *Storage) Reset() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) Close() error {
|
func (s *Storage) Close() error {
|
||||||
|
close(s.stopGC)
|
||||||
return s.db.Close()
|
return s.db.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,3 +147,30 @@ func (s *Storage) List() ([]byte, error) {
|
|||||||
|
|
||||||
return json.Marshal(data)
|
return json.Marshal(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Storage) gc() {
|
||||||
|
ticker := time.NewTicker(s.interval)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
s.cleanupExpired()
|
||||||
|
case <-s.stopGC:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Storage) cleanupExpired() {
|
||||||
|
records, err := surrealdb.Select[[]model, models.Table](s.db, models.Table(s.table))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
now := time.Now().Unix()
|
||||||
|
for _, item := range *records {
|
||||||
|
if item.Exp > 0 && now > item.Exp {
|
||||||
|
_ = s.Delete(item.Key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -182,6 +182,27 @@ func Test_Surrealdb_ListSkipsExpired(t *testing.T) {
|
|||||||
require.NotContains(t, result, "expired")
|
require.NotContains(t, result, "expired")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_Surrealdb_GarbageCollector_RemovesExpiredKeys(t *testing.T) {
|
||||||
|
testStore, err := newTestStore(t)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer testStore.Close()
|
||||||
|
|
||||||
|
err = testStore.Set("temp_key", []byte("temp_value"), 1*time.Second)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
val, err := testStore.Get("temp_key")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, val)
|
||||||
|
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
|
||||||
|
require.Eventually(t, func() bool {
|
||||||
|
val, err = testStore.Get("temp_key")
|
||||||
|
require.NoError(t, err)
|
||||||
|
return val == nil
|
||||||
|
}, 3*time.Second, 300*time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
func Benchmark_SurrealDB_Set(b *testing.B) {
|
func Benchmark_SurrealDB_Set(b *testing.B) {
|
||||||
testStore, err := newTestStore(b)
|
testStore, err := newTestStore(b)
|
||||||
require.NoError(b, err)
|
require.NoError(b, err)
|
||||||
|
Reference in New Issue
Block a user