step-7
Vyacheslav Bakhmutov 2014-03-06 16:22:13 +04:00
parent 2c4f868371
commit 2da67f7bac
4 changed files with 57 additions and 6 deletions

View File

@ -19,6 +19,7 @@ type ErrorMsg struct{
const (
REQUEST_BODY_SIZE = 1024 * 30
MAX_REQUEST_COUNT = 20
BIN_LIFETIME = 60 * 60 * 24 * 2
)
type Config struct {
@ -26,7 +27,7 @@ type Config struct {
}
func GetApi(config *Config) *martini.ClassicMartini {
storage := NewMemoryStorage(MAX_REQUEST_COUNT)
storage := NewMemoryStorage(MAX_REQUEST_COUNT, BIN_LIFETIME)
store := sessions.NewCookieStore([]byte(config.SessionSecret))
api := martini.Classic()

View File

@ -3,12 +3,14 @@ package skimmer
import (
"errors"
"sync"
"time"
)
type MemoryStorage struct {
BaseStorage
sync.RWMutex
binRecords map[string]*BinRecord
cleanTimer *time.Timer
}
type BinRecord struct {
@ -30,13 +32,40 @@ func (binRecord *BinRecord) ShrinkRequests(size int) {
}
}
func NewMemoryStorage(maxRequests int) *MemoryStorage {
return &MemoryStorage{
func NewMemoryStorage(maxRequests int, binLifetime int64) *MemoryStorage {
storage := &MemoryStorage{
BaseStorage{
maxRequests: maxRequests,
binLifetime: binLifetime,
},
sync.RWMutex{},
map[string]*BinRecord{},
&time.Timer{},
}
return storage
}
func (storage *MemoryStorage) StartCleaning(timeout int) {
defer func(){
storage.cleanTimer = time.AfterFunc(time.Duration(timeout) * time.Second, func(){storage.StartCleaning(timeout)})
}()
storage.clean()
}
func (storage *MemoryStorage) StopCleaning() {
if storage.cleanTimer != nil {
storage.cleanTimer.Stop()
}
}
func (storage *MemoryStorage) clean() {
storage.Lock()
defer storage.Unlock()
now := time.Now().Unix()
for name, binRecord := range storage.binRecords {
if binRecord.bin.Updated < (now - storage.binLifetime) {
delete(storage.binRecords, name)
}
}
}
@ -125,6 +154,7 @@ func (storage *MemoryStorage) CreateRequest(bin *Bin, req *Request) error {
binRecord.requestMap[req.Id] = req
binRecord.ShrinkRequests(storage.maxRequests)
binRecord.bin.RequestCount = len(binRecord.requests)
binRecord.bin.Updated = time.Now().Unix()
return nil
} else {
return err

View File

@ -5,16 +5,17 @@ import (
"github.com/stretchr/testify/assert"
"net/http"
"bytes"
"time"
)
func getMemoryStorage() *MemoryStorage {
return NewMemoryStorage(REQUEST_BODY_SIZE)
return NewMemoryStorage(REQUEST_BODY_SIZE, BIN_LIFETIME)
}
func TestNewMemoryStorage(t *testing.T) {
maxRequests := 20
storage := NewMemoryStorage(maxRequests)
storage := NewMemoryStorage(maxRequests, BIN_LIFETIME)
assert.Equal(t, storage.maxRequests, maxRequests)
assert.NotNil(t, storage.binRecords)
@ -103,7 +104,7 @@ func TestLookupBins(t *testing.T) {
}
func TestCreateRequest(t *testing.T) {
storage := NewMemoryStorage(2)
storage := NewMemoryStorage(2, BIN_LIFETIME)
bin := NewBin()
storage.CreateBin(bin)
httpRequest, _ := http.NewRequest("GET", "/", bytes.NewBuffer([]byte("body")))
@ -203,3 +204,21 @@ func TestLookupRequests(t *testing.T) {
}
}
func TestMemoryClean(t *testing.T) {
storage := NewMemoryStorage(2, -1)
bin := NewBin()
storage.CreateBin(bin)
assert.Equal(t, storage.binRecords[bin.Name].bin, bin)
storage.clean()
assert.Equal(t, len(storage.binRecords), 0)
storage.CreateBin(bin)
assert.Equal(t, storage.binRecords[bin.Name].bin, bin)
storage.StartCleaning(0)
assert.Equal(t, len(storage.binRecords), 0)
storage.CreateBin(bin)
time.Sleep(1 * time.Millisecond)
assert.Equal(t, len(storage.binRecords), 0)
storage.StopCleaning()
}

View File

@ -12,4 +12,5 @@ type Storage interface {
type BaseStorage struct {
maxRequests int
binLifetime int64
}