blob: 3c73d46ee2650d07f7bf1d117f0eb42a9873d78f [file] [log] [blame]
package quotaBucket
import (
"errors"
"github.com/30x/apidQuota/services"
)
type QuotaBucketType interface {
resetCount(bucket *QuotaBucket) error
incrementQuotaCount(qBucket *QuotaBucket) (*QuotaBucketResults, error)
resetQuotaForCurrentPeriod(qBucket *QuotaBucket) (*QuotaBucketResults, error)
}
type SynchronousQuotaBucketType struct{}
func (sQuotaBucket SynchronousQuotaBucketType) resetCount(qBucket *QuotaBucket) error {
//do nothing.
return nil
}
func (sQuotaBucket SynchronousQuotaBucketType) resetQuotaForCurrentPeriod(q *QuotaBucket) (*QuotaBucketResults, error) {
weight := q.GetWeight()
weightToReset := -weight
period, err := q.GetPeriod()
if err != nil {
return nil, errors.New("error getting period: " + err.Error())
}
currentCount, err := services.IncrementAndGetCount(q.GetEdgeOrgID(), q.GetID(), weightToReset, period.GetPeriodStartTime().Unix(), period.GetPeriodEndTime().Unix())
exceededCount := currentCount > q.GetMaxCount()
results := &QuotaBucketResults{
EdgeOrgID: q.GetEdgeOrgID(),
ID: q.GetID(),
exceededTokens: exceededCount,
currentTokens: currentCount,
MaxCount: q.GetMaxCount(),
startedAt: period.GetPeriodStartTime().Unix(),
expiresAt: period.GetPeriodEndTime().Unix(),
}
return results, nil
}
func (sQuotaBucket SynchronousQuotaBucketType) incrementQuotaCount(q *QuotaBucket) (*QuotaBucketResults, error) {
maxCount := q.GetMaxCount()
exceededCount := false
allowedCount := int64(0)
weight := q.GetWeight()
period, err := q.GetPeriod()
if err != nil {
return nil, errors.New("error getting period: " + err.Error())
}
//first retrieve the count from counter service.
currentCount, err := services.GetCount(q.GetEdgeOrgID(), q.GetID(), period.GetPeriodStartTime().Unix(), period.GetPeriodEndTime().Unix())
if err != nil {
return nil, err
}
if period.IsCurrentPeriod(q) {
if currentCount < maxCount {
allowed := maxCount - currentCount
if allowed > weight {
if weight != 0 {
currentCount, err = services.IncrementAndGetCount(q.GetEdgeOrgID(), q.GetID(), weight, period.GetPeriodStartTime().Unix(), period.GetPeriodEndTime().Unix())
if err != nil {
return nil, err
}
}
allowedCount = currentCount
} else {
if weight != 0 {
exceededCount = true
}
allowedCount = currentCount + weight
}
} else {
exceededCount = true
allowedCount = currentCount
}
}
results := &QuotaBucketResults{
EdgeOrgID: q.GetEdgeOrgID(),
ID: q.GetID(),
exceededTokens: exceededCount,
currentTokens: allowedCount,
MaxCount: maxCount,
startedAt: period.GetPeriodStartTime().Unix(),
expiresAt: period.GetPeriodEndTime().Unix(),
}
return results, nil
}
type AsynchronousQuotaBucketType struct {
initialized bool
globalCount int64
syncMessageCount int64
syncTimeInSec int64
}
func (quotaBucketType AsynchronousQuotaBucketType) resetCount(q *QuotaBucket) error {
//yet to implement
return nil
}
func (quotaBucketType AsynchronousQuotaBucketType) incrementQuotaCount(q *QuotaBucket) (*QuotaBucketResults, error) {
//getCount()
return nil, nil
}
func (quotaBucketType AsynchronousQuotaBucketType) resetQuotaForCurrentPeriod(q *QuotaBucket) (*QuotaBucketResults, error) {
return nil, nil
}
type NonDistributedQuotaBucketType struct{}
func (sQuotaBucket NonDistributedQuotaBucketType) resetCount(qBucket *QuotaBucket) error {
//yet to implement
return nil
}
func (sQuotaBucket NonDistributedQuotaBucketType) incrementQuotaCount(qBucket *QuotaBucket) (*QuotaBucketResults, error) {
return nil, nil
}
func (sQuotaBucket NonDistributedQuotaBucketType) resetQuotaForCurrentPeriod(q *QuotaBucket) (*QuotaBucketResults, error) {
return nil, nil
}
func GetQuotaBucketHandler(qBucket *QuotaBucket) (QuotaBucketType, error) {
if !qBucket.IsDistrubuted() {
quotaBucketType := &NonDistributedQuotaBucketType{}
return quotaBucketType, nil
} else {
if qBucket.IsSynchronous() {
quotaBucketType := &SynchronousQuotaBucketType{}
return quotaBucketType, nil
}
quotaBucketType := &AsynchronousQuotaBucketType{}
return quotaBucketType, nil
}
return nil, errors.New("ignoring: unrecognized quota type")
}