blob: 8dec92cf461cf94e9d0b168ca7a5fa635b91e76d [file] [log] [blame]
package quotaBucket
import (
"errors"
"strings"
"time"
)
const (
QuotaTypeCalendar = "calendar" // after start time
QuotaTypeFlexi = "flexi" //after first request
QuotaTypeRollingWindow = "rollingwindow" // in the past "window" time
)
type QuotaDescriptorType interface {
SetCurrentPeriod(bucket *QuotaBucket) error
}
func GetQuotaDescriptorTypeHandler(qType string) (QuotaDescriptorType, error) {
var qDescriptor QuotaDescriptorType
quotaType := strings.ToLower(strings.TrimSpace(qType))
switch quotaType {
case QuotaTypeCalendar:
qDescriptor = &CalendarQuotaDescriptorType{}
return qDescriptor, nil
case QuotaTypeRollingWindow:
qDescriptor = &RollingWindowQuotaDescriptorType{}
return qDescriptor, nil
default:
return nil, errors.New(InvalidQuotaDescriptorType + " Quota type " + qType + " in the request is not supported")
}
}
type CalendarQuotaDescriptorType struct{}
func (c CalendarQuotaDescriptorType) SetCurrentPeriod(qbucket *QuotaBucket) error {
startTime := qbucket.GetStartTime()
currentPeriod, err := qbucket.GetQuotaBucketPeriod()
if err != nil {
return err
}
if startTime.Before(time.Now().UTC()) || startTime.Equal(time.Now().UTC()) {
if currentPeriod != nil {
if currentPeriod.IsCurrentPeriod(qbucket) {
return nil
}
} else {
if currentPeriod.IsCurrentPeriod(qbucket) {
return nil
} else {
qBucketHandler, err := GetQuotaBucketHandler(qbucket.BucketType)
if err != nil {
return errors.New("error getting QuotaBucketType: " + err.Error())
}
qBucketHandler.resetCount(qbucket)
}
}
}
var currentStart, currentEnd time.Time
now := time.Now().UTC()
timeUnit := strings.ToLower(strings.TrimSpace(qbucket.TimeUnit))
switch timeUnit {
case TimeUnitSECOND:
currentStart = time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), 0, time.UTC)
secInDuration := time.Duration(int64(qbucket.Interval) * time.Second.Nanoseconds())
currentEnd = currentStart.Add(secInDuration)
break
case TimeUnitMINUTE:
currentStart = time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), 0, 0, time.UTC)
minInDuration := time.Duration(int64(qbucket.Interval) * time.Minute.Nanoseconds())
currentEnd = currentStart.Add(minInDuration)
break
case TimeUnitHOUR:
currentStart = time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, time.UTC)
hoursInDuration := time.Duration(int64(qbucket.Interval) * time.Hour.Nanoseconds())
currentEnd = currentStart.Add(hoursInDuration)
break
case TimeUnitDAY:
currentStart = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC)
currentEnd = currentStart.AddDate(0, 0, 1*qbucket.Interval)
break
case TimeUnitWEEK:
//todo
currentStart = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC)
for currentStart.Weekday() != time.Monday {
currentStart = currentStart.AddDate(0, 0, -1)
}
currentEnd = currentStart.AddDate(0, 0, 7*qbucket.Interval)
break
case TimeUnitMONTH:
currentStart = time.Date(now.Year(), now.Month(), 0, 0, 0, 0, 0, time.UTC)
currentEnd = currentStart.AddDate(0, qbucket.Interval, 0)
break
default:
return errors.New(InvalidQuotaTimeUnitType + " : ignoring unrecognized timeUnit : " + timeUnit)
}
qbucket.SetPeriod(currentStart, currentEnd)
return nil
}
type RollingWindowQuotaDescriptorType struct{}
func (c RollingWindowQuotaDescriptorType) SetCurrentPeriod(qbucket *QuotaBucket) error {
//yet to implement
var currentStart, currentEnd time.Time
currentEnd = time.Now().UTC()
interval, err := GetIntervalDurtation(qbucket)
if err != nil {
return errors.New("error in SetCurrentPeriod: " + err.Error())
}
currentStart = currentEnd.Add(-interval)
qbucket.SetPeriod(currentStart, currentEnd)
return nil
}
func GetIntervalDurtation(qb *QuotaBucket) (time.Duration, error) {
timeUnit := strings.ToLower(strings.TrimSpace(qb.TimeUnit))
switch timeUnit {
case TimeUnitSECOND:
return time.Duration(int64(qb.Interval) * time.Second.Nanoseconds()), nil
case TimeUnitMINUTE:
return time.Duration(int64(qb.Interval) * time.Minute.Nanoseconds()), nil
case TimeUnitHOUR:
return time.Duration(int64(qb.Interval) * time.Hour.Nanoseconds()), nil
case TimeUnitDAY:
return time.Duration(int64(qb.Interval*24) * time.Hour.Nanoseconds()), nil
case TimeUnitWEEK:
return time.Duration(int64(qb.Interval*24*7) * time.Hour.Nanoseconds()), nil
case TimeUnitMONTH:
now := time.Now().UTC()
var currentStart, currentEnd time.Time
quotaType := strings.ToLower(strings.TrimSpace(qb.QuotaDescriptorType))
switch quotaType {
case QuotaTypeCalendar:
currentStart = time.Date(now.Year(), now.Month(), 0, 0, 0, 0, 0, time.UTC)
currentEnd = currentStart.AddDate(0, qb.Interval, 0)
return currentEnd.Sub(currentStart), nil
case QuotaTypeRollingWindow:
currentEnd = now
currentStart = currentEnd.AddDate(0, (-1)*qb.Interval, 0)
return currentEnd.Sub(currentStart), nil
default:
return time.Duration(0), errors.New(InvalidQuotaDescriptorType + " : ignoring unrecognized quotaType : " + quotaType)
}
default:
return time.Duration(0), errors.New(InvalidQuotaTimeUnitType + " : ignoring unrecognized timeUnit : " + timeUnit)
}
}