Moved GetAccountActionPlansIndexHealth in engine

This commit is contained in:
Trial97
2021-06-16 18:23:06 +03:00
committed by Dan Christian Bogos
parent 5e7860eede
commit 1fc27c2d5b
5 changed files with 478 additions and 294 deletions

View File

@@ -21,10 +21,12 @@ package engine
import (
"fmt"
"strings"
"time"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/guardian"
"github.com/cgrates/cgrates/utils"
"github.com/cgrates/ltcache"
)
var (
@@ -818,3 +820,133 @@ func IsDynamicDPPath(path string) bool {
}
return false
}
type IndexHealthArgs struct {
IndexCacheLimit int
IndexCacheTTL time.Duration
IndexCacheStaticTTL bool
ObjectCacheLimit int
ObjectCacheTTL time.Duration
ObjectCacheStaticTTL bool
}
type IndexHealthReply struct {
MissingObjects []string // list of object that are referenced in indexes but are not found in the dataDB
MissingIndexes map[string][]string // list of missing indexes for each object (the map has the key as the objectID and a list of indexes)
BrokenReferences map[string][]string // list of broken references (the map has the key as the objectID and a list of indexes)
}
// add cache in args API
func GetAccountActionPlanIndexHealth(dm *DataManager, objLimit, indexLimit int, objTTL, indexTTL time.Duration, objStaticTTL, indexStaticTTL bool) (rply *IndexHealthReply, err error) {
// posible errors
missingAP := utils.StringSet{} // the index are present but the action plans are not //missing actionplans
brokenRef := map[string][]string{} // the actionPlans match the index but they are missing the account // broken reference
missingIndex := map[string][]string{} // the indexes are not present but the action plans points to that account // misingAccounts
// local cache
indexesCache := ltcache.NewCache(objLimit, objTTL, objStaticTTL, nil)
objectsCache := ltcache.NewCache(indexLimit, indexTTL, indexStaticTTL, nil)
getCachedIndex := func(acntID string) (apIDs []string, err error) {
if x, ok := indexesCache.Get(acntID); ok {
if x == nil {
return nil, utils.ErrNotFound
}
return x.([]string), nil
}
if apIDs, err = dm.GetAccountActionPlans(acntID, true, false, utils.NonTransactional); err != nil { // read from cache but do not write if not there
if err == utils.ErrNotFound {
indexesCache.Set(acntID, nil, nil)
}
return
}
indexesCache.Set(acntID, apIDs, nil)
return
}
getCachedObject := func(apID string) (obj *ActionPlan, err error) {
if x, ok := objectsCache.Get(apID); ok {
if x == nil {
return nil, utils.ErrNotFound
}
return x.(*ActionPlan), nil
}
if obj, err = dm.GetActionPlan(apID, true, false, utils.NonTransactional); err != nil { // read from cache but do not write if not there
if err == utils.ErrNotFound {
objectsCache.Set(apID, nil, nil)
}
return
}
objectsCache.Set(apID, obj, nil)
return
}
var acntIDs []string // start with the indexes and check the references
if acntIDs, err = dm.DataDB().GetKeysForPrefix(utils.AccountActionPlansPrefix); err != nil {
err = fmt.Errorf("error <%s> querying keys for accountActionPlans", err.Error())
return
}
for _, acntID := range acntIDs {
acntID = strings.TrimPrefix(acntID, utils.AccountActionPlansPrefix) //
var apIDs []string
if apIDs, err = getCachedIndex(acntID); err != nil { // read from cache but do not write if not there
err = fmt.Errorf("error <%s> querying the accountActionPlan: <%v>", err.Error(), acntID)
return
}
for _, apID := range apIDs {
var ap *ActionPlan
if ap, err = getCachedObject(apID); err != nil {
if err != utils.ErrNotFound {
err = fmt.Errorf("error <%s> querying the actionPlan: <%v>", err.Error(), apID)
return
}
err = nil
missingAP.Add(apID) // not found
continue
}
if !ap.AccountIDs.HasKey(acntID) { // the action plan exists but doesn't point towards the account we have index
brokenRef[apID] = append(brokenRef[apID], acntID)
}
}
}
var apIDs []string // we have all the indexes in cache now do a reverse check
if apIDs, err = dm.DataDB().GetKeysForPrefix(utils.ActionPlanPrefix); err != nil {
err = fmt.Errorf("error <%s> querying keys for actionPlans", err.Error())
return
}
for _, apID := range apIDs {
apID = strings.TrimPrefix(apID, utils.ActionPlanPrefix) //
var ap *ActionPlan
if ap, err = getCachedObject(apID); err != nil {
err = fmt.Errorf("error <%s> querying the actionPlan: <%v>", err.Error(), apID)
return
}
for acntID := range ap.AccountIDs {
var ids []string
if ids, err = getCachedIndex(acntID); err != nil { // read from cache but do not write if not there
if err != utils.ErrNotFound {
err = fmt.Errorf("error <%s> querying the accountActionPlan: <%v>", err.Error(), acntID)
return
}
err = nil
brokenRef[apID] = append(brokenRef[apID], acntID)
continue
}
if !utils.IsSliceMember(ids, apID) { // the index doesn't exits for this actionPlan
missingIndex[apID] = append(missingIndex[apID], acntID)
}
}
}
rply = &IndexHealthReply{
MissingObjects: missingAP.AsSlice(),
MissingIndexes: missingIndex,
BrokenReferences: brokenRef,
}
return
}

View File

@@ -0,0 +1,45 @@
/*
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
Copyright (C) ITsysCOM GmbH
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package engine
/*
func TestHealthAccountAction(t *testing.T) {
Cache.Clear(nil)
cfg := config.NewDefaultCGRConfig()
db := NewInternalDB(nil, nil, true)
dm := NewDataManager(db, cfg.CacheCfg(), nil)
if err := dm.SetAccountActionPlans("1001", []string{"AP1", "AP2"}, true); err != nil {
t.Fatal(err)
}
if err := dm.SetActionPlan("AP2", &ActionPlan{
Id: "AP2",
AccountIDs: utils.NewStringMap("1002"),
ActionTimings: []*ActionTiming{{}},
}, true, utils.NonTransactional); err != nil {
t.Fatal(err)
}
if rply, err := GetAccountActionPlanIndexHealth(dm, -1, -1, -1, -1, false, false); err != nil {
t.Fatal(err)
} else {
t.Error(utils.ToJSON(rply))
}
}
*/