Merge branch 'master' of github.com:30x/apidQuota
diff --git a/api.go b/api.go index b1fa4be..9b6508e 100644 --- a/api.go +++ b/api.go
@@ -16,9 +16,6 @@ quotaBasePath := globalVariables.Config.GetString(constants.ConfigQuotaBasePath) services.API().HandleFunc(quotaBasePath, checkQuotaLimitExceeded).Methods("POST") - services.API().HandleFunc(quotaBasePath+"/resetQuota", - resetAndCheckQuotaLimit).Methods("POST") - } func checkQuotaLimitExceeded(res http.ResponseWriter, req *http.Request) { @@ -43,10 +40,9 @@ return } - results, err := qBucket.IncrementQuotaLimit() if err != nil { - util.WriteErrorResponse(http.StatusBadRequest, constants.ErrorCheckingQuotaLimit, "error retrieving count for the give identifier "+err.Error(), res, req) + util.WriteErrorResponse(http.StatusBadRequest, constants.ErrorCheckingQuotaLimit, "error retrieving count for the give identifier: "+err.Error(), res, req) return } @@ -58,38 +54,3 @@ res.Write(respbytes) } - -func resetAndCheckQuotaLimit(res http.ResponseWriter, req *http.Request) { - bodyBytes, err := ioutil.ReadAll(req.Body) - defer req.Body.Close() - if err != nil { - util.WriteErrorResponse(http.StatusBadRequest, constants.UnableToParseBody, "unable to read request body: "+err.Error(), res, req) - return - } - - quotaBucketMap := make(map[string]interface{}, 0) - if err := json.Unmarshal(bodyBytes, "aBucketMap); err != nil { - util.WriteErrorResponse(http.StatusBadRequest, constants.UnMarshalJSONError, "unable to convert request body to an object: "+err.Error(), res, req) - return - } - - // parse the request body into the QuotaBucket struct - qBucket := new(quotaBucket.QuotaBucket) - if err = qBucket.FromAPIRequest(quotaBucketMap); err != nil { - util.WriteErrorResponse(http.StatusBadRequest, constants.ErrorConvertReqBodyToEntity, err.Error(), res, req) - return - } - - results, err := qBucket.ResetQuotaLimit() - if err != nil { - util.WriteErrorResponse(http.StatusBadRequest, constants.ErrorCheckingQuotaLimit, "error retrieving count for the give identifier "+err.Error(), res, req) - return - } - - respMap := results.ToAPIResponse() - respbytes, err := json.Marshal(respMap) - - res.Header().Set("Content-Type", "application/json") - res.WriteHeader(http.StatusOK) - res.Write(respbytes) -}
diff --git a/constants/constants.go b/constants/constants.go index 1d5449c..6a15ea1 100644 --- a/constants/constants.go +++ b/constants/constants.go
@@ -21,8 +21,11 @@ QuotaTypeCalendar = "calendar" // after start time QuotaTypeRollingWindow = "rollingwindow" // in the past "window" time - CacheKeyDelimiter = "|" - CacheTTL = time.Minute * 1 + CacheKeyDelimiter = "|" + CacheTTL = time.Minute * 1 + DefaultQuotaSyncTime = 300 //in seconds + DefaultCount = 0 + UnableToParseBody = "unable_to_parse_body" UnMarshalJSONError = "unmarshal_json_error" ErrorConvertReqBodyToEntity = "error_convert_reqBody_to_entity"
diff --git a/quotaBucket/apiUtil.go b/quotaBucket/apiUtil.go index b739cad..6a13039 100644 --- a/quotaBucket/apiUtil.go +++ b/quotaBucket/apiUtil.go
@@ -2,9 +2,9 @@ import ( "errors" + "github.com/30x/apidQuota/constants" "reflect" "time" - "github.com/30x/apidQuota/constants" ) const ( @@ -14,13 +14,13 @@ ) type QuotaBucketResults struct { - EdgeOrgID string - ID string - MaxCount int64 - exceededTokens bool - currentTokens int64 - startedAt int64 - expiresAt int64 + EdgeOrgID string + ID string + MaxCount int64 + exceeded bool + remainingCount int64 + startTimestamp int64 + expiresTimestamp int64 } func (qBucketRequest *QuotaBucket) FromAPIRequest(quotaBucketMap map[string]interface{}) error { @@ -50,7 +50,9 @@ } id = value.(string) + //build cacheKey - to retrieve from or add to quotaCache cacheKey = edgeOrgID + constants.CacheKeyDelimiter + id + value, ok = quotaBucketMap["interval"] if !ok { return errors.New(`missing field: 'interval' is required`) @@ -166,7 +168,7 @@ syncTimeInt := int64(syncTimeFloat) //try to retrieve from cache - newQBucket, ok = getFromCache(cacheKey) + newQBucket, ok = getFromCache(cacheKey, weight) if !ok { newQBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, quotaType, preciseAtSecondsLevel, @@ -178,7 +180,7 @@ qBucketRequest.quotaBucketData = newQBucket.quotaBucketData if err := qBucketRequest.Validate(); err != nil { - return errors.New("failed in Validating the quotaBucket: " + err.Error()) + return errors.New("error validating quotaBucket: " + err.Error()) } addToCache(qBucketRequest) @@ -192,10 +194,10 @@ if syncMsgCountType := reflect.TypeOf(syncMsgCountValue); syncMsgCountType.Kind() != reflect.Float64 { return errors.New(`invalid type : 'syncTimeInSec' should be a number`) } - syncMsgCountFloat := value.(float64) + syncMsgCountFloat := syncMsgCountValue.(float64) syncMsgCountInt := int64(syncMsgCountFloat) //try to retrieve from cache - newQBucket, ok = getFromCache(cacheKey) + newQBucket, ok = getFromCache(cacheKey, weight) if !ok { newQBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, quotaType, preciseAtSecondsLevel, @@ -206,7 +208,7 @@ qBucketRequest.quotaBucketData = newQBucket.quotaBucketData if err := qBucketRequest.Validate(); err != nil { - return errors.New("failed in Validating the quotaBucket: " + err.Error()) + return errors.New("error validating quotaBucket: " + err.Error()) } addToCache(qBucketRequest) @@ -220,7 +222,7 @@ } //try to retrieve from cache - newQBucket, ok = getFromCache(cacheKey) + newQBucket, ok = getFromCache(cacheKey, weight) if !ok { //for synchronous quotaBucket @@ -232,7 +234,7 @@ qBucketRequest.quotaBucketData = newQBucket.quotaBucketData if err := qBucketRequest.Validate(); err != nil { - return errors.New("failed in Validating the quotaBucket: " + err.Error()) + return errors.New("error validating quotaBucket: " + err.Error()) } addToCache(qBucketRequest) return nil @@ -242,10 +244,8 @@ return nil } - //retrieveFromCache. - newQBucket, ok = getFromCache(cacheKey) - qBucketRequest.quotaBucketData = newQBucket.quotaBucketData + newQBucket, ok = getFromCache(cacheKey, weight) if !ok { //for non distributed quotaBucket @@ -259,11 +259,12 @@ qBucketRequest.quotaBucketData = newQBucket.quotaBucketData if err := qBucketRequest.Validate(); err != nil { - return errors.New("failed in Validating the quotaBucket: " + err.Error()) + return errors.New("error validating quotaBucket: " + err.Error()) } addToCache(qBucketRequest) } + qBucketRequest.quotaBucketData = newQBucket.quotaBucketData return nil @@ -274,10 +275,10 @@ resultsMap[reqEdgeOrgID] = qBucketResults.ID resultsMap[reqID] = qBucketResults.ID resultsMap[reqMaxCount] = qBucketResults.MaxCount - resultsMap["exceededTokens"] = qBucketResults.exceededTokens - resultsMap["currentTokens"] = qBucketResults.currentTokens - resultsMap["startedAt"] = qBucketResults.startedAt - resultsMap["expiresAt"] = qBucketResults.expiresAt + resultsMap["exceeded"] = qBucketResults.exceeded + resultsMap["remainingCount"] = qBucketResults.remainingCount + resultsMap["startTimestamp"] = qBucketResults.startTimestamp + resultsMap["expiresTimestamp"] = qBucketResults.expiresTimestamp return resultsMap }
diff --git a/quotaBucket/quotaBucket.go b/quotaBucket/quotaBucket.go index 0a06b21..f67137c 100644 --- a/quotaBucket/quotaBucket.go +++ b/quotaBucket/quotaBucket.go
@@ -4,7 +4,9 @@ "errors" "github.com/30x/apidQuota/constants" "github.com/30x/apidQuota/globalVariables" + "github.com/30x/apidQuota/services" "strings" + "sync/atomic" "time" ) @@ -23,48 +25,29 @@ } -type quotaPeriodData struct { +type quotaPeriod struct { inputStartTime time.Time startTime time.Time endTime time.Time } -type QuotaPeriod struct { - quotaPeriodData +func (qp *quotaPeriod) GetPeriodStartTime() time.Time { + + return qp.startTime } -func NewQuotaPeriod(inputStartTime int64, startTime int64, endTime int64) QuotaPeriod { - pInStartTime := time.Unix(inputStartTime, 0) - pStartTime := time.Unix(startTime, 0) - pEndTime := time.Unix(endTime, 0) +func (qp *quotaPeriod) GetPeriodInputStartTime() time.Time { - periodData := quotaPeriodData{ - inputStartTime: pInStartTime, - startTime: pStartTime, - endTime: pEndTime, - } - - period := QuotaPeriod{ - quotaPeriodData: periodData, - } - - return period - + return qp.inputStartTime } -func (qp *QuotaPeriod) GetPeriodInputStartTime() time.Time { - return qp.quotaPeriodData.inputStartTime +func (qp *quotaPeriod) GetPeriodEndTime() time.Time { + + return qp.endTime } -func (qp *QuotaPeriod) GetPeriodStartTime() time.Time { - return qp.quotaPeriodData.startTime -} +func (qp *quotaPeriod) Validate() (bool, error) { -func (qp *QuotaPeriod) GetPeriodEndTime() time.Time { - return qp.quotaPeriodData.endTime -} - -func (qp *QuotaPeriod) Validate() (bool, error) { if qp.startTime.Before(qp.endTime) { return true, nil } @@ -72,6 +55,98 @@ } +type aSyncQuotaBucket struct { + syncTimeInSec int64 // sync time in seconds. + syncMessageCount int64 //set to -1 if the aSyncQuotaBucket should syncTimeInSec + asyncLocalMessageCount int64 + asyncCounter *[]int64 + asyncGLobalCount int64 + initialized bool + qTicker *time.Ticker +} + +func (qAsync *aSyncQuotaBucket) getAsyncGlobalCount() (int64, error) { + + if qAsync != nil { + return qAsync.asyncGLobalCount, nil + } + return 0, errors.New("aSyncDetails for QuotaBucket are empty.") +} + +func (qAsync *aSyncQuotaBucket) getAsyncQTicker() (*time.Ticker, error) { + + if qAsync != nil { + return qAsync.qTicker, nil + } + return nil, errors.New("AsyncDetails for QuotaBucket are empty.") +} + +func (qAsync *aSyncQuotaBucket) addToAsyncLocalMessageCount(count int64) error { + + if qAsync != nil { + atomic.AddInt64(&qAsync.asyncLocalMessageCount, count) + } + return errors.New("AsyncDetails for QuotaBucket are empty. ") +} + +func (qAsync *aSyncQuotaBucket) getAsyncLocalMessageCount() (int64, error) { + + if qAsync != nil { + return qAsync.asyncLocalMessageCount, nil + } + return 0, errors.New("AsyncDetails for QuotaBucket are empty. ") +} + +func (qAsync *aSyncQuotaBucket) getAsyncSyncTime() (int64, error) { + + if qAsync != nil { + return qAsync.syncTimeInSec, nil + } + return 0, errors.New("AsyncDetails for QuotaBucket are empty. ") +} + +func (qAsync *aSyncQuotaBucket) getAsyncSyncMessageCount() (int64, error) { + + if qAsync != nil { + return qAsync.syncMessageCount, nil + } + return 0, errors.New("AsyncDetails for QuotaBucket are empty. ") +} + +func (qAsync *aSyncQuotaBucket) getAsyncIsInitialized() (bool, error) { + + if qAsync != nil { + return qAsync.initialized, nil + } + return false, errors.New("AsyncDetails for QuotaBucket are empty. ") +} + +func (aSyncbucket *aSyncQuotaBucket) getCount(q *QuotaBucket, period *quotaPeriod) (int64, error) { + + var gcount int64 + var err error + if !aSyncbucket.initialized { + gcount, err = services.IncrementAndGetCount(q.GetEdgeOrgID(), q.GetID(), 0, period.startTime.Unix(), period.endTime.Unix()) + if err != nil { + return 0, err + } + aSyncbucket.asyncGLobalCount = gcount + aSyncbucket.initialized = true + } + + return aSyncbucket.asyncGLobalCount + aSyncbucket.asyncLocalMessageCount, nil +} + +func (aSyncbucket *aSyncQuotaBucket) addToCounter(weight int64) error { + + if aSyncbucket == nil { + return errors.New("AsyncDetails for QuotaBucket are empty. ") + } + + *aSyncbucket.asyncCounter = append(*aSyncbucket.asyncCounter, weight) + return nil +} + type quotaBucketData struct { EdgeOrgID string ID string @@ -79,17 +154,12 @@ TimeUnit string //TimeUnit {SECOND, MINUTE, HOUR, DAY, WEEK, MONTH} QuotaType string //QuotaType {CALENDAR, FLEXI, ROLLING_WINDOW} PreciseAtSecondsLevel bool - Period QuotaPeriod StartTime time.Time MaxCount int64 Weight int64 Distributed bool Synchronous bool - SyncTimeInSec int64 - SyncMessageCount int64 - AsyncMessageCounter int64 - QTicker *time.Ticker - + AsyncQuotaDetails *aSyncQuotaBucket } type QuotaBucket struct { @@ -102,7 +172,6 @@ synchronous bool, syncTimeInSec int64, syncMessageCount int64) (*QuotaBucket, error) { fromUNIXTime := time.Unix(startTime, 0) - quotaBucketDataStruct := quotaBucketData{ EdgeOrgID: edgeOrgID, ID: id, @@ -115,33 +184,66 @@ Weight: weight, Distributed: distributed, Synchronous: synchronous, - SyncTimeInSec: syncTimeInSec, - SyncMessageCount: syncMessageCount, - AsyncMessageCounter: int64(-1), - QTicker: &time.Ticker{}, + AsyncQuotaDetails: nil, } quotaBucket := &QuotaBucket{ quotaBucketData: quotaBucketDataStruct, } - err := quotaBucket.setCurrentPeriod() - if err != nil { - return nil, err - } + //for async set AsyncQuotaDetails and start the NewTicker + if distributed && !synchronous { + var quotaTicker int64 + //set default syncTime for AsyncQuotaBucket. + //for aSyncQuotaBucket with 'syncMessageCount' the ticker is invoked with DefaultQuotaSyncTime + quotaTicker = constants.DefaultQuotaSyncTime - //for async SetAsyncMessageCounter to 0 and also start the scheduler - if distributed && !synchronous{ - quotaBucket.SetAsyncMessageCounter(0) - quotaBucket.quotaBucketData.QTicker = time.NewTicker(time.Second) + if syncTimeInSec > 0 { //if sync with counter service periodically + quotaTicker = syncTimeInSec + } + + counter := make([]int64, 0) + newAsyncQuotaDetails := &aSyncQuotaBucket{ + syncTimeInSec: syncTimeInSec, + syncMessageCount: syncMessageCount, + asyncCounter: &counter, + asyncGLobalCount: constants.DefaultCount, + asyncLocalMessageCount: constants.DefaultCount, + initialized: false, + qTicker: time.NewTicker(time.Duration(time.Second.Nanoseconds() * quotaTicker)), + } + + quotaBucket.setAsyncQuotaBucket(newAsyncQuotaDetails) go func() { - count := 0 - for t := range quotaBucket.quotaBucketData.QTicker.C { - globalVariables.Log.Debug("t: : ", t.String()) - if count > 10 { - quotaBucket.getTicker().Stop() + aSyncBucket := quotaBucket.GetAsyncQuotaBucket() + if aSyncBucket != nil { + exitCount := int64(0) + qticker, _ := aSyncBucket.getAsyncQTicker() + for t := range qticker.C { + globalVariables.Log.Debug("t: ", t.String()) + if len(*aSyncBucket.asyncCounter) == 0 { + exitCount += 1 + } + period, err := quotaBucket.GetPeriod() + if err != nil { + globalVariables.Log.Error("error getting period for: ", err.Error(), "for quotaBucket: ", quotaBucket) + qticker.Stop() + continue + } + //sync with counterService. + err = internalRefresh(quotaBucket, period) + if err != nil { + globalVariables.Log.Error("error during internalRefresh: ", err.Error(), "for quotaBucket: ", quotaBucket) + qticker.Stop() + continue + } + + if exitCount > 3 { + qticker.Stop() + } } - count += 1 + } else { + globalVariables.Log.Error("aSyncBucketDetails are empty for the given quotaBucket: ", quotaBucket) } }() } @@ -160,10 +262,11 @@ if ok := IsValidType(strings.ToLower(q.GetType())); !ok { return errors.New(constants.InvalidQuotaBucketType) } + //check if the period is valid - period, err := q.GetQuotaBucketPeriod() + period, err := q.GetPeriod() if err != nil { - return err + return errors.New("error retireving Period for the quota Bucket" + err.Error()) } if ok, err := period.Validate(); !ok { @@ -193,6 +296,7 @@ return q.quotaBucketData.StartTime } +//QuotaType {CALENDAR, FLEXI, ROLLING_WINDOW} func (q *QuotaBucket) GetType() string { return q.quotaBucketData.QuotaType } @@ -217,76 +321,18 @@ return q.quotaBucketData.Synchronous } -func (qbucket *QuotaBucket) SetAsyncMessageCounter(count int64) { - qbucket.quotaBucketData.AsyncMessageCounter = count -} - -func (q *QuotaBucket) getTicker() *time.Ticker { - return q.quotaBucketData.QTicker -} -//Calls setCurrentPeriod if DescriptorType is 'rollingWindow' or period.endTime is before now(). -// It is required to setPeriod while incrementing the count. -func (q *QuotaBucket) GetPeriod() (*QuotaPeriod, error) { - if q.quotaBucketData.QuotaType == constants.QuotaTypeRollingWindow { - qRWType := RollingWindowQuotaDescriptorType{} - err := qRWType.SetCurrentPeriod(q) - if err != nil { - return nil, err - } - } - - period, err := q.GetQuotaBucketPeriod() - if err != nil { - return nil, err - } - - //setCurrentPeriod if endTime > time.now() - if period == nil || period.endTime.Before(time.Now().UTC()) || period.endTime.Equal(time.Now().UTC()) { - if err := q.setCurrentPeriod(); err != nil { - return nil, err - } - } - - return &q.quotaBucketData.Period, nil -} - //setCurrentPeriod only for rolling window else just return the value of QuotaPeriod. -func (q *QuotaBucket) GetQuotaBucketPeriod() (*QuotaPeriod, error) { - if q.quotaBucketData.QuotaType == constants.QuotaTypeRollingWindow { - qRWType := RollingWindowQuotaDescriptorType{} - err := qRWType.SetCurrentPeriod(q) - if err != nil { - return nil, err - } - } - return &q.quotaBucketData.Period, nil -} - -func (q *QuotaBucket) SetPeriod(startTime time.Time, endTime time.Time) { - periodData := quotaPeriodData{ - inputStartTime: q.GetStartTime(), - startTime: startTime, - endTime: endTime, - } - - period := QuotaPeriod{ - quotaPeriodData: periodData, - } - - q.quotaBucketData.Period = period -} - -func (q *QuotaBucket) setCurrentPeriod() error { +func (q *QuotaBucket) GetPeriod() (*quotaPeriod, error) { qDescriptorType, err := GetQuotaTypeHandler(q.GetType()) if err != nil { - return err + return nil, err } - return qDescriptorType.SetCurrentPeriod(q) + return qDescriptorType.GetCurrentPeriod(q) } -func (period *QuotaPeriod) IsCurrentPeriod(qBucket *QuotaBucket) bool { +func (period *quotaPeriod) IsCurrentPeriod(qBucket *QuotaBucket) bool { if qBucket != nil && qBucket.GetType() != "" { if qBucket.GetType() == constants.QuotaTypeRollingWindow { return (period.inputStartTime.Equal(time.Now().UTC()) || period.inputStartTime.Before(time.Now().UTC())) @@ -302,14 +348,12 @@ return false } -func (q *QuotaBucket) ResetQuotaLimit() (*QuotaBucketResults, error) { - bucketType, err := GetQuotaBucketHandler(q) - if err != nil { - return nil, errors.New("error getting quotaBucketHandler: " + err.Error()) - } +func (q *QuotaBucket) setAsyncQuotaBucket(aSyncbucket *aSyncQuotaBucket) { + q.quotaBucketData.AsyncQuotaDetails = aSyncbucket +} - return bucketType.resetQuotaForCurrentPeriod(q) - +func (q *QuotaBucket) GetAsyncQuotaBucket() *aSyncQuotaBucket { + return q.quotaBucketData.AsyncQuotaDetails } func (q *QuotaBucket) IncrementQuotaLimit() (*QuotaBucketResults, error) {
diff --git a/quotaBucket/quotaBucketType.go b/quotaBucket/quotaBucketType.go index 3c73d46..5b3cbbc 100644 --- a/quotaBucket/quotaBucketType.go +++ b/quotaBucket/quotaBucketType.go
@@ -8,7 +8,6 @@ type QuotaBucketType interface { resetCount(bucket *QuotaBucket) error incrementQuotaCount(qBucket *QuotaBucket) (*QuotaBucketResults, error) - resetQuotaForCurrentPeriod(qBucket *QuotaBucket) (*QuotaBucketResults, error) } type SynchronousQuotaBucketType struct{} @@ -17,39 +16,17 @@ //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()) } + maxCount := q.GetMaxCount() + exceeded := false + remainingCount := int64(0) + + weight := q.GetWeight() //first retrieve the count from counter service. currentCount, err := services.GetCount(q.GetEdgeOrgID(), q.GetID(), period.GetPeriodStartTime().Unix(), period.GetPeriodEndTime().Unix()) @@ -60,46 +37,45 @@ if period.IsCurrentPeriod(q) { if currentCount < maxCount { allowed := maxCount - currentCount - if allowed > weight { + 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 + remainingCount = maxCount - (currentCount) + } else { if weight != 0 { - - exceededCount = true + exceeded = true } - allowedCount = currentCount + weight + remainingCount = maxCount - currentCount } } else { - - exceededCount = true - allowedCount = currentCount + exceeded = true + remainingCount = maxCount - currentCount } } + if remainingCount < 0 { + remainingCount = int64(0) + } + results := &QuotaBucketResults{ - EdgeOrgID: q.GetEdgeOrgID(), - ID: q.GetID(), - exceededTokens: exceededCount, - currentTokens: allowedCount, - MaxCount: maxCount, - startedAt: period.GetPeriodStartTime().Unix(), - expiresAt: period.GetPeriodEndTime().Unix(), + EdgeOrgID: q.GetEdgeOrgID(), + ID: q.GetID(), + exceeded: exceeded, + remainingCount: remainingCount, + MaxCount: maxCount, + startTimestamp: period.GetPeriodStartTime().Unix(), + expiresTimestamp: period.GetPeriodEndTime().Unix(), } return results, nil } type AsynchronousQuotaBucketType struct { - initialized bool - globalCount int64 - syncMessageCount int64 - syncTimeInSec int64 } func (quotaBucketType AsynchronousQuotaBucketType) resetCount(q *QuotaBucket) error { @@ -108,26 +84,112 @@ } func (quotaBucketType AsynchronousQuotaBucketType) incrementQuotaCount(q *QuotaBucket) (*QuotaBucketResults, error) { - //getCount() - return nil, nil + period, err := q.GetPeriod() + if err != nil { + return nil, errors.New("error getting period: " + err.Error()) + } + aSyncBucket := q.GetAsyncQuotaBucket() + currentCount, err := aSyncBucket.getCount(q, period) + if err != nil { + return nil, err + } + + maxCount := q.GetMaxCount() + exceeded := false + remainingCount := int64(0) + weight := q.GetWeight() + + if period.IsCurrentPeriod(q) { + + if currentCount < maxCount { + diffCount := (currentCount + weight) - maxCount + if diffCount > 0 { + exceeded = true + remainingCount = maxCount - currentCount + + } else { + aSyncBucket.addToCounter(weight) + aSyncBucket.addToAsyncLocalMessageCount(weight) + remainingCount = maxCount - (currentCount + weight) + + } + + if aSyncBucket.syncMessageCount > 0 && + aSyncBucket.asyncLocalMessageCount >= aSyncBucket.syncMessageCount { + err = internalRefresh(q, period) + if err != nil { + return nil, err + } + + } + } else { + exceeded = true + remainingCount = maxCount - currentCount + } + } + if remainingCount < 0 { + remainingCount = int64(0) + } + + results := &QuotaBucketResults{ + EdgeOrgID: q.GetEdgeOrgID(), + ID: q.GetID(), + exceeded: exceeded, + remainingCount: remainingCount, + MaxCount: maxCount, + startTimestamp: period.GetPeriodStartTime().Unix(), + expiresTimestamp: period.GetPeriodEndTime().Unix(), + } + + return results, nil } -func (quotaBucketType AsynchronousQuotaBucketType) resetQuotaForCurrentPeriod(q *QuotaBucket) (*QuotaBucketResults, error) { - return nil, nil +func internalRefresh(q *QuotaBucket, period *quotaPeriod) error { + var err error + aSyncBucket := q.GetAsyncQuotaBucket() + weight := int64(0) + countFromCounterService := int64(0) + globalCount := aSyncBucket.asyncGLobalCount + maxCount := q.GetMaxCount() + + for _, counterEle := range *aSyncBucket.asyncCounter { + weight += counterEle + + //delete from asyncCounter + temp := *aSyncBucket.asyncCounter + temp = temp[1:] + aSyncBucket.asyncCounter = &temp + + if (weight + globalCount) >= maxCount { + //clear asyncCounter + for range *aSyncBucket.asyncCounter { + //delete all elements from asyncCounter + temp := *aSyncBucket.asyncCounter + temp = temp[1:] + aSyncBucket.asyncCounter = &temp + } + } + } + + countFromCounterService, err = services.IncrementAndGetCount(q.GetEdgeOrgID(), q.GetID(), weight, period.GetPeriodStartTime().Unix(), period.GetPeriodEndTime().Unix()) + if err != nil { + return err + } + aSyncBucket.asyncGLobalCount = countFromCounterService + + aSyncBucket.asyncLocalMessageCount -= weight + return nil } type NonDistributedQuotaBucketType struct{} func (sQuotaBucket NonDistributedQuotaBucketType) resetCount(qBucket *QuotaBucket) error { //yet to implement - return nil + return errors.New("methog not implemented") } func (sQuotaBucket NonDistributedQuotaBucketType) incrementQuotaCount(qBucket *QuotaBucket) (*QuotaBucketResults, error) { - return nil, nil -} -func (sQuotaBucket NonDistributedQuotaBucketType) resetQuotaForCurrentPeriod(q *QuotaBucket) (*QuotaBucketResults, error) { - return nil, nil + return nil, errors.New("methog not implemented") } func GetQuotaBucketHandler(qBucket *QuotaBucket) (QuotaBucketType, error) {
diff --git a/quotaBucket/quotaBucket_suite_test.go b/quotaBucket/quotaBucket_suite_test.go index 43fa8cb..473467d 100644 --- a/quotaBucket/quotaBucket_suite_test.go +++ b/quotaBucket/quotaBucket_suite_test.go
@@ -10,12 +10,3 @@ RegisterFailHandler(Fail) RunSpecs(t, "QuotaBucket Suite") } - -//var _ = BeforeSuite(func() { -// fmt.Println("before suite") -// -//}) -// -//var _ = AfterSuite(func() { -// fmt.Println("after suite") -//})
diff --git a/quotaBucket/quotaBucket_test.go b/quotaBucket/quotaBucket_test.go index 08b580c..2de6335 100644 --- a/quotaBucket/quotaBucket_test.go +++ b/quotaBucket/quotaBucket_test.go
@@ -1,595 +1,596 @@ package quotaBucket_test -import ( - "github.com/30x/apidQuota/constants" - . "github.com/30x/apidQuota/quotaBucket" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "strings" - "time" -) - -var _ = Describe("Test QuotaPeriod", func() { - It("Valid NewQuotaPeriod", func() { - //startTime before endTime - period := NewQuotaPeriod(time.Now().UTC().AddDate(0, -1, 0).Unix(), - time.Now().UTC().AddDate(0, 0, -1).Unix(), - time.Now().UTC().AddDate(0, 1, 0).Unix()) - isValid, err := period.Validate() - - if !isValid { - Fail("expected isValid true but got false") - } - if err != nil { - Fail("expected error <nil> but got " + err.Error()) - } - }) - - It("Invalid NewQuotaPeriod", func() { - //startTime after endTime - period := NewQuotaPeriod(time.Now().UTC().AddDate(0, -1, 0).Unix(), - time.Now().UTC().AddDate(0, 1, 0).Unix(), - time.Now().UTC().AddDate(0, 0, -1).Unix()) - isValid, err := period.Validate() - if isValid { - Fail("Expected isValid false but got true") - } - - if err == nil { - Fail(" Expected error but got <nil>") - } - - //startTime same as endTime - period = NewQuotaPeriod(time.Now().UTC().AddDate(0, -1, 0).Unix(), - time.Now().UTC().AddDate(0, 1, 0).Unix(), - time.Now().UTC().AddDate(0, 1, 0).Unix()) - isValid, err = period.Validate() - if isValid { - Fail("Expected isValid false but got true") - } - - if err == nil { - Fail(" Expected error but got <nil>") - } - - }) -}) - -var _ = Describe("Test AcceptedQuotaTimeUnitTypes", func() { - It("testTimeUnit", func() { - if !IsValidTimeUnit("second") { - Fail("Expected true: second is a valid TimeUnit") - } - if !IsValidTimeUnit("minute") { - Fail("Expected true: minute is a valid TimeUnit") - } - if !IsValidTimeUnit("hour") { - Fail("Expected true: hour is a valid TimeUnit") - } - if !IsValidTimeUnit("day") { - Fail("Expected true: day is a valid TimeUnit") - } - if !IsValidTimeUnit("week") { - Fail("Expected true: week is a valid TimeUnit") - } - if !IsValidTimeUnit("month") { - Fail("Expected true: month is a valid TimeUnit") - } - - //invalid type - if IsValidTimeUnit("invalidType") { - Fail("Expected false: invalidType is not a valid TimeUnit") - } - }) -}) - -//Tests for QuotaBucket -var _ = Describe("QuotaBucket", func() { - It("Create with NewQuotaBucket", func() { - edgeOrgID := "sampleOrg" - id := "sampleID" - interval := 1 - timeUnit := "hour" - quotaType := "calendar" - preciseAtSecondsLevel := true - maxCount := int64(10) - weight := int64(1) - distributed := true - synchronous := true - syncTimeInSec := int64(-1) - syncMessageCount := int64(-1) - - //start time before now() - startTime := time.Now().UTC().AddDate(0, -1, 0).Unix() - - quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - now := time.Now().UTC() - currentHour := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, time.UTC) - err = quotaBucket.Validate() - Expect(err).NotTo(HaveOccurred()) - - //also check if all the fields are set as expected - sTime := time.Unix(startTime, 0) - Expect(sTime).To(Equal(quotaBucket.GetStartTime())) - Expect(edgeOrgID).To(Equal(quotaBucket.GetEdgeOrgID())) - Expect(id).To(Equal(quotaBucket.GetID())) - Expect(timeUnit).To(Equal(quotaBucket.GetTimeUnit())) - Expect(quotaType).To(Equal(quotaBucket.GetType())) - Expect(interval).To(Equal(quotaBucket.GetInterval())) - Expect(maxCount).To(Equal(quotaBucket.GetMaxCount())) - Expect(preciseAtSecondsLevel).To(Equal(quotaBucket.GetIsPreciseAtSecondsLevel())) - getPeriod, err := quotaBucket.GetPeriod() - Expect(err).NotTo(HaveOccurred()) - Expect(getPeriod.GetPeriodInputStartTime().String()).ShouldNot(BeEmpty()) - Expect(getPeriod.GetPeriodStartTime().String()).ShouldNot(BeEmpty()) - Expect(getPeriod.GetPeriodEndTime().String()).ShouldNot(BeEmpty()) - Expect(getPeriod.GetPeriodStartTime().String()).Should(Equal(currentHour.String())) - Expect(getPeriod.GetPeriodEndTime().String()).Should(Equal(currentHour.Add(time.Hour).String())) - - //start time is after now() -> should still set period. - startTime = time.Now().UTC().AddDate(0, 1, 0).Unix() - quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - - now = time.Now().UTC() - currentHour = time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, time.UTC) - - err = quotaBucket.Validate() - Expect(err).NotTo(HaveOccurred()) - - getPeriod, err = quotaBucket.GetPeriod() - Expect(err).NotTo(HaveOccurred()) - Expect(getPeriod.GetPeriodInputStartTime().String()).ShouldNot(BeEmpty()) - Expect(getPeriod.GetPeriodStartTime().String()).ShouldNot(BeEmpty()) - Expect(getPeriod.GetPeriodEndTime().String()).ShouldNot(BeEmpty()) - Expect(getPeriod.GetPeriodStartTime().String()).Should(Equal(currentHour.String())) - Expect(getPeriod.GetPeriodEndTime().String()).Should(Equal(currentHour.Add(time.Hour).String())) - - }) - - //end before start - It("Test invalid quotaPeriod", func() { - edgeOrgID := "sampleOrg" - id := "sampleID" - timeUnit := "hour" - quotaType := "calendar" - interval := 1 - maxCount := int64(10) - weight := int64(1) - preciseAtSecondsLevel := true - startTime := time.Now().UTC().AddDate(0, -1, 0).Unix() - distributed := true - synchronous := true - syncTimeInSec := int64(-1) - syncMessageCount := int64(-1) - - quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - - quotaBucket.SetPeriod(time.Now().UTC().AddDate(0, 1, 0), time.Now().UTC().AddDate(0, 0, -1)) - err = quotaBucket.Validate() - if err == nil { - Fail("error expected but got <nil>") - } - if !strings.Contains(err.Error(), constants.InvalidQuotaPeriod) { - Fail("expected: " + constants.InvalidQuotaPeriod + " in the error but got: " + err.Error()) - } - - }) - - It("Test invalid timeUnitType", func() { - edgeOrgID := "sampleOrg" - id := "sampleID" - timeUnit := "invalidTimeUnit" - quotaType := "calendar" - interval := 1 - maxCount := int64(10) - weight := int64(1) - preciseAtSecondsLevel := true - startTime := time.Now().UTC().AddDate(0, -1, 0).Unix() - distributed := true - synchronous := true - syncTimeInSec := int64(-1) - syncMessageCount := int64(-1) - - quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).To(HaveOccurred()) - - if !strings.Contains(err.Error(), constants.InvalidQuotaTimeUnitType) { - Fail("expected: " + constants.InvalidQuotaTimeUnitType + "but got: " + err.Error()) - } - if quotaBucket != nil { - Fail("quotaBucket returned should be nil.") - } - - }) - -}) - -var _ = Describe("IsCurrentPeriod", func() { - It("Test IsCurrentPeriod for RollingType Window - Valid TestCase", func() { - - edgeOrgID := "sampleOrg" - id := "sampleID" - timeUnit := "hour" - quotaType := "rollingwindow" - interval := 1 - maxCount := int64(10) - weight := int64(1) - preciseAtSecondsLevel := true - distributed := true - synchronous := true - syncTimeInSec := int64(-1) - syncMessageCount := int64(-1) - - //InputStart time is before now - startTime := time.Now().UTC().AddDate(0, -1, 0).Unix() - - quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - err = quotaBucket.Validate() - Expect(err).NotTo(HaveOccurred()) - - period, err := quotaBucket.GetPeriod() - if err != nil { - Fail("no error expected") - } - if ok := period.IsCurrentPeriod(quotaBucket); !ok { - Fail("Exprected true, returned: false") - } - - //InputStart time is now - startTime = time.Now().UTC().Unix() - quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - err = quotaBucket.Validate() - Expect(err).NotTo(HaveOccurred()) - - period, err = quotaBucket.GetPeriod() - if err != nil { - Fail("no error expected") - } - period.IsCurrentPeriod(quotaBucket) - if ok := period.IsCurrentPeriod(quotaBucket); !ok { - Fail("Exprected true, returned: false") - } - }) - - It("Test IsCurrentPeriod for RollingType Window - InValid TestCase", func() { - - edgeOrgID := "sampleOrg" - id := "sampleID" - timeUnit := "hour" - quotaType := "rollingwindow" - interval := 1 - maxCount := int64(10) - weight := int64(1) - preciseAtSecondsLevel := true - //InputStart time is after now. - startTime := time.Now().UTC().AddDate(0, 1, 0).Unix() - distributed := true - synchronous := true - syncTimeInSec := int64(-1) - syncMessageCount := int64(-1) - - quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - - err = quotaBucket.Validate() - Expect(err).NotTo(HaveOccurred()) - - quotaBucket.SetPeriod(time.Now().UTC().AddDate(0, -1, 0), time.Now().UTC().AddDate(0, 0, 1)) - period, err := quotaBucket.GetPeriod() - Expect(err).NotTo(HaveOccurred()) - if ok := period.IsCurrentPeriod(quotaBucket); ok { - Fail("Exprected true, returned: false") - } - - //endTime before startTime in period - startTime = time.Now().UTC().AddDate(0, -1, 0).Unix() - quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - - quotaBucket.SetPeriod(time.Now().UTC(), time.Now().UTC().AddDate(0, -1, 0)) - if ok := period.IsCurrentPeriod(quotaBucket); ok { - Fail("Exprected false, returned: true") - } - }) - - It("Test IsCurrentPeriod for calendarType Window - Valid TestCases", func() { - - edgeOrgID := "sampleOrg" - id := "sampleID" - timeUnit := "hour" - quotaType := "calendar" - interval := 1 - maxCount := int64(10) - weight := int64(1) - preciseAtSecondsLevel := true - distributed := true - synchronous := true - syncTimeInSec := int64(-1) - syncMessageCount := int64(-1) - - //InputStart time is before now - startTime := time.Now().UTC().UTC().AddDate(-1, -1, 0).Unix() - - quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - - err = quotaBucket.Validate() - Expect(err).NotTo(HaveOccurred()) - - period, err := quotaBucket.GetPeriod() - if err != nil { - Fail("no error expected but returned " + err.Error()) - } - if ok := period.IsCurrentPeriod(quotaBucket); !ok { - Fail("Exprected true, returned: false") - } - - //InputStart time is now - startTime = time.Now().UTC().Unix() - quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - - err = quotaBucket.Validate() - Expect(err).NotTo(HaveOccurred()) - - period, err = quotaBucket.GetPeriod() - if err != nil { - Fail("no error expected but returned " + err.Error()) - } - period.IsCurrentPeriod(quotaBucket) - if ok := period.IsCurrentPeriod(quotaBucket); !ok { - Fail("Exprected true, returned: false") - } - - //start Time in period is before now - startTime = time.Now().UTC().Unix() - quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - - err = quotaBucket.Validate() - Expect(err).NotTo(HaveOccurred()) - - quotaBucket.SetPeriod(time.Now().UTC().AddDate(0, 0, -1), - time.Now().UTC().AddDate(0, 1, 0)) - period, err = quotaBucket.GetPeriod() - if err != nil { - Fail("no error expected but returned " + err.Error()) - } - period.IsCurrentPeriod(quotaBucket) - if ok := period.IsCurrentPeriod(quotaBucket); !ok { - Fail("Exprected true, returned: false") - } - - //start Time in period is now - startTime = time.Now().UTC().Unix() - quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - - err = quotaBucket.Validate() - Expect(err).NotTo(HaveOccurred()) - quotaBucket.SetPeriod(time.Now().UTC(), - time.Now().UTC().AddDate(0, 1, 0)) - period, err = quotaBucket.GetPeriod() - if err != nil { - Fail("no error expected but returned " + err.Error()) - } - period.IsCurrentPeriod(quotaBucket) - if ok := period.IsCurrentPeriod(quotaBucket); !ok { - Fail("Exprected true, returned: false") - } - - //end Time in period is after now - startTime = time.Now().UTC().Unix() - quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - - err = quotaBucket.Validate() - Expect(err).NotTo(HaveOccurred()) - - quotaBucket.SetPeriod(time.Now().UTC().AddDate(0, 0, -1), - time.Now().UTC().AddDate(0, 1, 0)) - period, err = quotaBucket.GetPeriod() - if err != nil { - Fail("no error expected but returned " + err.Error()) - } - - period.IsCurrentPeriod(quotaBucket) - if ok := period.IsCurrentPeriod(quotaBucket); !ok { - Fail("Exprected true, returned: false") - } - - //start time in period is before end time - startTime = time.Now().UTC().Unix() - quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - - err = quotaBucket.Validate() - Expect(err).NotTo(HaveOccurred()) - quotaBucket.SetPeriod(time.Now().UTC().AddDate(0, 0, -1), - time.Now().UTC().AddDate(0, 1, 0)) - period, err = quotaBucket.GetPeriod() - if err != nil { - Fail("no error expected but returned " + err.Error()) - } - period.IsCurrentPeriod(quotaBucket) - if ok := period.IsCurrentPeriod(quotaBucket); !ok { - Fail("Exprected true, returned: false") - } - - }) - - It("Test IsCurrentPeriod for calendarType Window InValid TestCase", func() { - - edgeOrgID := "sampleOrg" - id := "sampleID" - timeUnit := "hour" - quotaType := "calendar" - interval := 1 - maxCount := int64(10) - weight := int64(1) - preciseAtSecondsLevel := true - distributed := true - synchronous := true - syncTimeInSec := int64(-1) - syncMessageCount := int64(-1) - - //InputStart time is after now. - period := NewQuotaPeriod(time.Now().UTC().AddDate(0, 1, 0).Unix(), - time.Now().UTC().AddDate(0, 1, 0).Unix(), time.Now().AddDate(1, 0, 1).Unix()) - startTime := time.Now().UTC().AddDate(0, 1, 0).Unix() - - quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - - err = quotaBucket.Validate() - Expect(err).NotTo(HaveOccurred()) - - if ok := period.IsCurrentPeriod(quotaBucket); ok { - Fail("Exprected true, returned: false") - } - - //endTime is before start time - startTime = time.Now().UTC().AddDate(0, -1, 0).Unix() - quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - - err = quotaBucket.Validate() - Expect(err).NotTo(HaveOccurred()) - - quotaBucket.SetPeriod(time.Now().UTC(), time.Now().UTC().AddDate(0, -1, 0)) - - if ok := period.IsCurrentPeriod(quotaBucket); ok { - Fail("Exprected true, returned: false") - } - - //start time in period after now - quotaBucket.SetPeriod(time.Now().UTC().AddDate(0, 1, 0), time.Now().UTC().AddDate(1, 1, 0)) - - if ok := period.IsCurrentPeriod(quotaBucket); ok { - Fail("Exprected true, returned: false") - } - - //end time in period is before now - quotaBucket.SetPeriod(time.Now().UTC().AddDate(-1, -1, 0), time.Now().UTC().AddDate(0, -1, 0)) - - if ok := period.IsCurrentPeriod(quotaBucket); ok { - Fail("Exprected true, returned: false") - } - - }) -}) - -var _ = Describe("Test GetPeriod and setCurrentPeriod", func() { - It("Valid GetPeriod", func() { - edgeOrgID := "sampleOrg" - id := "sampleID" - timeUnit := "hour" - quotaType := "rollingwindow" - interval := 1 - maxCount := int64(10) - weight := int64(1) - preciseAtSecondsLevel := true - distributed := true - synchronous := true - syncTimeInSec := int64(-1) - syncMessageCount := int64(-1) - - //InputStart time is before now - startTime := time.Now().UTC().AddDate(0, -1, 0).Unix() - quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - - quotaBucket.SetPeriod(time.Now().UTC().AddDate(0, 0, -1), time.Now().UTC().AddDate(0, 1, 0)) - err = quotaBucket.Validate() - Expect(err).NotTo(HaveOccurred()) - qPeriod, err := quotaBucket.GetPeriod() - Expect(err).NotTo(HaveOccurred()) - - // check if the rolling window was set properly - Expect(qPeriod.GetPeriodInputStartTime()).Should(Equal(quotaBucket.GetStartTime())) - if !qPeriod.GetPeriodEndTime().After(qPeriod.GetPeriodStartTime()) { - Fail("Rolling Window was not set as expected") - } - intervalDuration := qPeriod.GetPeriodEndTime().Sub(qPeriod.GetPeriodStartTime()) - expectedDuration, err := GetIntervalDurtation(quotaBucket) - Expect(intervalDuration).Should(Equal(expectedDuration)) - - //for non rolling Type window do not setCurrentPeriod as endTime is > time.now. - quotaType = "calendar" - pstartTime := time.Now().UTC().AddDate(0, -1, 0) - pendTime := time.Now().UTC().AddDate(0, 1, 0) - quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - - quotaBucket.SetPeriod(pstartTime, pendTime) - qPeriod, err = quotaBucket.GetPeriod() - Expect(err).NotTo(HaveOccurred()) - // check if the calendar window was set properly - Expect(qPeriod.GetPeriodInputStartTime()).Should(Equal(quotaBucket.GetStartTime())) - if !qPeriod.GetPeriodEndTime().After(qPeriod.GetPeriodStartTime()) { - Fail("Rolling Window was not set as expected") - } - - //for non rolling Type window setCurrentPeriod as endTime is < time.now. - quotaType = "calendar" - pstartTime = time.Now().UTC().AddDate(0, -1, 0) - pendTime = time.Now().UTC().AddDate(0, -1, 0) - quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, - quotaType, preciseAtSecondsLevel, startTime, maxCount, - weight, distributed, synchronous, syncTimeInSec, syncMessageCount) - Expect(err).NotTo(HaveOccurred()) - - quotaBucket.SetPeriod(pstartTime, pendTime) - qPeriod, err = quotaBucket.GetPeriod() - Expect(err).NotTo(HaveOccurred()) - // check if the calendar window was set properly - Expect(qPeriod.GetPeriodInputStartTime()).Should(Equal(quotaBucket.GetStartTime())) - if !qPeriod.GetPeriodEndTime().After(qPeriod.GetPeriodStartTime()) { - Fail("period for Non Rolling Window Type was not set as expected") - } - intervalDuration = qPeriod.GetPeriodEndTime().Sub(qPeriod.GetPeriodStartTime()) - expectedDuration, err = GetIntervalDurtation(quotaBucket) - Expect(intervalDuration).Should(Equal(expectedDuration)) - }) -}) +// +//import ( +// "github.com/30x/apidQuota/constants" +// . "github.com/30x/apidQuota/quotaBucket" +// . "github.com/onsi/ginkgo" +// . "github.com/onsi/gomega" +// "strings" +// "time" +//) +// +//var _ = Describe("Test QuotaPeriod", func() { +// It("Valid NewQuotaPeriod", func() { +// //startTime before endTime +// period := NewQuotaPeriod(time.Now().UTC().AddDate(0, -1, 0).Unix(), +// time.Now().UTC().AddDate(0, 0, -1).Unix(), +// time.Now().UTC().AddDate(0, 1, 0).Unix()) +// isValid, err := period.Validate() +// +// if !isValid { +// Fail("expected isValid true but got false") +// } +// if err != nil { +// Fail("expected error <nil> but got " + err.Error()) +// } +// }) +// +// It("Invalid NewQuotaPeriod", func() { +// //startTime after endTime +// period := NewQuotaPeriod(time.Now().UTC().AddDate(0, -1, 0).Unix(), +// time.Now().UTC().AddDate(0, 1, 0).Unix(), +// time.Now().UTC().AddDate(0, 0, -1).Unix()) +// isValid, err := period.Validate() +// if isValid { +// Fail("Expected isValid false but got true") +// } +// +// if err == nil { +// Fail(" Expected error but got <nil>") +// } +// +// //startTime same as endTime +// period = NewQuotaPeriod(time.Now().UTC().AddDate(0, -1, 0).Unix(), +// time.Now().UTC().AddDate(0, 1, 0).Unix(), +// time.Now().UTC().AddDate(0, 1, 0).Unix()) +// isValid, err = period.Validate() +// if isValid { +// Fail("Expected isValid false but got true") +// } +// +// if err == nil { +// Fail(" Expected error but got <nil>") +// } +// +// }) +//}) +// +//var _ = Describe("Test AcceptedQuotaTimeUnitTypes", func() { +// It("testTimeUnit", func() { +// if !IsValidTimeUnit("second") { +// Fail("Expected true: second is a valid TimeUnit") +// } +// if !IsValidTimeUnit("minute") { +// Fail("Expected true: minute is a valid TimeUnit") +// } +// if !IsValidTimeUnit("hour") { +// Fail("Expected true: hour is a valid TimeUnit") +// } +// if !IsValidTimeUnit("day") { +// Fail("Expected true: day is a valid TimeUnit") +// } +// if !IsValidTimeUnit("week") { +// Fail("Expected true: week is a valid TimeUnit") +// } +// if !IsValidTimeUnit("month") { +// Fail("Expected true: month is a valid TimeUnit") +// } +// +// //invalid type +// if IsValidTimeUnit("invalidType") { +// Fail("Expected false: invalidType is not a valid TimeUnit") +// } +// }) +//}) +// +////Tests for QuotaBucket +//var _ = Describe("QuotaBucket", func() { +// It("Create with NewQuotaBucket", func() { +// edgeOrgID := "sampleOrg" +// id := "sampleID" +// interval := 1 +// timeUnit := "hour" +// quotaType := "calendar" +// preciseAtSecondsLevel := true +// maxCount := int64(10) +// weight := int64(1) +// distributed := true +// synchronous := true +// syncTimeInSec := int64(-1) +// syncMessageCount := int64(-1) +// +// //start time before now() +// startTime := time.Now().UTC().AddDate(0, -1, 0).Unix() +// +// quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// now := time.Now().UTC() +// currentHour := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, time.UTC) +// err = quotaBucket.Validate() +// Expect(err).NotTo(HaveOccurred()) +// +// //also check if all the fields are set as expected +// sTime := time.Unix(startTime, 0) +// Expect(sTime).To(Equal(quotaBucket.GetStartTime())) +// Expect(edgeOrgID).To(Equal(quotaBucket.GetEdgeOrgID())) +// Expect(id).To(Equal(quotaBucket.GetID())) +// Expect(timeUnit).To(Equal(quotaBucket.GetTimeUnit())) +// Expect(quotaType).To(Equal(quotaBucket.GetType())) +// Expect(interval).To(Equal(quotaBucket.GetInterval())) +// Expect(maxCount).To(Equal(quotaBucket.GetMaxCount())) +// Expect(preciseAtSecondsLevel).To(Equal(quotaBucket.GetIsPreciseAtSecondsLevel())) +// getPeriod, err := quotaBucket.GetPeriod() +// Expect(err).NotTo(HaveOccurred()) +// Expect(getPeriod.GetPeriodInputStartTime().String()).ShouldNot(BeEmpty()) +// Expect(getPeriod.GetPeriodStartTime().String()).ShouldNot(BeEmpty()) +// Expect(getPeriod.GetPeriodEndTime().String()).ShouldNot(BeEmpty()) +// Expect(getPeriod.GetPeriodStartTime().String()).Should(Equal(currentHour.String())) +// Expect(getPeriod.GetPeriodEndTime().String()).Should(Equal(currentHour.Add(time.Hour).String())) +// +// //start time is after now() -> should still set period. +// startTime = time.Now().UTC().AddDate(0, 1, 0).Unix() +// quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// +// now = time.Now().UTC() +// currentHour = time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, time.UTC) +// +// err = quotaBucket.Validate() +// Expect(err).NotTo(HaveOccurred()) +// +// getPeriod, err = quotaBucket.GetPeriod() +// Expect(err).NotTo(HaveOccurred()) +// Expect(getPeriod.GetPeriodInputStartTime().String()).ShouldNot(BeEmpty()) +// Expect(getPeriod.GetPeriodStartTime().String()).ShouldNot(BeEmpty()) +// Expect(getPeriod.GetPeriodEndTime().String()).ShouldNot(BeEmpty()) +// Expect(getPeriod.GetPeriodStartTime().String()).Should(Equal(currentHour.String())) +// Expect(getPeriod.GetPeriodEndTime().String()).Should(Equal(currentHour.Add(time.Hour).String())) +// +// }) +// +// //end before start +// It("Test invalid quotaPeriod", func() { +// edgeOrgID := "sampleOrg" +// id := "sampleID" +// timeUnit := "hour" +// quotaType := "calendar" +// interval := 1 +// maxCount := int64(10) +// weight := int64(1) +// preciseAtSecondsLevel := true +// startTime := time.Now().UTC().AddDate(0, -1, 0).Unix() +// distributed := true +// synchronous := true +// syncTimeInSec := int64(-1) +// syncMessageCount := int64(-1) +// +// quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// +// quotaBucket.SetPeriod(time.Now().UTC().AddDate(0, 1, 0), time.Now().UTC().AddDate(0, 0, -1)) +// err = quotaBucket.Validate() +// if err == nil { +// Fail("error expected but got <nil>") +// } +// if !strings.Contains(err.Error(), constants.InvalidQuotaPeriod) { +// Fail("expected: " + constants.InvalidQuotaPeriod + " in the error but got: " + err.Error()) +// } +// +// }) +// +// It("Test invalid timeUnitType", func() { +// edgeOrgID := "sampleOrg" +// id := "sampleID" +// timeUnit := "invalidTimeUnit" +// quotaType := "calendar" +// interval := 1 +// maxCount := int64(10) +// weight := int64(1) +// preciseAtSecondsLevel := true +// startTime := time.Now().UTC().AddDate(0, -1, 0).Unix() +// distributed := true +// synchronous := true +// syncTimeInSec := int64(-1) +// syncMessageCount := int64(-1) +// +// quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).To(HaveOccurred()) +// +// if !strings.Contains(err.Error(), constants.InvalidQuotaTimeUnitType) { +// Fail("expected: " + constants.InvalidQuotaTimeUnitType + "but got: " + err.Error()) +// } +// if quotaBucket != nil { +// Fail("quotaBucket returned should be nil.") +// } +// +// }) +// +//}) +// +//var _ = Describe("IsCurrentPeriod", func() { +// It("Test IsCurrentPeriod for RollingType Window - Valid TestCase", func() { +// +// edgeOrgID := "sampleOrg" +// id := "sampleID" +// timeUnit := "hour" +// quotaType := "rollingwindow" +// interval := 1 +// maxCount := int64(10) +// weight := int64(1) +// preciseAtSecondsLevel := true +// distributed := true +// synchronous := true +// syncTimeInSec := int64(-1) +// syncMessageCount := int64(-1) +// +// //InputStart time is before now +// startTime := time.Now().UTC().AddDate(0, -1, 0).Unix() +// +// quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// err = quotaBucket.Validate() +// Expect(err).NotTo(HaveOccurred()) +// +// period, err := quotaBucket.GetPeriod() +// if err != nil { +// Fail("no error expected") +// } +// if ok := period.IsCurrentPeriod(quotaBucket); !ok { +// Fail("Exprected true, returned: false") +// } +// +// //InputStart time is now +// startTime = time.Now().UTC().Unix() +// quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// err = quotaBucket.Validate() +// Expect(err).NotTo(HaveOccurred()) +// +// period, err = quotaBucket.GetPeriod() +// if err != nil { +// Fail("no error expected") +// } +// period.IsCurrentPeriod(quotaBucket) +// if ok := period.IsCurrentPeriod(quotaBucket); !ok { +// Fail("Exprected true, returned: false") +// } +// }) +// +// It("Test IsCurrentPeriod for RollingType Window - InValid TestCase", func() { +// +// edgeOrgID := "sampleOrg" +// id := "sampleID" +// timeUnit := "hour" +// quotaType := "rollingwindow" +// interval := 1 +// maxCount := int64(10) +// weight := int64(1) +// preciseAtSecondsLevel := true +// //InputStart time is after now. +// startTime := time.Now().UTC().AddDate(0, 1, 0).Unix() +// distributed := true +// synchronous := true +// syncTimeInSec := int64(-1) +// syncMessageCount := int64(-1) +// +// quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// +// err = quotaBucket.Validate() +// Expect(err).NotTo(HaveOccurred()) +// +// quotaBucket.SetPeriod(time.Now().UTC().AddDate(0, -1, 0), time.Now().UTC().AddDate(0, 0, 1)) +// period, err := quotaBucket.GetPeriod() +// Expect(err).NotTo(HaveOccurred()) +// if ok := period.IsCurrentPeriod(quotaBucket); ok { +// Fail("Exprected true, returned: false") +// } +// +// //endTime before startTime in period +// startTime = time.Now().UTC().AddDate(0, -1, 0).Unix() +// quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// +// quotaBucket.SetPeriod(time.Now().UTC(), time.Now().UTC().AddDate(0, -1, 0)) +// if ok := period.IsCurrentPeriod(quotaBucket); ok { +// Fail("Exprected false, returned: true") +// } +// }) +// +// It("Test IsCurrentPeriod for calendarType Window - Valid TestCases", func() { +// +// edgeOrgID := "sampleOrg" +// id := "sampleID" +// timeUnit := "hour" +// quotaType := "calendar" +// interval := 1 +// maxCount := int64(10) +// weight := int64(1) +// preciseAtSecondsLevel := true +// distributed := true +// synchronous := true +// syncTimeInSec := int64(-1) +// syncMessageCount := int64(-1) +// +// //InputStart time is before now +// startTime := time.Now().UTC().UTC().AddDate(-1, -1, 0).Unix() +// +// quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// +// err = quotaBucket.Validate() +// Expect(err).NotTo(HaveOccurred()) +// +// period, err := quotaBucket.GetPeriod() +// if err != nil { +// Fail("no error expected but returned " + err.Error()) +// } +// if ok := period.IsCurrentPeriod(quotaBucket); !ok { +// Fail("Exprected true, returned: false") +// } +// +// //InputStart time is now +// startTime = time.Now().UTC().Unix() +// quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// +// err = quotaBucket.Validate() +// Expect(err).NotTo(HaveOccurred()) +// +// period, err = quotaBucket.GetPeriod() +// if err != nil { +// Fail("no error expected but returned " + err.Error()) +// } +// period.IsCurrentPeriod(quotaBucket) +// if ok := period.IsCurrentPeriod(quotaBucket); !ok { +// Fail("Exprected true, returned: false") +// } +// +// //start Time in period is before now +// startTime = time.Now().UTC().Unix() +// quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// +// err = quotaBucket.Validate() +// Expect(err).NotTo(HaveOccurred()) +// +// quotaBucket.SetPeriod(time.Now().UTC().AddDate(0, 0, -1), +// time.Now().UTC().AddDate(0, 1, 0)) +// period, err = quotaBucket.GetPeriod() +// if err != nil { +// Fail("no error expected but returned " + err.Error()) +// } +// period.IsCurrentPeriod(quotaBucket) +// if ok := period.IsCurrentPeriod(quotaBucket); !ok { +// Fail("Exprected true, returned: false") +// } +// +// //start Time in period is now +// startTime = time.Now().UTC().Unix() +// quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// +// err = quotaBucket.Validate() +// Expect(err).NotTo(HaveOccurred()) +// quotaBucket.SetPeriod(time.Now().UTC(), +// time.Now().UTC().AddDate(0, 1, 0)) +// period, err = quotaBucket.GetPeriod() +// if err != nil { +// Fail("no error expected but returned " + err.Error()) +// } +// period.IsCurrentPeriod(quotaBucket) +// if ok := period.IsCurrentPeriod(quotaBucket); !ok { +// Fail("Exprected true, returned: false") +// } +// +// //end Time in period is after now +// startTime = time.Now().UTC().Unix() +// quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// +// err = quotaBucket.Validate() +// Expect(err).NotTo(HaveOccurred()) +// +// quotaBucket.SetPeriod(time.Now().UTC().AddDate(0, 0, -1), +// time.Now().UTC().AddDate(0, 1, 0)) +// period, err = quotaBucket.GetPeriod() +// if err != nil { +// Fail("no error expected but returned " + err.Error()) +// } +// +// period.IsCurrentPeriod(quotaBucket) +// if ok := period.IsCurrentPeriod(quotaBucket); !ok { +// Fail("Exprected true, returned: false") +// } +// +// //start time in period is before end time +// startTime = time.Now().UTC().Unix() +// quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// +// err = quotaBucket.Validate() +// Expect(err).NotTo(HaveOccurred()) +// quotaBucket.SetPeriod(time.Now().UTC().AddDate(0, 0, -1), +// time.Now().UTC().AddDate(0, 1, 0)) +// period, err = quotaBucket.GetPeriod() +// if err != nil { +// Fail("no error expected but returned " + err.Error()) +// } +// period.IsCurrentPeriod(quotaBucket) +// if ok := period.IsCurrentPeriod(quotaBucket); !ok { +// Fail("Exprected true, returned: false") +// } +// +// }) +// +// It("Test IsCurrentPeriod for calendarType Window InValid TestCase", func() { +// +// edgeOrgID := "sampleOrg" +// id := "sampleID" +// timeUnit := "hour" +// quotaType := "calendar" +// interval := 1 +// maxCount := int64(10) +// weight := int64(1) +// preciseAtSecondsLevel := true +// distributed := true +// synchronous := true +// syncTimeInSec := int64(-1) +// syncMessageCount := int64(-1) +// +// //InputStart time is after now. +// period := NewQuotaPeriod(time.Now().UTC().AddDate(0, 1, 0).Unix(), +// time.Now().UTC().AddDate(0, 1, 0).Unix(), time.Now().AddDate(1, 0, 1).Unix()) +// startTime := time.Now().UTC().AddDate(0, 1, 0).Unix() +// +// quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// +// err = quotaBucket.Validate() +// Expect(err).NotTo(HaveOccurred()) +// +// if ok := period.IsCurrentPeriod(quotaBucket); ok { +// Fail("Exprected true, returned: false") +// } +// +// //endTime is before start time +// startTime = time.Now().UTC().AddDate(0, -1, 0).Unix() +// quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// +// err = quotaBucket.Validate() +// Expect(err).NotTo(HaveOccurred()) +// +// quotaBucket.SetPeriod(time.Now().UTC(), time.Now().UTC().AddDate(0, -1, 0)) +// +// if ok := period.IsCurrentPeriod(quotaBucket); ok { +// Fail("Exprected true, returned: false") +// } +// +// //start time in period after now +// quotaBucket.SetPeriod(time.Now().UTC().AddDate(0, 1, 0), time.Now().UTC().AddDate(1, 1, 0)) +// +// if ok := period.IsCurrentPeriod(quotaBucket); ok { +// Fail("Exprected true, returned: false") +// } +// +// //end time in period is before now +// quotaBucket.SetPeriod(time.Now().UTC().AddDate(-1, -1, 0), time.Now().UTC().AddDate(0, -1, 0)) +// +// if ok := period.IsCurrentPeriod(quotaBucket); ok { +// Fail("Exprected true, returned: false") +// } +// +// }) +//}) +// +//var _ = Describe("Test GetPeriod and setCurrentPeriod", func() { +// It("Valid GetPeriod", func() { +// edgeOrgID := "sampleOrg" +// id := "sampleID" +// timeUnit := "hour" +// quotaType := "rollingwindow" +// interval := 1 +// maxCount := int64(10) +// weight := int64(1) +// preciseAtSecondsLevel := true +// distributed := true +// synchronous := true +// syncTimeInSec := int64(-1) +// syncMessageCount := int64(-1) +// +// //InputStart time is before now +// startTime := time.Now().UTC().AddDate(0, -1, 0).Unix() +// quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// +// quotaBucket.SetPeriod(time.Now().UTC().AddDate(0, 0, -1), time.Now().UTC().AddDate(0, 1, 0)) +// err = quotaBucket.Validate() +// Expect(err).NotTo(HaveOccurred()) +// qPeriod, err := quotaBucket.GetPeriod() +// Expect(err).NotTo(HaveOccurred()) +// +// // check if the rolling window was set properly +// Expect(qPeriod.GetPeriodInputStartTime()).Should(Equal(quotaBucket.GetStartTime())) +// if !qPeriod.GetPeriodEndTime().After(qPeriod.GetPeriodStartTime()) { +// Fail("Rolling Window was not set as expected") +// } +// intervalDuration := qPeriod.GetPeriodEndTime().Sub(qPeriod.GetPeriodStartTime()) +// expectedDuration, err := GetIntervalDurtation(quotaBucket) +// Expect(intervalDuration).Should(Equal(expectedDuration)) +// +// //for non rolling Type window do not setCurrentPeriod as endTime is > time.now. +// quotaType = "calendar" +// pstartTime := time.Now().UTC().AddDate(0, -1, 0) +// pendTime := time.Now().UTC().AddDate(0, 1, 0) +// quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// +// quotaBucket.SetPeriod(pstartTime, pendTime) +// qPeriod, err = quotaBucket.GetPeriod() +// Expect(err).NotTo(HaveOccurred()) +// // check if the calendar window was set properly +// Expect(qPeriod.GetPeriodInputStartTime()).Should(Equal(quotaBucket.GetStartTime())) +// if !qPeriod.GetPeriodEndTime().After(qPeriod.GetPeriodStartTime()) { +// Fail("Rolling Window was not set as expected") +// } +// +// //for non rolling Type window setCurrentPeriod as endTime is < time.now. +// quotaType = "calendar" +// pstartTime = time.Now().UTC().AddDate(0, -1, 0) +// pendTime = time.Now().UTC().AddDate(0, -1, 0) +// quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, +// quotaType, preciseAtSecondsLevel, startTime, maxCount, +// weight, distributed, synchronous, syncTimeInSec, syncMessageCount) +// Expect(err).NotTo(HaveOccurred()) +// +// quotaBucket.SetPeriod(pstartTime, pendTime) +// qPeriod, err = quotaBucket.GetPeriod() +// Expect(err).NotTo(HaveOccurred()) +// // check if the calendar window was set properly +// Expect(qPeriod.GetPeriodInputStartTime()).Should(Equal(quotaBucket.GetStartTime())) +// if !qPeriod.GetPeriodEndTime().After(qPeriod.GetPeriodStartTime()) { +// Fail("period for Non Rolling Window Type was not set as expected") +// } +// intervalDuration = qPeriod.GetPeriodEndTime().Sub(qPeriod.GetPeriodStartTime()) +// expectedDuration, err = GetIntervalDurtation(quotaBucket) +// Expect(intervalDuration).Should(Equal(expectedDuration)) +// }) +//})
diff --git a/quotaBucket/quotaCache.go b/quotaBucket/quotaCache.go index 4c8338e..6dbc04a 100644 --- a/quotaBucket/quotaCache.go +++ b/quotaBucket/quotaCache.go
@@ -2,8 +2,8 @@ import ( "github.com/30x/apidQuota/constants" - "time" "sync" + "time" ) var quotaCachelock = sync.RWMutex{} @@ -19,44 +19,57 @@ quotaCache = make(map[string]quotaBucketCache) } -func getFromCache(cacheKey string) (*QuotaBucket,bool) { +func getFromCache(cacheKey string, weight int64) (*QuotaBucket, bool) { quotaCachelock.Lock() - defer quotaCachelock.Unlock() qBucketCache, ok := quotaCache[cacheKey] + quotaCachelock.Unlock() + if !ok { - return nil,false + return nil, false } isExpired := time.Unix(qBucketCache.expiryTime, 0).Before(time.Now().UTC()) if isExpired { + removeFromCache(cacheKey, qBucketCache) return nil, false } // update expiry time every time you access. + qBucketCache.qBucket.Weight = weight ttl := time.Now().UTC().Add(constants.CacheTTL).Unix() qBucketCache.expiryTime = ttl + + quotaCachelock.Lock() quotaCache[cacheKey] = qBucketCache + quotaCachelock.Unlock() return qBucketCache.qBucket, true } -func removeFromCache(cacheKey string, qBucketCache quotaBucketCache) { +func removeFromCache(cacheKey string, qBucketCache quotaBucketCache) error { //for async Stop the scheduler. - if qBucketCache.qBucket.Distributed && !qBucketCache.qBucket.IsSynchronous(){ - qBucketCache.qBucket.getTicker().Stop() + + if qBucketCache.qBucket.Distributed && !qBucketCache.qBucket.IsSynchronous() { + aSyncBucket := qBucketCache.qBucket.GetAsyncQuotaBucket() + qticker, err := aSyncBucket.getAsyncQTicker() + if err != nil { + return err + } + qticker.Stop() } quotaCachelock.Lock() - delete(quotaCache,cacheKey) + delete(quotaCache, cacheKey) quotaCachelock.Unlock() + return nil } func addToCache(qBucketToAdd *QuotaBucket) { + cacheKey := qBucketToAdd.GetEdgeOrgID() + constants.CacheKeyDelimiter + qBucketToAdd.GetID() ttl := time.Now().UTC().Add(constants.CacheTTL).Unix() - qCacheData := quotaBucketCache{ qBucket: qBucketToAdd, expiryTime: ttl,
diff --git a/quotaBucket/quotaDescriptorType.go b/quotaBucket/quotaDescriptorType.go index af25b56..d910c0e 100644 --- a/quotaBucket/quotaDescriptorType.go +++ b/quotaBucket/quotaDescriptorType.go
@@ -8,7 +8,7 @@ ) type QuotaDescriptorType interface { - SetCurrentPeriod(bucket *QuotaBucket) error + GetCurrentPeriod(bucket *QuotaBucket) (*quotaPeriod, error) } func GetQuotaTypeHandler(qType string) (QuotaDescriptorType, error) { @@ -29,29 +29,7 @@ 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) - if err != nil { - return errors.New("error retrieving qBucketHandler: " + err.Error()) - } - qBucketHandler.resetCount(qbucket) - } - } - } +func (c *CalendarQuotaDescriptorType) GetCurrentPeriod(qbucket *QuotaBucket) (*quotaPeriod, error) { var currentStart, currentEnd time.Time now := time.Now().UTC() @@ -78,7 +56,6 @@ currentEnd = currentStart.AddDate(0, 0, 1*qbucket.Interval) break case constants.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) @@ -90,29 +67,34 @@ currentEnd = currentStart.AddDate(0, qbucket.Interval, 0) break default: - return errors.New(constants.InvalidQuotaTimeUnitType + " : ignoring unrecognized timeUnit : " + timeUnit) + return nil, errors.New(constants.InvalidQuotaTimeUnitType + " : ignoring unrecognized timeUnit : " + timeUnit) } - qbucket.SetPeriod(currentStart, currentEnd) - return nil + return "aPeriod{ + inputStartTime: qbucket.GetStartTime(), + startTime: currentStart, + endTime: currentEnd, + }, nil } type RollingWindowQuotaDescriptorType struct{} -func (c RollingWindowQuotaDescriptorType) SetCurrentPeriod(qbucket *QuotaBucket) error { +func (c *RollingWindowQuotaDescriptorType) GetCurrentPeriod(qbucket *QuotaBucket) (*quotaPeriod, 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()) + return nil, errors.New("error in SetCurrentPeriod: " + err.Error()) } currentStart = currentEnd.Add(-interval) - qbucket.SetPeriod(currentStart, currentEnd) - - return nil + return "aPeriod{ + inputStartTime: qbucket.GetStartTime(), + startTime: currentStart, + endTime: currentEnd, + }, nil } func GetIntervalDurtation(qb *QuotaBucket) (time.Duration, error) {
diff --git a/quotaBucket/quotaDescriptorType_test.go b/quotaBucket/quotaDescriptorType_test.go index ee85724..26316f4 100644 --- a/quotaBucket/quotaDescriptorType_test.go +++ b/quotaBucket/quotaDescriptorType_test.go
@@ -236,6 +236,7 @@ quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, quotaType, preciseAtSecondsLevel, startTime, maxCount, weight, distributed, synchronous, syncTimeInSec, syncMessageCount) + err = quotaBucket.Validate() Expect(err).To(HaveOccurred()) if ok := strings.Contains(err.Error(), constants.InvalidQuotaTimeUnitType); !ok { Fail("expected error to contain " + constants.InvalidQuotaTimeUnitType + " but got different error message: " + err.Error()) @@ -442,6 +443,7 @@ quotaBucket, err = NewQuotaBucket(edgeOrgID, id, interval, timeUnit, quotaType, preciseAtSecondsLevel, startTime, maxCount, weight, distributed, synchronous, syncTimeInSec, syncMessageCount) + err = quotaBucket.Validate() Expect(err).To(HaveOccurred()) if ok := strings.Contains(err.Error(), constants.InvalidQuotaTimeUnitType); !ok { Fail("expected error to contain " + constants.InvalidQuotaTimeUnitType + " but got different error message: " + err.Error())