refactor
diff --git a/api.go b/api.go
index cebd66b..2ad5103 100644
--- a/api.go
+++ b/api.go
@@ -2,7 +2,6 @@
import (
"encoding/json"
- "fmt"
"github.com/30x/apid-core"
"github.com/30x/apidQuota/constants"
"github.com/30x/apidQuota/globalVariables"
@@ -43,12 +42,11 @@
results, err := qBucket.IncrementQuotaLimit()
if err != nil {
- util.WriteErrorResponse(http.StatusBadRequest, constants.UnMarshalJSONError, "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
}
respMap := results.ToAPIResponse()
- fmt.Println("results from inc quota: ", results)
respbytes, err := json.Marshal(respMap)
res.Header().Set("Content-Type", "application/json")
diff --git a/api_test.go b/api_test.go
index 9d6452c..4bae205 100644
--- a/api_test.go
+++ b/api_test.go
@@ -3,15 +3,96 @@
import (
. "github.com/onsi/ginkgo"
//"net/http"
+ "encoding/json"
+ "net/http"
+ "io/ioutil"
+ "bytes"
+ "time"
)
func init() {
//testAPIDQuotaURL = ""
}
-var _ = Describe("Api", func() {
- It("test Synchronous quota", func() {
+var testhttpClient *http.Client = &http.Client{
+ //setting the timeout to 60 sec for requests to counterService
+ Timeout: time.Duration(60 * time.Second),
+}
- //req, err := http.NewRequest("POST", )
+const testQuotaAPIURL = "http://localhost:9000/quota"
+
+var _ = Describe("Api Tests", func() {
+ FIt("test Synchronous quota - valid test cases", func() {
+ requestData := make(map[string]interface{})
+ requestData["edgeOrgID"] = "testTenant"
+ requestData["id"] = "testID"
+ requestData["interval"] = 1
+ requestData["timeUnit"] = "HOUR"
+ requestData["quotaType"] = "CALENDAR"
+ requestData["preciseAtSecondsLevel"] = false
+ requestData["startTime"] = 1489189921
+ requestData["maxCount"] = 5
+ requestData["bucketType"] = "Synchronous"
+ requestData["weight"] = 2
+
+ reqBytes, err := json.Marshal(requestData)
+ if err != nil {
+ Fail("error converting requestBody into bytes: " + err.Error())
+ }
+
+ //valid request body
+ req, err := http.NewRequest("POST", testQuotaAPIURL, ioutil.NopCloser(bytes.NewReader(reqBytes)))
+ if err != nil {
+ Fail("error getting newRequest: " + err.Error())
+ }
+
+ res, err := testhttpClient.Do(req)
+ if err != nil {
+ Fail("error calling the api: " + err.Error())
+ }
+
+ // Check the status code is what we expect.
+ if status := res.StatusCode; status != http.StatusOK {
+ Fail("wrong status code: " + res.Status)
+ }
+
+ //valid request - case insensitive - timeUnit, quotaType, bucketType
+ requestData["timeUnit"] = "HoUR"
+ requestData["quotaType"] = "cALEndar"
+ requestData["bucketType"] = "syncHRonous"
+
+ req, err = http.NewRequest("POST", testQuotaAPIURL, ioutil.NopCloser(bytes.NewReader(reqBytes)))
+ if err != nil {
+ Fail("error getting newRequest: " + err.Error())
+ }
+
+ res, err = testhttpClient.Do(req)
+ if err != nil {
+ Fail("error calling the api: " + err.Error())
+ }
+
+ // Check the status code is what we expect.
+ if status := res.StatusCode; status != http.StatusOK {
+ Fail("wrong status code: " + res.Status)
+ }
+
+ //valid request - startTime not sent in request - optional.
+ delete(requestData, "startTime")
+
+ req, err = http.NewRequest("POST", testQuotaAPIURL, ioutil.NopCloser(bytes.NewReader(reqBytes)))
+ if err != nil {
+ Fail("error getting newRequest: " + err.Error())
+ }
+
+ res, err = testhttpClient.Do(req)
+ if err != nil {
+ Fail("error calling the api: " + err.Error())
+ }
+
+ // Check the status code is what we expect.
+ if status := res.StatusCode; status != http.StatusOK {
+ Fail("wrong status code: " + res.Status)
+ }
+
})
})
diff --git a/constants/constants.go b/constants/constants.go
index 9ced04b..261e9cb 100644
--- a/constants/constants.go
+++ b/constants/constants.go
@@ -5,6 +5,7 @@
UnMarshalJSONError = "unmarshal_json_error"
ErrorConvertReqBodyToEntity = "error_convert_reqBody_to_entity"
ConfigQuotaBasePath = "quota_base_path"
+ ErrorCheckingQuotaLimit = "error_checking_quota_limit"
QuotaBasePathDefault = "/quota"
ConfigCounterServiceBasePath = "counterService_base_path"
diff --git a/quotaBucket/apiUtil.go b/quotaBucket/apiUtil.go
index 5515271..30cffed 100644
--- a/quotaBucket/apiUtil.go
+++ b/quotaBucket/apiUtil.go
@@ -3,14 +3,21 @@
import (
"errors"
"reflect"
+ "time"
+)
+
+const (
+ reqEdgeOrgID = "edgeOrgID"
+ reqID = "id"
+ reqMaxCount = "maxCount"
)
type QuotaBucketResults struct {
EdgeOrgID string
ID string
- exceededTokens bool
- allowedTokens int64
MaxCount int64
+ exceededTokens bool
+ currentTokens int64
startedAt int64
expiresAt int64
}
@@ -21,7 +28,7 @@
var startTime, maxCount, weight int64
var preciseAtSecondsLevel bool
- value, ok := quotaBucketMap["edgeOrgID"]
+ value, ok := quotaBucketMap[reqEdgeOrgID]
if !ok {
return errors.New(`missing field: 'edgeOrgID' is required`)
}
@@ -30,7 +37,7 @@
}
edgeOrgID = value.(string)
- value, ok = quotaBucketMap["id"]
+ value, ok = quotaBucketMap[reqID]
if !ok {
return errors.New(`missing field: 'id' is required`)
}
@@ -80,8 +87,8 @@
preciseAtSecondsLevel = value.(bool)
value, ok = quotaBucketMap["startTime"]
- if !ok {
- return errors.New(`missing field: 'startTime' is required`)
+ if !ok { //todo: in the current cps code startTime is optional for QuotaBucket. should we make start time optional to NewQuotaBucket?
+ startTime = time.Now().UTC().Unix()
}
//from input when its read its float, need to then convert to int.
if startTimeType := reflect.TypeOf(value); startTimeType.Kind() != reflect.Float64 {
@@ -90,7 +97,7 @@
startTimeFloat := value.(float64)
startTime = int64(startTimeFloat)
- value, ok = quotaBucketMap["maxCount"]
+ value, ok = quotaBucketMap[reqMaxCount]
if !ok {
return errors.New(`missing field: 'maxCount' is required`)
}
@@ -121,10 +128,9 @@
weightFloat := value.(float64)
weight = int64(weightFloat)
-
newQBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, quotaType, preciseAtSecondsLevel, startTime, maxCount, bucketType, weight)
if err != nil {
- return errors.New("error creating newquotaBucket: " + err.Error())
+ return errors.New("error creating quotaBucket: " + err.Error())
}
@@ -138,16 +144,15 @@
}
-func (qBucketResults *QuotaBucketResults) ToAPIResponse() (map[string]interface{}) {
+func (qBucketResults *QuotaBucketResults) ToAPIResponse() map[string]interface{} {
resultsMap := make(map[string]interface{})
- resultsMap["edgeOrgID"] = qBucketResults.ID
- resultsMap["id"] = qBucketResults.ID
+ resultsMap[reqEdgeOrgID] = qBucketResults.ID
+ resultsMap[reqID] = qBucketResults.ID
+ resultsMap[reqMaxCount] = qBucketResults.MaxCount
resultsMap["exceededTokens"] = qBucketResults.exceededTokens
- resultsMap["allowedTokens"] = qBucketResults.allowedTokens
- resultsMap["MaxCount"] = qBucketResults.MaxCount
+ resultsMap["currentTokens"] = qBucketResults.currentTokens
resultsMap["startedAt"] = qBucketResults.startedAt
resultsMap["expiresAt"] = qBucketResults.expiresAt
-
return resultsMap
-}
\ No newline at end of file
+}
diff --git a/quotaBucket/quotaBucket.go b/quotaBucket/quotaBucket.go
index c06247f..546ff10 100644
--- a/quotaBucket/quotaBucket.go
+++ b/quotaBucket/quotaBucket.go
@@ -2,7 +2,6 @@
import (
"errors"
- "fmt"
"github.com/30x/apidQuota/services"
"strings"
"time"
@@ -45,34 +44,45 @@
}
-type QuotaPeriod struct {
+type quotaPeriodData struct {
inputStartTime time.Time
startTime time.Time
endTime time.Time
}
+type QuotaPeriod struct {
+ quotaPeriodData
+}
+
func NewQuotaPeriod(inputStartTime int64, startTime int64, endTime int64) QuotaPeriod {
pInStartTime := time.Unix(inputStartTime, 0)
pStartTime := time.Unix(startTime, 0)
pEndTime := time.Unix(endTime, 0)
- period := &QuotaPeriod{inputStartTime: pInStartTime,
- startTime: pStartTime,
- endTime: pEndTime,
+ periodData := quotaPeriodData{
+ inputStartTime: pInStartTime,
+ startTime: pStartTime,
+ endTime: pEndTime,
}
- return *period
+
+ period := QuotaPeriod{
+ quotaPeriodData: periodData,
+ }
+
+ return period
+
}
func (qp *QuotaPeriod) GetPeriodInputStartTime() time.Time {
- return qp.inputStartTime
+ return qp.quotaPeriodData.inputStartTime
}
func (qp *QuotaPeriod) GetPeriodStartTime() time.Time {
- return qp.startTime
+ return qp.quotaPeriodData.startTime
}
func (qp *QuotaPeriod) GetPeriodEndTime() time.Time {
- return qp.endTime
+ return qp.quotaPeriodData.endTime
}
func (qp *QuotaPeriod) Validate() (bool, error) {
@@ -107,7 +117,7 @@
fromUNIXTime := time.Unix(startTime, 0)
- quotaBucketDataStruct := "aBucketData{
+ quotaBucketDataStruct := quotaBucketData{
EdgeOrgID: edgeOrgID,
ID: id,
Interval: interval,
@@ -121,7 +131,7 @@
}
quotaBucket := &QuotaBucket{
- quotaBucketData: *quotaBucketDataStruct,
+ quotaBucketData: quotaBucketDataStruct,
}
err := quotaBucket.setCurrentPeriod()
@@ -176,15 +186,29 @@
return q.quotaBucketData.StartTime
}
-func (q *QuotaBucket) GetQuotaType() string {
+func (q *QuotaBucket) GetQuotaDescriptorType() string {
return q.quotaBucketData.QuotaDescriptorType
}
-func (q *QuotaBucket) GetPreciseAtSecondsLevel() bool {
+func (q *QuotaBucket) GetIsPreciseAtSecondsLevel() bool {
return q.quotaBucketData.PreciseAtSecondsLevel
}
-//Calls setCurrentPeriod if QuotaDescriptorType is rollingWindow or period.endTime is before now.
+func (q *QuotaBucket) GetMaxCount() int64 {
+ return q.quotaBucketData.MaxCount
+}
+
+func (q *QuotaBucket) GetBucketType() string {
+ return q.quotaBucketData.BucketType
+}
+
+func (q *QuotaBucket) GetWeight() int64 {
+ return q.quotaBucketData.Weight
+}
+
+
+//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.QuotaDescriptorType == QuotaTypeRollingWindow {
qRWType := RollingWindowQuotaDescriptorType{}
@@ -209,7 +233,7 @@
return &q.quotaBucketData.Period, nil
}
-//setCurrentPeriod only for rolling window else just return the value of QuotaPeriod
+//setCurrentPeriod only for rolling window else just return the value of QuotaPeriod.
func (q *QuotaBucket) GetQuotaBucketPeriod() (*QuotaPeriod, error) {
if q.quotaBucketData.QuotaDescriptorType == QuotaTypeRollingWindow {
qRWType := RollingWindowQuotaDescriptorType{}
@@ -221,29 +245,23 @@
return &q.quotaBucketData.Period, nil
}
-func (q *QuotaBucket) GetMaxCount() int64 {
- return q.quotaBucketData.MaxCount
-}
-
-func (q *QuotaBucket) GetBucketType() string {
- return q.quotaBucketData.BucketType
-}
-
-func (q *QuotaBucket) GetBucketWeight() int64 {
- return q.quotaBucketData.Weight
-}
-
func (q *QuotaBucket) SetPeriod(startTime time.Time, endTime time.Time) {
- period := QuotaPeriod{inputStartTime: q.GetStartTime(),
- startTime: startTime,
- endTime: endTime,
+ periodData := quotaPeriodData{
+ inputStartTime: q.GetStartTime(),
+ startTime: startTime,
+ endTime: endTime,
}
+
+ period := QuotaPeriod{
+ quotaPeriodData: periodData,
+ }
+
q.quotaBucketData.Period = period
}
func (q *QuotaBucket) setCurrentPeriod() error {
- qDescriptorType, err := GetQuotaDescriptorTypeHandler(q.GetQuotaType())
+ qDescriptorType, err := GetQuotaDescriptorTypeHandler(q.GetQuotaDescriptorType())
if err != nil {
return err
}
@@ -253,7 +271,7 @@
func (period *QuotaPeriod) IsCurrentPeriod(qBucket *QuotaBucket) bool {
if qBucket != nil && qBucket.GetBucketType() != "" {
- if qBucket.GetQuotaType() == QuotaTypeRollingWindow {
+ if qBucket.GetQuotaDescriptorType() == QuotaTypeRollingWindow {
return (period.inputStartTime.Equal(time.Now().UTC()) || period.inputStartTime.Before(time.Now().UTC()))
}
@@ -271,12 +289,11 @@
maxCount := q.GetMaxCount()
exceededCount := false
allowedCount := int64(0)
- weight := q.GetBucketWeight()
+ weight := q.GetWeight()
period, err := q.GetPeriod()
if err != nil {
return nil, errors.New("error getting period: " + err.Error())
}
- fmt.Println("period set, start time: ", period.GetPeriodStartTime().String(), " end time: ", period.GetPeriodEndTime().String())
//first retrieve the count from counter service.
currentCount, err := services.IncrementAndGetCount(q.GetEdgeOrgID(), q.GetID(), 0, period.GetPeriodStartTime().Unix(), period.GetPeriodEndTime().Unix())
@@ -284,28 +301,18 @@
return nil, err
}
- fmt.Println("currentcount1: ", currentCount)
- fmt.Println("startTime get period : ", period.GetPeriodStartTime().String())
- fmt.Println("endTime get period : ", period.GetPeriodEndTime().String())
-
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())
- fmt.Println("currentcount2: ", currentCount)
if err != nil {
return nil, err
}
}
-
allowedCount = currentCount
} else {
-
if weight != 0 {
exceededCount = true
@@ -320,14 +327,13 @@
}
results := &QuotaBucketResults{
- EdgeOrgID : q.GetEdgeOrgID(),
- ID : q.GetID(),
- exceededTokens : exceededCount,
- allowedTokens : allowedCount,
- MaxCount : maxCount,
- startedAt : period.GetPeriodStartTime().Unix(),
- expiresAt : period.GetPeriodEndTime().Unix(),
-
+ EdgeOrgID: q.GetEdgeOrgID(),
+ ID: q.GetID(),
+ exceededTokens: exceededCount,
+ currentTokens: allowedCount,
+ MaxCount: maxCount,
+ startedAt: period.GetPeriodStartTime().Unix(),
+ expiresAt: period.GetPeriodEndTime().Unix(),
}
return results, nil
diff --git a/quotaBucket/quotaBucket_test.go b/quotaBucket/quotaBucket_test.go
index 3adfce6..aa1cebc 100644
--- a/quotaBucket/quotaBucket_test.go
+++ b/quotaBucket/quotaBucket_test.go
@@ -37,6 +37,20 @@
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>")
+ }
+
})
})
@@ -69,7 +83,7 @@
})
var _ = Describe("Test AcceptedQuotaBucketTypes", func() {
- It("testTimeUnit", func() {
+ It("testBucketTypes", func() {
if !IsValidQuotaBucketType("synchronous") {
Fail("Expected true: synchronous is a valid quotaBucket")
}
@@ -87,6 +101,7 @@
})
})
+//Tests for QuotaBucket
var _ = Describe("QuotaBucket", func() {
It("Create with NewQuotaBucket", func() {
edgeOrgID := "sampleOrg"
@@ -98,11 +113,13 @@
maxCount := int64(10)
weight := int64(1)
preciseAtSecondsLevel := true
+ //start time before now()
startTime := time.Now().UTC().AddDate(0, -1, 0).Unix()
quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, quotaType, preciseAtSecondsLevel, startTime, maxCount, bucketType, weight)
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())
@@ -112,16 +129,39 @@
Expect(edgeOrgID).To(Equal(quotaBucket.GetEdgeOrgID()))
Expect(id).To(Equal(quotaBucket.GetID()))
Expect(timeUnit).To(Equal(quotaBucket.GetTimeUnit()))
- Expect(quotaType).To(Equal(quotaBucket.GetQuotaType()))
+ Expect(quotaType).To(Equal(quotaBucket.GetQuotaDescriptorType()))
Expect(bucketType).To(Equal(quotaBucket.GetBucketType()))
Expect(interval).To(Equal(quotaBucket.GetInterval()))
Expect(maxCount).To(Equal(quotaBucket.GetMaxCount()))
- Expect(preciseAtSecondsLevel).To(Equal(quotaBucket.GetPreciseAtSecondsLevel()))
+ 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, bucketType, weight)
+ 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()))
+
})
@@ -141,7 +181,7 @@
quotaBucket, err := NewQuotaBucket(edgeOrgID, id, interval, timeUnit, quotaType, preciseAtSecondsLevel, startTime, maxCount, bucketType, weight)
Expect(err).NotTo(HaveOccurred())
- quotaBucket.SetPeriod(time.Now().UTC().UTC().AddDate(0, 1, 0), time.Now().AddDate(0, 0, -1))
+ 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>")
@@ -202,7 +242,7 @@
})
var _ = Describe("IsCurrentPeriod", func() {
- It("Test RollingType Window Valid TestCase", func() {
+ It("Test IsCurrentPeriod for RollingType Window - Valid TestCase", func() {
edgeOrgID := "sampleOrg"
id := "sampleID"
@@ -246,7 +286,7 @@
}
})
- It("Test RollingType Window InValid TestCase", func() {
+ It("Test IsCurrentPeriod for RollingType Window - InValid TestCase", func() {
edgeOrgID := "sampleOrg"
id := "sampleID"
@@ -284,7 +324,7 @@
}
})
- It("Test calendarType Window Valid TestCases", func() {
+ It("Test IsCurrentPeriod for calendarType Window - Valid TestCases", func() {
edgeOrgID := "sampleOrg"
id := "sampleID"
@@ -424,7 +464,7 @@
})
- It("Test Non RollingType Window InValid TestCase", func() {
+ It("Test IsCurrentPeriod for calendarType Window InValid TestCase", func() {
edgeOrgID := "sampleOrg"
id := "sampleID"
@@ -466,7 +506,7 @@
}
//start time in period after now
- quotaBucket.SetPeriod(time.Now().AddDate(0, 1, 0), time.Now().AddDate(1, 1, 0))
+ 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")
diff --git a/services/counterServiceHelper.go b/services/counterServiceHelper.go
index 13afa98..d0de935 100644
--- a/services/counterServiceHelper.go
+++ b/services/counterServiceHelper.go
@@ -18,7 +18,7 @@
key = "key"
delta = "delta"
startTime = "startTime"
- endTime = "endTime"
+ endTime = "endTime"
)
var client *http.Client = &http.Client{