From d369267c21b5926a60c9e1a6e3444db4b3939051 Mon Sep 17 00:00:00 2001 From: serr Date: Mon, 6 Jan 2025 14:25:52 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D1=8C=20=D0=B4=D0=B5=D0=BB=D0=B0=D1=82=D1=8C=20=D0=B4=D0=B0?= =?UTF-8?q?=D0=BC=D0=BF=D1=8B=20=D0=BA=D1=8D=D1=88=D0=B0=20=D0=B8=20=D0=B2?= =?UTF-8?q?=D0=BE=D1=81=D1=81=D1=82=D0=B0=D0=BD=D0=B0=D0=B2=D0=BB=D0=B8?= =?UTF-8?q?=D0=B2=D0=B0=D1=82=D1=8C=20=D0=B8=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- candycache.go | 86 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 4 deletions(-) diff --git a/candycache.go b/candycache.go index 04c8f23..d8d9db0 100644 --- a/candycache.go +++ b/candycache.go @@ -1,7 +1,10 @@ package candycache import ( + "encoding/json" "errors" + "fmt" + "io" "reflect" "sync" "time" @@ -35,8 +38,6 @@ func Cacher(cleanupInterval time.Duration) *Cache { cleanupInterval: cleanupInterval, } - // Запускаем Garbage Collector если интервал очистки больше 0 - // Иначе (если он отрицательный) кэш будет жить до ручного вызова Cleanup if cleanupInterval > 0 { go cache.gc(cleanupInterval) } @@ -83,7 +84,6 @@ func (c *Cache) Get(key string) (interface{}, error) { item, found := c.storage[key] - // Элемент не найден в кэше if !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] - // Элемент не найден в кэше if !found { return false, errors.New("key not found") } @@ -191,6 +190,85 @@ func (c *Cache) Size() int { 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 { if i == nil { return 0