yjp 1 рік тому
батько
коміт
f756908dcb

+ 3 - 3
framework/core/infrastructure/cache/cache.go

@@ -12,7 +12,7 @@ import (
 )
 
 type Cache interface {
-	Set(key string, value string) error
+	Set(key string, value string, expireSec int64) error
 	Get(key string) (string, error)
 	GetMulti(keys []string) (map[string]string, error)
 	GetAll() (map[string]string, error)
@@ -20,7 +20,7 @@ type Cache interface {
 	Clear() error
 }
 
-func Set(cache Cache, key string, value any) error {
+func Set(cache Cache, key string, value any, expireSec int64) error {
 	valueReflectValue := reflect.ValueOf(value)
 
 	if !valueReflectValue.IsValid() {
@@ -32,7 +32,7 @@ func Set(cache Cache, key string, value any) error {
 		return err
 	}
 
-	return cache.Set(key, stringValue)
+	return cache.Set(key, stringValue, expireSec)
 }
 
 func Get[T any](cache Cache, key string) (T, error) {

+ 75 - 5
framework/core/infrastructure/cache/local/local.go

@@ -3,17 +3,22 @@ package local
 import (
 	"strings"
 	"sync"
+	"time"
 )
 
 type Cache struct {
-	namespace string
-	syncMap   *sync.Map
+	namespace                      string
+	syncMap                        *sync.Map
+	expireRoutineDoneChannelsMutex *sync.Mutex
+	expireRoutineDoneChannels      []chan any
 }
 
 func New(namespace string) *Cache {
 	return &Cache{
-		namespace: namespace,
-		syncMap:   new(sync.Map),
+		namespace:                      namespace,
+		syncMap:                        new(sync.Map),
+		expireRoutineDoneChannelsMutex: new(sync.Mutex),
+		expireRoutineDoneChannels:      make([]chan any, 0),
 	}
 }
 
@@ -22,11 +27,76 @@ func Destroy(cache *Cache) {
 		return
 	}
 
+	cache.expireRoutineDoneChannelsMutex.Lock()
+
+	for _, doneChan := range cache.expireRoutineDoneChannels {
+		doneChan <- nil
+		close(doneChan)
+		doneChan = nil
+	}
+
+	cache.expireRoutineDoneChannels = nil
+
+	cache.expireRoutineDoneChannelsMutex.Unlock()
+
 	cache.syncMap = nil
 }
 
-func (cache *Cache) Set(key string, value string) error {
+func (cache *Cache) Set(key string, value string, expireSec int64) error {
 	cache.syncMap.Store(cache.key2CacheKey(key), value)
+
+	if expireSec != 0 {
+		doneChan := make(chan any)
+
+		cache.expireRoutineDoneChannelsMutex.Lock()
+
+		if cache.expireRoutineDoneChannels != nil {
+			cache.expireRoutineDoneChannels = append(cache.expireRoutineDoneChannels, doneChan)
+		}
+
+		cache.expireRoutineDoneChannelsMutex.Unlock()
+
+		go func() {
+			timer := time.NewTimer(time.Second * time.Duration(expireSec))
+
+			defer func() {
+				timer.Stop()
+
+				cache.expireRoutineDoneChannelsMutex.Lock()
+
+				if cache.expireRoutineDoneChannels != nil {
+					findIndex := -1
+
+					for i, savedDoneChan := range cache.expireRoutineDoneChannels {
+						if savedDoneChan == doneChan {
+							findIndex = i
+							close(savedDoneChan)
+							savedDoneChan = nil
+							break
+						}
+					}
+
+					if findIndex != -1 {
+						cache.expireRoutineDoneChannels =
+							append(cache.expireRoutineDoneChannels[:findIndex], cache.expireRoutineDoneChannels[findIndex+1:]...)
+					}
+				}
+
+				cache.expireRoutineDoneChannelsMutex.Unlock()
+			}()
+
+			for {
+				select {
+				case <-timer.C:
+					cache.syncMap.Delete(cache.key2CacheKey(key))
+					return
+				case <-doneChan:
+					return
+				}
+			}
+		}()
+	}
+
 	return nil
 }
 

+ 3 - 2
framework/core/infrastructure/cache/redis/redis.go

@@ -5,6 +5,7 @@ import (
 	"github.com/pkg/errors"
 	"github.com/redis/go-redis/v9"
 	"strings"
+	"time"
 )
 
 const (
@@ -46,8 +47,8 @@ func Destroy(cache *Cache) error {
 	return nil
 }
 
-func (cache *Cache) Set(key string, value string) error {
-	cmd := cache.redisClient.Set(context.Background(), cache.key2CacheKey(key), value, 0)
+func (cache *Cache) Set(key string, value string, expireSec int64) error {
+	cmd := cache.redisClient.Set(context.Background(), cache.key2CacheKey(key), value, time.Duration(expireSec)*time.Second)
 	if cmd.Err() != nil {
 		return errors.New(cmd.Err().Error())
 	}