first commit
This commit is contained in:
68
services/cache_service.go
Normal file
68
services/cache_service.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// cacheItem 캐시 항목
|
||||
type cacheItem struct {
|
||||
value interface{}
|
||||
expiresAt time.Time
|
||||
}
|
||||
|
||||
// CacheService 인메모리 TTL 캐시
|
||||
type CacheService struct {
|
||||
mu sync.RWMutex
|
||||
items map[string]*cacheItem
|
||||
}
|
||||
|
||||
var cacheSvc *CacheService
|
||||
var cacheOnce sync.Once
|
||||
|
||||
// GetCacheService 캐시 서비스 싱글턴 반환
|
||||
func GetCacheService() *CacheService {
|
||||
cacheOnce.Do(func() {
|
||||
c := &CacheService{items: make(map[string]*cacheItem)}
|
||||
go c.cleanup() // 만료 항목 주기적 정리
|
||||
cacheSvc = c
|
||||
})
|
||||
return cacheSvc
|
||||
}
|
||||
|
||||
// Set 캐시에 값 저장 (ttl: 유효기간)
|
||||
func (c *CacheService) Set(key string, value interface{}, ttl time.Duration) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.items[key] = &cacheItem{
|
||||
value: value,
|
||||
expiresAt: time.Now().Add(ttl),
|
||||
}
|
||||
}
|
||||
|
||||
// Get 캐시에서 값 조회. 없거나 만료됐으면 nil, false 반환
|
||||
func (c *CacheService) Get(key string) (interface{}, bool) {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
item, ok := c.items[key]
|
||||
if !ok || time.Now().After(item.expiresAt) {
|
||||
return nil, false
|
||||
}
|
||||
return item.value, true
|
||||
}
|
||||
|
||||
// cleanup 만료된 캐시 항목을 주기적으로 삭제 (메모리 누수 방지)
|
||||
func (c *CacheService) cleanup() {
|
||||
ticker := time.NewTicker(30 * time.Second)
|
||||
defer ticker.Stop()
|
||||
for range ticker.C {
|
||||
c.mu.Lock()
|
||||
now := time.Now()
|
||||
for key, item := range c.items {
|
||||
if now.After(item.expiresAt) {
|
||||
delete(c.items, key)
|
||||
}
|
||||
}
|
||||
c.mu.Unlock()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user