diff --git a/apier/v1/resourcesv1_it_test.go b/apier/v1/resourcesv1_it_test.go index 6f4b95742..ca1cde0d0 100644 --- a/apier/v1/resourcesv1_it_test.go +++ b/apier/v1/resourcesv1_it_test.go @@ -196,7 +196,7 @@ func testV1RsTTL0(t *testing.T) { argsRU, &reply); err != nil { t.Error(err) } - // second allocation should be also allowed + // overwrite the first allocation argsRU = utils.ArgRSv1ResourceUsage{ CGREvent: utils.CGREvent{ Tenant: "cgrates.org", @@ -205,7 +205,7 @@ func testV1RsTTL0(t *testing.T) { "Destination": "3002"}, }, UsageID: "651a8db2-4f67-4cf8-b622-169e8a482e21", - Units: 1, + Units: 2, } if err := rlsV1Rpc.Call(utils.ResourceSv1AllocateResources, argsRU, &reply); err != nil { t.Error(err) @@ -219,13 +219,13 @@ func testV1RsTTL0(t *testing.T) { "Destination": "3002"}, }, UsageID: "651a8db2-4f67-4cf8-b622-169e8a482e22", - Units: 2, + Units: 4, } if err := rlsV1Rpc.Call(utils.ResourceSv1AllocateResources, argsRU, &reply); err == nil || err.Error() != utils.ErrResourceUnavailable.Error() { t.Error(err) } - // make sure no usage was recorded + // check the record var rs *engine.Resources args := &utils.ArgRSv1ResourceUsage{ CGREvent: utils.CGREvent{ @@ -235,6 +235,22 @@ func testV1RsTTL0(t *testing.T) { "Destination": "3002"}, }, } + expiryTime, err := utils.ParseTimeDetectLayout("0001-01-01T00:00:00Z", "") + if err != nil { + t.Error(err) + } + expectedResources := &engine.Resource{ + Tenant: "cgrates.org", + ID: "ResGroup3", + Usages: map[string]*engine.ResourceUsage{ + "651a8db2-4f67-4cf8-b622-169e8a482e21": &engine.ResourceUsage{ + Tenant: "cgrates.org", + ID: "651a8db2-4f67-4cf8-b622-169e8a482e21", + ExpiryTime: expiryTime, + Units: 2, + }, + }, + } if err := rlsV1Rpc.Call(utils.ResourceSv1GetResourcesForEvent, args, &rs); err != nil { t.Error(err) @@ -242,8 +258,8 @@ func testV1RsTTL0(t *testing.T) { t.Errorf("Resources: %+v", rs) } else { res := *rs - if len(res[0].Usages) != 0 || len(res[0].TTLIdx) != 0 { - t.Errorf("Resource should have no usage records in: %+v", res[0]) + if !reflect.DeepEqual(expectedResources, res[0]) { + t.Errorf("Expecting: %+v, received: %+v", expectedResources, res[0]) } } // release should not give out errors diff --git a/data/tariffplans/tutorial/Resources.csv b/data/tariffplans/tutorial/Resources.csv index 51fb93c84..0f47b20a6 100644 --- a/data/tariffplans/tutorial/Resources.csv +++ b/data/tariffplans/tutorial/Resources.csv @@ -1,4 +1,4 @@ #Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],TTL[4],Limit[5],AllocationMessage[6],Blocker[7],Stored[8],Weight[9],ThresholdIDs[10] cgrates.org,ResGroup1,FLTR_1,2014-07-29T15:00:00Z,1s,7,,false,false,20, cgrates.org,ResGroup2,FLTR_DST_FS,2014-07-29T15:00:00Z,3600s,8,SPECIAL_1002,false,true,10, -cgrates.org,ResGroup3,FLTR_RES_GR3,2014-07-29T15:00:00Z,0s,1,,true,false,20, +cgrates.org,ResGroup3,FLTR_RES_GR3,2014-07-29T15:00:00Z,*unlimited,3,,true,false,20, diff --git a/engine/resources.go b/engine/resources.go index f1a7c3e47..649524e7d 100755 --- a/engine/resources.go +++ b/engine/resources.go @@ -148,7 +148,7 @@ func (r *Resource) recordUsage(ru *ResourceUsage) (err error) { if _, hasID := r.Usages[ru.ID]; hasID { return fmt.Errorf("duplicate resource usage with id: %s", ru.TenantID()) } - if r.ttl != nil { + if r.ttl != nil && *r.ttl != -1 { if *r.ttl == 0 { return // no recording for ttl of 0 } @@ -206,7 +206,7 @@ func (rs Resources) recordUsage(ru *ResourceUsage) (err error) { } if err != nil { for _, r := range rs[:nonReservedIdx] { - r.clearUsage(ru.TenantID()) // best effort + r.clearUsage(ru.ID) // best effort } } return @@ -254,6 +254,9 @@ func (rs Resources) allocateResource(ru *ResourceUsage, dryRun bool) (alcMessage // Simulate resource usage for _, r := range rs { r.removeExpiredUnits() + if _, hasID := r.Usages[ru.ID]; hasID { // update + r.clearUsage(ru.ID) + } if r.rPrf.Limit >= r.totalUsage()+ru.Units { if alcMessage == "" { if r.rPrf.AllocationMessage != "" { diff --git a/engine/resources_test.go b/engine/resources_test.go index d41bb9271..9a0dcb573 100644 --- a/engine/resources_test.go +++ b/engine/resources_test.go @@ -336,7 +336,7 @@ func TestRSAllocateResource(t *testing.T) { if alcMessage, err := rs.allocateResource(ru1, true); err != nil { t.Error(err.Error()) } else { - if alcMessage != "RL2" { + if alcMessage != "ALLOC" { t.Errorf("Wrong allocation message: %v", alcMessage) } } @@ -350,8 +350,8 @@ func TestRSAllocateResource(t *testing.T) { } ru2.Units = 0 - if _, err := rs.allocateResource(ru2, false); err == nil { - t.Error("Duplicate ResourceUsage id should not be allowed") + if _, err := rs.allocateResource(ru2, false); err != nil { + t.Error(err) } } diff --git a/utils/coreutils.go b/utils/coreutils.go index fca396d6a..6101a353d 100644 --- a/utils/coreutils.go +++ b/utils/coreutils.go @@ -294,6 +294,9 @@ func ParseDurationWithNanosecs(durStr string) (d time.Duration, err error) { if durStr == "" { return } + if durStr == UNLIMITED { + durStr = "-1" + } if _, err = strconv.ParseFloat(durStr, 64); err == nil { // Seconds format considered durStr += "ns" }