Добавил возможность делать дампы кэша и восстанавливать их
parent
9ddbc94e9c
commit
d369267c21
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue