Updated redis itnerface for rates

This commit is contained in:
porosnicuadrian
2022-02-01 17:11:02 +02:00
committed by Dan Christian Bogos
parent d4b65ef86a
commit e84b89186c
9 changed files with 139 additions and 11 deletions

View File

@@ -626,7 +626,7 @@ func (rplSv1 *ReplicatorSv1) SetActionProfile(ctx *context.Context, sp *engine.A
}
func (rplSv1 *ReplicatorSv1) RemoveRateProfile(ctx *context.Context, args *utils.TenantIDWithAPIOpts, reply *string) (err error) {
if err = rplSv1.dm.DataDB().RemoveRateProfileDrv(ctx, args.Tenant, args.ID); err != nil {
if err = rplSv1.dm.DataDB().RemoveRateProfileDrv(ctx, args.Tenant, args.ID, []string{}); err != nil {
return
}
if err = rplSv1.v1.CallCache(ctx, utils.IfaceAsString(args.APIOpts[utils.MetaCache]),

View File

@@ -2,6 +2,10 @@
// CGRateS Configuration file
// will be used in apis/attributes_it_test.go
"general": {
"node_id": "id", // identifier of this instance in the cluster, if empty it will be autogenerated
"log_level": 7,
},
"data_db": { // database used to store runtime data (eg: accounts, cdr stats)
"db_type": "redis", // data_db type: <redis|mongo>

View File

@@ -24,7 +24,7 @@ import (
)
type DataDBMock struct {
RemoveRateProfileDrvF func(ctx *context.Context, str1 string, str2 string) error
RemoveRateProfileDrvF func(ctx *context.Context, str1 string, str2 string, rateIDs []string) error
SetRateProfileDrvF func(*context.Context, *utils.RateProfile) error
GetRateProfileDrvF func(*context.Context, string, string) (*utils.RateProfile, error)
GetKeysForPrefixF func(*context.Context, string) ([]string, error)
@@ -382,9 +382,9 @@ func (dbM *DataDBMock) SetRateProfileDrv(ctx *context.Context, rt *utils.RatePro
return utils.ErrNotImplemented
}
func (dbM *DataDBMock) RemoveRateProfileDrv(ctx *context.Context, str1 string, str2 string) error {
func (dbM *DataDBMock) RemoveRateProfileDrv(ctx *context.Context, str1 string, str2 string, rateIDs []string) error {
if dbM.RemoveRateProfileDrvF != nil {
return dbM.RemoveRateProfileDrvF(ctx, str1, str2)
return dbM.RemoveRateProfileDrvF(ctx, str1, str2, []string{})
}
return utils.ErrNotImplemented
}

View File

@@ -2028,7 +2028,7 @@ func (dm *DataManager) RemoveRateProfile(ctx *context.Context, tenant, id string
if err != nil && err != utils.ErrNotFound {
return
}
if err = dm.DataDB().RemoveRateProfileDrv(ctx, tenant, id); err != nil {
if err = dm.DataDB().RemoveRateProfileDrv(ctx, tenant, id, []string{}); err != nil {
return
}
if oldRpp == nil {
@@ -2103,8 +2103,8 @@ func (dm *DataManager) RemoveRateProfileRates(ctx *context.Context, tenant, id s
delete(oldRpp.Rates, rateID)
}
}
if err = dm.DataDB().SetRateProfileDrv(ctx, oldRpp); err != nil {
return err
if err = dm.DataDB().RemoveRateProfileDrv(ctx, tenant, id, rateIDs); err != nil {
return
}
if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaRateProfiles]; itm.Replicate {

View File

@@ -95,7 +95,7 @@ type DataDB interface {
RemoveDispatcherHostDrv(*context.Context, string, string) error
GetRateProfileDrv(*context.Context, string, string) (*utils.RateProfile, error)
SetRateProfileDrv(*context.Context, *utils.RateProfile) error
RemoveRateProfileDrv(*context.Context, string, string) error
RemoveRateProfileDrv(*context.Context, string, string, []string) error
GetActionProfileDrv(*context.Context, string, string) (*ActionProfile, error)
SetActionProfileDrv(*context.Context, *ActionProfile) error
RemoveActionProfileDrv(*context.Context, string, string) error

View File

@@ -485,7 +485,7 @@ func (iDB *InternalDB) SetRateProfileDrv(_ *context.Context, rpp *utils.RateProf
return
}
func (iDB *InternalDB) RemoveRateProfileDrv(_ *context.Context, tenant, id string) (err error) {
func (iDB *InternalDB) RemoveRateProfileDrv(_ *context.Context, tenant, id string, rateIDs []string) (err error) {
iDB.db.Remove(utils.CacheRateProfiles, utils.ConcatenatedKey(tenant, id),
true, utils.NonTransactional)
return

View File

@@ -1228,7 +1228,7 @@ func (ms *MongoStorage) SetRateProfileDrv(ctx *context.Context, rpp *utils.RateP
})
}
func (ms *MongoStorage) RemoveRateProfileDrv(ctx *context.Context, tenant, id string) (err error) {
func (ms *MongoStorage) RemoveRateProfileDrv(ctx *context.Context, tenant, id string, rateIDs []string) (err error) {
return ms.query(ctx, func(sctx mongo.SessionContext) (err error) {
dr, err := ms.getCol(ColRpp).DeleteOne(sctx, bson.M{"tenant": tenant, "id": id})
if dr.DeletedCount == 0 {

View File

@@ -64,6 +64,7 @@ const (
redisHGET = "HGET"
redisRENAME = "RENAME"
redisHMSET = "HMSET"
redisHSET = "HSET"
redisLoadError = "Redis is loading the dataset in memory"
RedisLimit = 524287 // https://github.com/StackExchange/StackExchange.Redis/issues/201#issuecomment-98639005
@@ -727,6 +728,7 @@ func (rs *RedisStorage) RemoveLoadIDsDrv() (err error) {
return rs.Cmd(nil, redisDEL, utils.LoadIDs)
}
/*
func (rs *RedisStorage) GetRateProfileDrv(ctx *context.Context, tenant, id string) (rpp *utils.RateProfile, err error) {
var values []byte
if err = rs.Cmd(&values, redisGET, utils.RateProfilePrefix+utils.ConcatenatedKey(tenant, id)); err != nil {
@@ -739,6 +741,7 @@ func (rs *RedisStorage) GetRateProfileDrv(ctx *context.Context, tenant, id strin
return
}
func (rs *RedisStorage) SetRateProfileDrv(ctx *context.Context, rpp *utils.RateProfile) (err error) {
var result []byte
if result, err = rs.ms.Marshal(rpp); err != nil {
@@ -746,8 +749,40 @@ func (rs *RedisStorage) SetRateProfileDrv(ctx *context.Context, rpp *utils.RateP
}
return rs.Cmd(nil, redisSET, utils.RateProfilePrefix+utils.ConcatenatedKey(rpp.Tenant, rpp.ID), string(result))
}
*/
func (rs *RedisStorage) RemoveRateProfileDrv(ctx *context.Context, tenant, id string) (err error) {
func (rs *RedisStorage) SetRateProfileDrv(ctx *context.Context, rpp *utils.RateProfile) (err error) {
rpMap, err := rpp.AsDataDBMap()
if err != nil {
return
}
for key, val := range rpMap {
if err = rs.FlatCmd(nil, redisHSET, utils.RateProfilePrefix+utils.ConcatenatedKey(rpp.Tenant, rpp.ID), key, val); err != nil {
break
}
}
return
}
func (rs *RedisStorage) GetRateProfileDrv(ctx *context.Context, tenant, id string) (rpp *utils.RateProfile, err error) {
mapRP := make(map[string]interface{})
if err = rs.Cmd(&mapRP, redisHGETALL, utils.RateProfilePrefix+utils.ConcatenatedKey(tenant, id)); err != nil {
return
} else if len(mapRP) == 0 {
err = utils.ErrNotFound
return
}
rpp, err = utils.NewRateProfileFromMapDataDBMap(tenant, id, mapRP)
return
}
func (rs *RedisStorage) RemoveRateProfileDrv(ctx *context.Context, tenant, id string, rateIDs []string) (err error) {
if len(rateIDs) != 0 {
tntID := utils.ConcatenatedKey(tenant, id)
for _, rateID := range rateIDs {
return rs.Cmd(nil, redisHDEL, utils.RateProfilePrefix+tntID, utils.Rates+utils.InInFieldSep+rateID)
}
}
return rs.Cmd(nil, redisDEL, utils.RateProfilePrefix+utils.ConcatenatedKey(tenant, id))
}

View File

@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package utils
import (
"encoding/json"
"fmt"
"sort"
"strconv"
@@ -909,3 +910,91 @@ func (iR *IntervalRate) FieldAsInterface(fldPath []string) (_ interface{}, err e
return iR.Increment, nil
}
}
// AsDataDBMap is used to is a convert method in order to properly set trough a hasmap in redis server our rate profile
func (rp *RateProfile) AsDataDBMap() (mp map[string]interface{}, err error) {
mp = map[string]interface{}{
MaxCostStrategy: rp.MaxCostStrategy,
}
if len(rp.FilterIDs) != 0 {
var fltrs string
for idx, fltr := range rp.FilterIDs {
fltrs += fltr
if idx != len(rp.FilterIDs)-1 {
fltrs += InfieldSep
}
}
mp[FilterIDs] = fltrs
}
if rp.Weights != nil {
mp[Weights] = rp.Weights.String(InfieldSep, ANDSep)
}
if rp.MinCost != nil {
minCostBts, err := rp.MinCost.MarshalBinary()
if err != nil {
return nil, err
}
mp[MinCost] = minCostBts
}
if rp.MaxCost != nil {
maxCostBts, err := rp.MaxCost.MarshalBinary()
if err != nil {
return nil, err
}
mp[MaxCost] = maxCostBts
}
for rateID, rt := range rp.Rates {
var result []byte
if result, err = json.Marshal(rt); err != nil {
return nil, err
}
fldKey := ConcatenatedKey(Rates, rateID)
mp[fldKey] = result
}
return mp, nil
}
// NewRateProfileFromMapDataDBMap will convert a RateProfile map into a RatePRofile struct. This is used when we get the map from redis database
func NewRateProfileFromMapDataDBMap(tnt, id string, mapRP map[string]interface{}) (rp *RateProfile, err error) {
rp = &RateProfile{
ID: id,
Tenant: tnt,
MaxCostStrategy: IfaceAsString(mapRP[MaxCostStrategy]),
Rates: make(map[string]*Rate),
}
if fltrsIDs, has := mapRP[FilterIDs]; has {
fltrs := strings.Split(IfaceAsString(fltrsIDs), InfieldSep)
rp.FilterIDs = make([]string, len(fltrs))
for idx, fltr := range fltrs {
rp.FilterIDs[idx] = fltr
}
}
if weights, has := mapRP[Weights]; has {
rp.Weights, err = NewDynamicWeightsFromString(IfaceAsString(weights), InfieldSep, ANDSep)
if err != nil {
return nil, err
}
}
if minCost, has := mapRP[MinCost]; has {
rp.MinCost, err = NewDecimalFromString(IfaceAsString(minCost))
if err != nil {
return nil, err
}
}
if maxCost, has := mapRP[MaxCost]; has {
rp.MaxCost, err = NewDecimalFromString(IfaceAsString(maxCost))
if err != nil {
return nil, err
}
}
for keyID, rateStr := range mapRP {
if strings.HasPrefix(keyID, Rates+ConcatenatedKeySep) {
var rate *Rate
if err := json.Unmarshal([]byte(IfaceAsString(rateStr)), &rate); err != nil {
return nil, err
}
rp.Rates[strings.TrimPrefix(keyID, Rates+ConcatenatedKeySep)] = rate
}
}
return rp, err
}