mirror of https://github.com/statping/statping
				
				
				
			
		
			
				
	
	
		
			114 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
package handlers
 | 
						|
 | 
						|
import (
 | 
						|
	"github.com/statping/statping/utils"
 | 
						|
	"sync"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
var CacheStorage Cacher
 | 
						|
 | 
						|
type Cacher interface {
 | 
						|
	Get(key string) []byte
 | 
						|
	Delete(key string)
 | 
						|
	Set(key string, content []byte, duration time.Duration)
 | 
						|
	List() map[string]Item
 | 
						|
	Lock()
 | 
						|
	Unlock()
 | 
						|
	StopRoutine()
 | 
						|
}
 | 
						|
 | 
						|
// Item is a cached reference
 | 
						|
type Item struct {
 | 
						|
	Content    []byte
 | 
						|
	Expiration int64
 | 
						|
}
 | 
						|
 | 
						|
// cleanRoutine is a go routine to automatically remove expired caches that haven't been hit recently
 | 
						|
func cleanRoutine(s *Storage) {
 | 
						|
	duration := 5 * time.Second
 | 
						|
 | 
						|
CacheRoutine:
 | 
						|
	for {
 | 
						|
		select {
 | 
						|
		case <-s.running:
 | 
						|
			break CacheRoutine
 | 
						|
		case <-time.After(duration):
 | 
						|
			for k, v := range s.List() {
 | 
						|
				if v.Expired() {
 | 
						|
					s.Delete(k)
 | 
						|
				}
 | 
						|
			}
 | 
						|
			duration = 5 * time.Second
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Expired returns true if the item has expired.
 | 
						|
func (item Item) Expired() bool {
 | 
						|
	if item.Expiration == 0 {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	return utils.Now().UnixNano() > item.Expiration
 | 
						|
}
 | 
						|
 | 
						|
//Storage mecanism for caching strings in memory
 | 
						|
type Storage struct {
 | 
						|
	items   map[string]Item
 | 
						|
	mu      *sync.RWMutex
 | 
						|
	running chan bool
 | 
						|
}
 | 
						|
 | 
						|
//NewStorage creates a new in memory CacheStorage
 | 
						|
func NewStorage() *Storage {
 | 
						|
	storage := &Storage{
 | 
						|
		items:   make(map[string]Item),
 | 
						|
		mu:      &sync.RWMutex{},
 | 
						|
		running: make(chan bool),
 | 
						|
	}
 | 
						|
	go cleanRoutine(storage)
 | 
						|
	return storage
 | 
						|
}
 | 
						|
 | 
						|
func (s Storage) StopRoutine() {
 | 
						|
	close(s.running)
 | 
						|
}
 | 
						|
 | 
						|
func (s Storage) Lock() {
 | 
						|
	s.mu.Lock()
 | 
						|
}
 | 
						|
 | 
						|
func (s Storage) Unlock() {
 | 
						|
	s.mu.Unlock()
 | 
						|
}
 | 
						|
 | 
						|
func (s Storage) List() map[string]Item {
 | 
						|
	return s.items
 | 
						|
}
 | 
						|
 | 
						|
//Get a cached content by key
 | 
						|
func (s Storage) Get(key string) []byte {
 | 
						|
	item := s.items[key]
 | 
						|
	if item.Expired() {
 | 
						|
		CacheStorage.Delete(key)
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	return item.Content
 | 
						|
}
 | 
						|
 | 
						|
func (s Storage) Delete(key string) {
 | 
						|
	s.mu.Lock()
 | 
						|
	defer s.mu.Unlock()
 | 
						|
	delete(s.items, key)
 | 
						|
}
 | 
						|
 | 
						|
//Set a cached content by key
 | 
						|
func (s Storage) Set(key string, content []byte, duration time.Duration) {
 | 
						|
	s.mu.Lock()
 | 
						|
	defer s.mu.Unlock()
 | 
						|
	s.items[key] = Item{
 | 
						|
		Content:    content,
 | 
						|
		Expiration: utils.Now().Add(duration).UnixNano(),
 | 
						|
	}
 | 
						|
}
 |