Добавил возможность делать дампы кэша и восстанавливать их

main
serr 2025-01-06 14:25:52 +03:00
parent 9ddbc94e9c
commit d369267c21
1 changed files with 82 additions and 4 deletions

View File

@ -1,7 +1,10 @@
package candycache package candycache
import ( import (
"encoding/json"
"errors" "errors"
"fmt"
"io"
"reflect" "reflect"
"sync" "sync"
"time" "time"
@ -35,8 +38,6 @@ func Cacher(cleanupInterval time.Duration) *Cache {
cleanupInterval: cleanupInterval, cleanupInterval: cleanupInterval,
} }
// Запускаем Garbage Collector если интервал очистки больше 0
// Иначе (если он отрицательный) кэш будет жить до ручного вызова Cleanup
if cleanupInterval > 0 { if cleanupInterval > 0 {
go cache.gc(cleanupInterval) go cache.gc(cleanupInterval)
} }
@ -83,7 +84,6 @@ func (c *Cache) Get(key string) (interface{}, error) {
item, found := c.storage[key] item, found := c.storage[key]
// Элемент не найден в кэше
if !found { if !found {
return nil, errors.New("key not found") return nil, errors.New("key not found")
} }
@ -100,7 +100,6 @@ func (c *Cache) IsExpired(key string) (bool, error) {
item, found := c.storage[key] item, found := c.storage[key]
// Элемент не найден в кэше
if !found { if !found {
return false, errors.New("key not found") return false, errors.New("key not found")
} }
@ -191,6 +190,85 @@ func (c *Cache) Size() int {
return size return size
} }
// Save сохраняет кэш в io.Writer в формате JSON, записывая каждый элемент по отдельности.
func (c *Cache) Save(w io.Writer) error {
c.RLock()
defer c.RUnlock()
if _, err := w.Write([]byte("[\n")); err != nil {
return err
}
encoder := json.NewEncoder(w)
first := true
for key, item := range c.storage {
entry := struct {
Key string `json:"key"`
DestroyTimestamp int64 `json:"destroyTimestamp"`
Data interface{} `json:"data"`
}{
Key: key,
DestroyTimestamp: item.destroyTimestamp,
Data: item.data,
}
if !first {
if _, err := w.Write([]byte(",\n")); err != nil {
return err
}
}
first = false
if err := encoder.Encode(entry); err != nil {
return err
}
}
if _, err := w.Write([]byte("]")); err != nil {
return err
}
return nil
}
// Load загружает кэш из io.Reader в формате JSON.
func (c *Cache) Load(r io.Reader) error {
c.Lock()
defer c.Unlock()
decoder := json.NewDecoder(r)
if _, err := decoder.Token(); err != nil {
if err == io.EOF {
return fmt.Errorf("файл пустой или имеет неправильный формат")
}
return err
}
for decoder.More() {
var entry struct {
Key string `json:"key"`
DestroyTimestamp int64 `json:"destroyTimestamp"`
Data interface{} `json:"data"`
}
if err := decoder.Decode(&entry); err != nil {
return err
}
c.storage[entry.Key] = Item{
destroyTimestamp: entry.DestroyTimestamp,
data: entry.Data,
}
}
if _, err := decoder.Token(); err != nil {
return err
}
return nil
}
func isize(i interface{}) int { func isize(i interface{}) int {
if i == nil { if i == nil {
return 0 return 0