mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Cache sorted resource IDs as slice
This commit is contained in:
committed by
Dan Christian Bogos
parent
5f66cd2220
commit
eab21e5d8d
@@ -367,15 +367,6 @@ func (rs Resources) unlock() {
|
||||
}
|
||||
}
|
||||
|
||||
// resIDsMp returns a map of resource IDs which is used for caching
|
||||
func (rs Resources) resIDsMp() (mp utils.StringSet) {
|
||||
mp = make(utils.StringSet)
|
||||
for _, r := range rs {
|
||||
mp.Add(r.ID)
|
||||
}
|
||||
return mp
|
||||
}
|
||||
|
||||
// recordUsage will record the usage in all the resource limits, failing back on errors
|
||||
func (rs Resources) recordUsage(ru *ResourceUsage) (err error) {
|
||||
var nonReservedIdx int // index of first resource not reserved
|
||||
@@ -640,16 +631,16 @@ func (rS *ResourceService) processThresholds(rs Resources, opts map[string]any)
|
||||
// matchingResourcesForEvent returns ordered list of matching resources which are active by the time of the call
|
||||
func (rS *ResourceService) matchingResourcesForEvent(tnt string, ev *utils.CGREvent,
|
||||
evUUID string, usageTTL *time.Duration) (rs Resources, err error) {
|
||||
var rIDs utils.StringSet
|
||||
evNm := utils.MapStorage{
|
||||
utils.MetaReq: ev.Event,
|
||||
utils.MetaOpts: ev.APIOpts,
|
||||
}
|
||||
var itemIDs []string
|
||||
if x, ok := Cache.Get(utils.CacheEventResources, evUUID); ok { // The ResourceIDs were cached as utils.StringSet{"resID":bool}
|
||||
if x == nil {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
rIDs = x.(utils.StringSet)
|
||||
itemIDs = x.([]string)
|
||||
defer func() { // make sure we uncache if we find errors
|
||||
if err != nil {
|
||||
if errCh := Cache.Remove(utils.CacheEventResources, evUUID,
|
||||
@@ -660,7 +651,7 @@ func (rS *ResourceService) matchingResourcesForEvent(tnt string, ev *utils.CGREv
|
||||
}()
|
||||
|
||||
} else { // select the resourceIDs out of dataDB
|
||||
rIDs, err = MatchingItemIDsForEvent(evNm,
|
||||
rIDs, err := MatchingItemIDsForEvent(evNm,
|
||||
rS.cgrcfg.ResourceSCfg().StringIndexedFields,
|
||||
rS.cgrcfg.ResourceSCfg().PrefixIndexedFields,
|
||||
rS.cgrcfg.ResourceSCfg().SuffixIndexedFields,
|
||||
@@ -675,13 +666,11 @@ func (rS *ResourceService) matchingResourcesForEvent(tnt string, ev *utils.CGREv
|
||||
return nil, errCh
|
||||
}
|
||||
}
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
// Lock items in sorted order to prevent AB-BA deadlock.
|
||||
itemIDs = slices.Sorted(maps.Keys(rIDs))
|
||||
}
|
||||
|
||||
// Lock items in sorted order to prevent AB-BA deadlock.
|
||||
itemIDs := slices.Sorted(maps.Keys(rIDs))
|
||||
|
||||
rs = make(Resources, 0, len(itemIDs))
|
||||
for _, id := range itemIDs {
|
||||
lkPrflID := guardian.Guardian.GuardIDs("",
|
||||
@@ -749,7 +738,7 @@ func (rS *ResourceService) matchingResourcesForEvent(tnt string, ev *utils.CGREv
|
||||
break
|
||||
}
|
||||
}
|
||||
if err = Cache.Set(utils.CacheEventResources, evUUID, rs.resIDsMp(), nil, true, ""); err != nil {
|
||||
if err = Cache.Set(utils.CacheEventResources, evUUID, itemIDs, nil, true, ""); err != nil {
|
||||
rs.unlock()
|
||||
}
|
||||
return
|
||||
|
||||
@@ -1856,81 +1856,6 @@ func TestResourceUsageTTLCase4(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceResIDsMp(t *testing.T) {
|
||||
resprf := []*ResourceProfile{
|
||||
{
|
||||
Tenant: config.CgrConfig().GeneralCfg().DefaultTenant,
|
||||
ID: "ResourceProfile1",
|
||||
FilterIDs: []string{"FLTR_RES_1"},
|
||||
ActivationInterval: &utils.ActivationInterval{
|
||||
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
|
||||
},
|
||||
UsageTTL: 10 * time.Second,
|
||||
Limit: 10.00,
|
||||
AllocationMessage: "AllocationMessage",
|
||||
Weight: 20.00,
|
||||
ThresholdIDs: []string{""},
|
||||
},
|
||||
{
|
||||
Tenant: config.CgrConfig().GeneralCfg().DefaultTenant,
|
||||
ID: "ResourceProfile2", // identifier of this resource
|
||||
FilterIDs: []string{"FLTR_RES_2"},
|
||||
ActivationInterval: &utils.ActivationInterval{
|
||||
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
|
||||
},
|
||||
UsageTTL: 10 * time.Second,
|
||||
Limit: 10.00,
|
||||
AllocationMessage: "AllocationMessage",
|
||||
Weight: 20.00,
|
||||
ThresholdIDs: []string{""},
|
||||
},
|
||||
{
|
||||
Tenant: config.CgrConfig().GeneralCfg().DefaultTenant,
|
||||
ID: "ResourceProfile3",
|
||||
FilterIDs: []string{"FLTR_RES_3"},
|
||||
ActivationInterval: &utils.ActivationInterval{
|
||||
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
|
||||
},
|
||||
UsageTTL: 10 * time.Second,
|
||||
Limit: 10.00,
|
||||
AllocationMessage: "AllocationMessage",
|
||||
Weight: 20.00,
|
||||
ThresholdIDs: []string{""},
|
||||
},
|
||||
}
|
||||
resourceTest := Resources{
|
||||
{
|
||||
Tenant: config.CgrConfig().GeneralCfg().DefaultTenant,
|
||||
ID: "ResourceProfile1",
|
||||
Usages: map[string]*ResourceUsage{},
|
||||
TTLIdx: []string{},
|
||||
rPrf: resprf[0],
|
||||
},
|
||||
{
|
||||
Tenant: config.CgrConfig().GeneralCfg().DefaultTenant,
|
||||
ID: "ResourceProfile2",
|
||||
Usages: map[string]*ResourceUsage{},
|
||||
TTLIdx: []string{},
|
||||
rPrf: resprf[1],
|
||||
},
|
||||
{
|
||||
Tenant: config.CgrConfig().GeneralCfg().DefaultTenant,
|
||||
ID: "ResourceProfile3",
|
||||
Usages: map[string]*ResourceUsage{},
|
||||
TTLIdx: []string{},
|
||||
rPrf: resprf[2],
|
||||
},
|
||||
}
|
||||
expected := utils.StringSet{
|
||||
"ResourceProfile1": struct{}{},
|
||||
"ResourceProfile2": struct{}{},
|
||||
"ResourceProfile3": struct{}{},
|
||||
}
|
||||
if rcv := resourceTest.resIDsMp(); !reflect.DeepEqual(rcv, expected) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceMatchWithIndexFalse(t *testing.T) {
|
||||
var dmRES *DataManager
|
||||
cfg := config.NewDefaultCGRConfig()
|
||||
@@ -2205,9 +2130,11 @@ func TestResourceCaching(t *testing.T) {
|
||||
t.Errorf("Expecting: nil, received: %s", err)
|
||||
}
|
||||
|
||||
res := &Resource{Tenant: resProf.Tenant,
|
||||
res := &Resource{
|
||||
Tenant: resProf.Tenant,
|
||||
ID: resProf.ID,
|
||||
Usages: make(map[string]*ResourceUsage)}
|
||||
Usages: make(map[string]*ResourceUsage),
|
||||
}
|
||||
|
||||
if err := Cache.Set(utils.CacheResources, "cgrates.org:ResourceProfileCached",
|
||||
res, nil, cacheCommit(utils.EmptyString), utils.EmptyString); err != nil {
|
||||
@@ -2215,7 +2142,7 @@ func TestResourceCaching(t *testing.T) {
|
||||
}
|
||||
|
||||
resources := Resources{res}
|
||||
if err := Cache.Set(utils.CacheEventResources, "TestResourceCaching", resources.resIDsMp(), nil, true, ""); err != nil {
|
||||
if err := Cache.Set(utils.CacheEventResources, "TestResourceCaching", []string{resProf.ID}, nil, true, ""); err != nil {
|
||||
t.Errorf("Expecting: nil, received: %s", err)
|
||||
}
|
||||
|
||||
@@ -2224,7 +2151,8 @@ func TestResourceCaching(t *testing.T) {
|
||||
ID: utils.UUIDSha1Prefix(),
|
||||
Event: map[string]any{
|
||||
"Account": "1001",
|
||||
"Destination": "3002"},
|
||||
"Destination": "3002",
|
||||
},
|
||||
}
|
||||
|
||||
mres, err := rS.matchingResourcesForEvent(ev.Tenant, ev,
|
||||
@@ -5653,7 +5581,7 @@ func TestResourceMatchingResourcesForEventNotFoundInDB(t *testing.T) {
|
||||
rS := NewResourceService(dmRES, cfg,
|
||||
&FilterS{dm: dmRES, cfg: cfg}, nil)
|
||||
|
||||
Cache.Set(utils.CacheEventResources, "TestResourceMatchingResourcesForEventNotFoundInDB", utils.StringSet{"Res2": {}}, nil, true, utils.NonTransactional)
|
||||
Cache.Set(utils.CacheEventResources, "TestResourceMatchingResourcesForEventNotFoundInDB", []string{"Res2"}, nil, true, utils.NonTransactional)
|
||||
_, err := rS.matchingResourcesForEvent("cgrates.org", new(utils.CGREvent),
|
||||
"TestResourceMatchingResourcesForEventNotFoundInDB", utils.DurationPointer(10*time.Second))
|
||||
if err != utils.ErrNotFound {
|
||||
@@ -5675,8 +5603,8 @@ func TestResourceMatchingResourcesForEventLocks(t *testing.T) {
|
||||
&FilterS{dm: dm, cfg: cfg}, nil)
|
||||
Cache.Clear(nil)
|
||||
prfs := make([]*ResourceProfile, 0)
|
||||
ids := utils.StringSet{}
|
||||
for i := 0; i < 10; i++ {
|
||||
ids := make([]string, 0, 11)
|
||||
for i := range 10 {
|
||||
rPrf := &ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: fmt.Sprintf("RES%d", i),
|
||||
@@ -5688,7 +5616,7 @@ func TestResourceMatchingResourcesForEventLocks(t *testing.T) {
|
||||
}
|
||||
dm.SetResourceProfile(rPrf, true)
|
||||
prfs = append(prfs, rPrf)
|
||||
ids.Add(rPrf.ID)
|
||||
ids = append(ids, rPrf.ID)
|
||||
}
|
||||
dm.RemoveResource("cgrates.org", "RES1")
|
||||
Cache.Set(utils.CacheEventResources, "TestResourceMatchingResourcesForEventLocks", ids, nil, true, utils.NonTransactional)
|
||||
@@ -5727,8 +5655,8 @@ func TestResourceMatchingResourcesForEventLocks2(t *testing.T) {
|
||||
&FilterS{dm: dm, cfg: cfg}, nil)
|
||||
Cache.Clear(nil)
|
||||
prfs := make([]*ResourceProfile, 0)
|
||||
ids := utils.StringSet{}
|
||||
for i := 0; i < 10; i++ {
|
||||
ids := make([]string, 0, 11)
|
||||
for i := range 10 {
|
||||
rPrf := &ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: fmt.Sprintf("RES%d", i),
|
||||
@@ -5740,7 +5668,7 @@ func TestResourceMatchingResourcesForEventLocks2(t *testing.T) {
|
||||
}
|
||||
dm.SetResourceProfile(rPrf, true)
|
||||
prfs = append(prfs, rPrf)
|
||||
ids.Add(rPrf.ID)
|
||||
ids = append(ids, rPrf.ID)
|
||||
}
|
||||
rPrf := &ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -5757,7 +5685,7 @@ func TestResourceMatchingResourcesForEventLocks2(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
prfs = append(prfs, rPrf)
|
||||
ids.Add(rPrf.ID)
|
||||
ids = append(ids, rPrf.ID)
|
||||
Cache.Set(utils.CacheEventResources, "TestResourceMatchingResourcesForEventLocks2", ids, nil, true, utils.NonTransactional)
|
||||
_, err := rS.matchingResourcesForEvent("cgrates.org", new(utils.CGREvent),
|
||||
"TestResourceMatchingResourcesForEventLocks2", utils.DurationPointer(10*time.Second))
|
||||
@@ -5793,8 +5721,8 @@ func TestResourceMatchingResourcesForEventLocksActivationInterval(t *testing.T)
|
||||
rS := NewResourceService(dm, cfg,
|
||||
&FilterS{dm: dm, cfg: cfg}, nil)
|
||||
|
||||
ids := utils.StringSet{}
|
||||
for i := 0; i < 10; i++ {
|
||||
ids := make([]string, 0, 10)
|
||||
for i := range 10 {
|
||||
rPrf := &ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: fmt.Sprintf("RES%d", i),
|
||||
@@ -5805,7 +5733,7 @@ func TestResourceMatchingResourcesForEventLocksActivationInterval(t *testing.T)
|
||||
ThresholdIDs: []string{utils.MetaNone},
|
||||
}
|
||||
dm.SetResourceProfile(rPrf, true)
|
||||
ids.Add(rPrf.ID)
|
||||
ids = append(ids, rPrf.ID)
|
||||
}
|
||||
rPrf := &ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -5820,7 +5748,7 @@ func TestResourceMatchingResourcesForEventLocksActivationInterval(t *testing.T)
|
||||
},
|
||||
}
|
||||
dm.SetResourceProfile(rPrf, true)
|
||||
ids.Add(rPrf.ID)
|
||||
ids = append(ids, rPrf.ID)
|
||||
Cache.Set(utils.CacheEventResources, "TestResourceMatchingResourcesForEventLocks2", ids, nil, true, utils.NonTransactional)
|
||||
mres, err := rS.matchingResourcesForEvent("cgrates.org", &utils.CGREvent{Time: utils.TimePointer(time.Now())},
|
||||
"TestResourceMatchingResourcesForEventLocks2", utils.DurationPointer(10*time.Second))
|
||||
@@ -5872,9 +5800,9 @@ func TestResourceMatchingResourcesForEventLocks3(t *testing.T) {
|
||||
rS := NewResourceService(dm, cfg,
|
||||
&FilterS{dm: dm, cfg: cfg}, nil)
|
||||
|
||||
ids := utils.StringSet{}
|
||||
for i := 0; i < 10; i++ {
|
||||
ids.Add(fmt.Sprintf("RES%d", i))
|
||||
ids := make([]string, 0, 11)
|
||||
for i := range 10 {
|
||||
ids = append(ids, fmt.Sprintf("RES%d", i))
|
||||
}
|
||||
Cache.Set(utils.CacheEventResources, "TestResourceMatchingResourcesForEventLocks3", ids, nil, true, utils.NonTransactional)
|
||||
_, err := rS.matchingResourcesForEvent("cgrates.org", new(utils.CGREvent),
|
||||
|
||||
Reference in New Issue
Block a user