From b5dbb31163e131eebdabcbb02397babd75bf88f8 Mon Sep 17 00:00:00 2001 From: ionutboangiu Date: Mon, 3 Jul 2023 12:17:59 -0400 Subject: [PATCH] Clean up and refactor after mongo update - Converting directly from a D to an M is deprecated. We are now decoding directly in a M. - Used errors.As and errors.Is for proper error comparison and assertion - Streamlined function parameters and removed redundancies - Revised sloppy reassignments and added missing error checks - Shortened and reorganized function structure for improved readability --- engine/storage_mongo_datadb.go | 1537 +++++++++++++++----------------- engine/storage_mongo_stordb.go | 171 ++-- 2 files changed, 822 insertions(+), 886 deletions(-) diff --git a/engine/storage_mongo_datadb.go b/engine/storage_mongo_datadb.go index 64c4fd843..985e179aa 100644 --- a/engine/storage_mongo_datadb.go +++ b/engine/storage_mongo_datadb.go @@ -22,6 +22,7 @@ import ( "bytes" "compress/zlib" "context" + "errors" "fmt" "io" "strings" @@ -38,7 +39,7 @@ import ( "go.mongodb.org/mongo-driver/mongo/options" ) -// Mongo collections names +// Collection names in MongoDB. const ( ColDst = "destinations" ColRds = "reverse_destinations" @@ -102,7 +103,8 @@ var ( // NewMongoStorage initializes a new MongoDB storage instance with provided connection parameters and settings. // Returns an error if the setup fails. func NewMongoStorage(host, port, db, user, pass, mrshlerStr string, cdrsIndexes []string, - isDataDB bool) (*MongoStorage, error) { + isDataDB bool, +) (*MongoStorage, error) { url, err := buildURL("mongodb", host, port, db, user, pass) if err != nil { return nil, err @@ -139,7 +141,7 @@ func NewMongoStorage(host, port, db, user, pass, mrshlerStr string, cdrsIndexes mongoStorage.db = strings.Split(db, "?")[0] } - if err = mongoStorage.query(func(sctx mongo.SessionContext) error { + err = mongoStorage.query(func(sctx mongo.SessionContext) error { // Create indexes only if the database is empty or only the version table is present. cols, err := mongoStorage.client.Database(mongoStorage.db). ListCollectionNames(sctx, bson.D{}) @@ -157,13 +159,14 @@ func NewMongoStorage(host, port, db, user, pass, mrshlerStr string, cdrsIndexes return mongoStorage.EnsureIndexes() } return nil - }); err != nil { + }) + if err != nil { return nil, err } return mongoStorage, nil } -// MongoStorage struct for new mongo driver +// MongoStorage represents a storage interface for the new MongoDB driver. type MongoStorage struct { client *mongo.Client ctx context.Context @@ -176,7 +179,7 @@ type MongoStorage struct { isDataDB bool } -func (ms *MongoStorage) query(argfunc func(ctx mongo.SessionContext) error) (err error) { +func (ms *MongoStorage) query(argfunc func(ctx mongo.SessionContext) error) error { ms.ctxTTLMutex.RLock() ctxSession, ctxSessionCancel := context.WithTimeout(ms.ctx, ms.ctxTTL) ms.ctxTTLMutex.RUnlock() @@ -184,12 +187,12 @@ func (ms *MongoStorage) query(argfunc func(ctx mongo.SessionContext) error) (err return ms.client.UseSession(ctxSession, argfunc) } -// IsDataDB returns if the storeage is used for DataDb +// IsDataDB returns whether the storage is used for DataDB. func (ms *MongoStorage) IsDataDB() bool { return ms.isDataDB } -// SetTTL set the context TTL used for queries (is thread safe) +// SetTTL sets the context TTL used for queries (Thread-safe). func (ms *MongoStorage) SetTTL(ttl time.Duration) { ms.ctxTTLMutex.Lock() ms.ctxTTL = ttl @@ -199,14 +202,14 @@ func (ms *MongoStorage) SetTTL(ttl time.Duration) { func (ms *MongoStorage) enusureIndex(colName string, uniq bool, keys ...string) error { return ms.query(func(sctx mongo.SessionContext) error { col := ms.getCol(colName) - io := options.Index().SetUnique(uniq) + indexOptions := options.Index().SetUnique(uniq) doc := make(bson.D, 0) for _, k := range keys { doc = append(doc, bson.E{Key: k, Value: 1}) } _, err := col.Indexes().CreateOne(sctx, mongo.IndexModel{ Keys: doc, - Options: io, + Options: indexOptions, }) return err }) @@ -224,38 +227,36 @@ func (ms *MongoStorage) getCol(col string) *mongo.Collection { return ms.client.Database(ms.db).Collection(col) } -// GetContext returns the context used for the current DB +// GetContext returns the context used for the current database. func (ms *MongoStorage) GetContext() context.Context { return ms.ctx } func isNotFound(err error) bool { - de, ok := err.(mongo.CommandError) - if !ok { // if still can't converted to the mongo.CommandError check if error do not contains message - return strings.Contains(err.Error(), "ns not found") + var de *mongo.CommandError + + if errors.As(err, &de) { + return de.Code == 26 || de.Message == "ns not found" } - return de.Code == 26 || de.Message == "ns not found" + + // If the error cannot be converted to mongo.CommandError + // check if the error message contains "ns not found" + return strings.Contains(err.Error(), "ns not found") } -func (ms *MongoStorage) ensureIndexesForCol(col string) (err error) { // exported for migrator - if err = ms.dropAllIndexesForCol(col); err != nil && !isNotFound(err) { // make sure you do not have indexes - return +func (ms *MongoStorage) ensureIndexesForCol(col string) error { // exported for migrator + err := ms.dropAllIndexesForCol(col) + if err != nil && !isNotFound(err) { // make sure you do not have indexes + return err } - err = nil switch col { case ColAct, ColApl, ColAAp, ColAtr, ColRpl, ColDst, ColRds, ColLht, ColRFI: - if err = ms.enusureIndex(col, true, "key"); err != nil { - return - } + err = ms.enusureIndex(col, true, "key") case ColRsP, ColRes, ColSqs, ColSqp, ColTps, ColThs, ColSpp, ColAttr, ColFlt, ColCpp, ColDpp, ColDph: - if err = ms.enusureIndex(col, true, "tenant", "id"); err != nil { - return - } + err = ms.enusureIndex(col, true, "tenant", "id") case ColRpf, ColShg, ColAcc: - if err = ms.enusureIndex(col, true, "id"); err != nil { - return - } - //StorDB + err = ms.enusureIndex(col, true, "id") + // StorDB case utils.TBLTPTimings, utils.TBLTPDestinations, utils.TBLTPDestinationRates, utils.TBLTPRatingPlans, utils.TBLTPSharedGroups, utils.TBLTPActions, @@ -263,53 +264,49 @@ func (ms *MongoStorage) ensureIndexesForCol(col string) (err error) { // exporte utils.TBLTPStats, utils.TBLTPResources, utils.TBLTPDispatchers, utils.TBLTPDispatcherHosts, utils.TBLTPChargers, utils.TBLTPSuppliers, utils.TBLTPThresholds: - if err = ms.enusureIndex(col, true, "tpid", "id"); err != nil { - return - } + err = ms.enusureIndex(col, true, "tpid", "id") case utils.TBLTPRateProfiles: - if err = ms.enusureIndex(col, true, "tpid", "tenant", - "category", "subject", "loadid"); err != nil { - return + err = ms.enusureIndex(col, true, "tpid", "tenant", + "category", "subject", "loadid") + case utils.SessionCostsTBL: + err = ms.enusureIndex(col, true, CGRIDLow, RunIDLow) + if err == nil { + err = ms.enusureIndex(col, false, OriginHostLow, OriginIDLow) + } + if err == nil { + err = ms.enusureIndex(col, false, RunIDLow, OriginIDLow) } case utils.CDRsTBL: - if err = ms.enusureIndex(col, true, CGRIDLow, RunIDLow, - OriginIDLow); err != nil { - return - } - for _, idxKey := range ms.cdrsIndexes { - if err = ms.enusureIndex(col, false, idxKey); err != nil { - return + err = ms.enusureIndex(col, true, CGRIDLow, RunIDLow, + OriginIDLow) + if err == nil { + for _, idxKey := range ms.cdrsIndexes { + err = ms.enusureIndex(col, false, idxKey) + if err != nil { + break + } } } - case utils.SessionCostsTBL: - if err = ms.enusureIndex(col, true, CGRIDLow, - RunIDLow); err != nil { - return - } - if err = ms.enusureIndex(col, false, OriginHostLow, - OriginIDLow); err != nil { - return - } - if err = ms.enusureIndex(col, false, RunIDLow, - OriginIDLow); err != nil { - return - } } - return + return err } -// EnsureIndexes creates db indexes +// EnsureIndexes creates database indexes for the specified collections. func (ms *MongoStorage) EnsureIndexes(cols ...string) error { if len(cols) == 0 { if ms.isDataDB { - cols = []string{ColAct, ColApl, ColAAp, ColAtr, ColRpl, ColDst, ColRds, ColLht, ColRFI, + cols = []string{ + ColAct, ColApl, ColAAp, ColAtr, ColRpl, ColDst, ColRds, ColLht, ColRFI, ColRsP, ColRes, ColSqs, ColSqp, ColTps, ColThs, ColSpp, ColAttr, ColFlt, ColCpp, - ColDpp, ColRpf, ColShg, ColAcc} + ColDpp, ColRpf, ColShg, ColAcc, + } } else { - cols = []string{utils.TBLTPTimings, utils.TBLTPDestinations, utils.TBLTPDestinationRates, + cols = []string{ + utils.TBLTPTimings, utils.TBLTPDestinations, utils.TBLTPDestinationRates, utils.TBLTPRatingPlans, utils.TBLTPSharedGroups, utils.TBLTPActions, utils.TBLTPActionPlans, utils.TBLTPActionTriggers, utils.TBLTPStats, utils.TBLTPResources, utils.TBLTPRateProfiles, - utils.CDRsTBL, utils.SessionCostsTBL} + utils.CDRsTBL, utils.SessionCostsTBL, + } } } for _, col := range cols { @@ -320,63 +317,36 @@ func (ms *MongoStorage) EnsureIndexes(cols ...string) error { return nil } -func (ms *MongoStorage) getColNameForPrefix(prefix string) (string, bool) { - res, ok := map[string]string{ - utils.DESTINATION_PREFIX: ColDst, - utils.REVERSE_DESTINATION_PREFIX: ColRds, - utils.ACTION_PREFIX: ColAct, - utils.ACTION_PLAN_PREFIX: ColApl, - utils.AccountActionPlansPrefix: ColAAp, - utils.TASKS_KEY: ColTsk, - utils.ACTION_TRIGGER_PREFIX: ColAtr, - utils.RATING_PLAN_PREFIX: ColRpl, - utils.RATING_PROFILE_PREFIX: ColRpf, - utils.ACCOUNT_PREFIX: ColAcc, - utils.SHARED_GROUP_PREFIX: ColShg, - utils.LOADINST_KEY: ColLht, - utils.VERSION_PREFIX: ColVer, - utils.TimingsPrefix: ColTmg, - utils.ResourcesPrefix: ColRes, - utils.ResourceProfilesPrefix: ColRsP, - utils.ThresholdProfilePrefix: ColTps, - utils.StatQueueProfilePrefix: ColSqp, - utils.ThresholdPrefix: ColThs, - utils.FilterPrefix: ColFlt, - utils.SupplierProfilePrefix: ColSpp, - utils.AttributeProfilePrefix: ColAttr, - }[prefix] - return res, ok -} - -// Close disconects the client +// Close disconnects the MongoDB client. func (ms *MongoStorage) Close() { if err := ms.client.Disconnect(ms.ctx); err != nil { utils.Logger.Err(fmt.Sprintf(" Error on disconect:%s", err)) } } -// Flush drops the datatable -func (ms *MongoStorage) Flush(ignore string) (err error) { +// Flush drops the datatable and recreates the indexes. +func (ms *MongoStorage) Flush(_ string) (err error) { return ms.query(func(sctx mongo.SessionContext) error { - if err = ms.client.Database(ms.db).Drop(sctx); err != nil { + err := ms.client.Database(ms.db).Drop(sctx) + if err != nil { return err } - return ms.EnsureIndexes() // recreate the indexes + return ms.EnsureIndexes() }) } -// DB returnes a database object +// DB returns the database object associated with the MongoDB client. func (ms *MongoStorage) DB() *mongo.Database { return ms.client.Database(ms.db) } -// SelectDatabase selects the database -func (ms *MongoStorage) SelectDatabase(dbName string) (err error) { +// SelectDatabase selects the specified database. +func (ms *MongoStorage) SelectDatabase(dbName string) error { ms.db = dbName - return + return nil } -func (ms *MongoStorage) RemoveKeysForPrefix(prefix string) (err error) { +func (ms *MongoStorage) RemoveKeysForPrefix(prefix string) error { var colName string switch prefix { case utils.DestinationPrefix: @@ -433,9 +403,10 @@ func (ms *MongoStorage) RemoveKeysForPrefix(prefix string) (err error) { }) } -// IsDBEmpty implementation -func (ms *MongoStorage) IsDBEmpty() (resp bool, err error) { - err = ms.query(func(sctx mongo.SessionContext) error { +// IsDBEmpty checks if the database is empty by verifying if each collection is empty. +func (ms *MongoStorage) IsDBEmpty() (bool, error) { + var isEmpty bool + err := ms.query(func(sctx mongo.SessionContext) error { cols, err := ms.DB().ListCollectionNames(sctx, bson.D{}) if err != nil { return err @@ -444,22 +415,22 @@ func (ms *MongoStorage) IsDBEmpty() (resp bool, err error) { if col == utils.CDRsTBL { // ignore cdrs collection continue } - var count int64 - if count, err = ms.getCol(col).CountDocuments(sctx, bson.D{}, options.Count().SetLimit(1)); err != nil { // check if collection is empty so limit the count to 1 + count, err := ms.getCol(col).CountDocuments(sctx, bson.D{}, options.Count().SetLimit(1)) // limiting the count to 1 since we are only checking if the collection is empty + if err != nil { return err } if count != 0 { return nil } } - resp = true + isEmpty = true return nil }) - return resp, err + return isEmpty, err } -func (ms *MongoStorage) getAllKeysMatchingField(sctx mongo.SessionContext, col, prefix, subject, field string) (result []string, err error) { - fieldResult := bson.D{} +func (ms *MongoStorage) getAllKeysMatchingField(sctx mongo.SessionContext, col, prefix, subject, field string) (keys []string, err error) { + fieldResult := bson.M{} iter, err := ms.getCol(col).Find(sctx, bson.M{ field: primitive.Regex{ @@ -480,13 +451,13 @@ func (ms *MongoStorage) getAllKeysMatchingField(sctx mongo.SessionContext, col, if err != nil { return } - result = append(result, prefix+fieldResult.Map()[field].(string)) + keys = append(keys, prefix+fieldResult[field].(string)) } - return result, iter.Close(sctx) + return keys, iter.Close(sctx) } -func (ms *MongoStorage) getAllKeysMatchingTenantID(sctx mongo.SessionContext, col, prefix, subject string, tntID *utils.TenantID) (result []string, err error) { - idResult := struct{ Tenant, Id string }{} +func (ms *MongoStorage) getAllKeysMatchingTenantID(sctx mongo.SessionContext, col, prefix, subject string, tntID *utils.TenantID) (keys []string, err error) { + idResult := struct{ Tenant, ID string }{} elem := bson.M{} if tntID.Tenant != "" { elem["tenant"] = tntID.Tenant @@ -507,21 +478,21 @@ func (ms *MongoStorage) getAllKeysMatchingTenantID(sctx mongo.SessionContext, co if err != nil { return } - result = append(result, prefix+utils.ConcatenatedKey(idResult.Tenant, idResult.Id)) + keys = append(keys, prefix+utils.ConcatenatedKey(idResult.Tenant, idResult.ID)) } - return result, iter.Close(sctx) + return keys, iter.Close(sctx) } -func (ms *MongoStorage) getAllIndexKeys(sctx mongo.SessionContext, col, prefix, field string) (result []string, err error) { - fieldResult := bson.D{} - iter, err := ms.getCol(col).Find(sctx, +func (ms *MongoStorage) getAllIndexKeys(sctx mongo.SessionContext, prefix string) (keys []string, err error) { + fieldResult := bson.M{} + iter, err := ms.getCol(ColRFI).Find(sctx, bson.M{ - field: primitive.Regex{ + "key": primitive.Regex{ Pattern: "^" + prefix, }, }, options.Find().SetProjection( - bson.M{field: 1}, + bson.M{"key": 1}, ), ) if err != nil { @@ -532,93 +503,94 @@ func (ms *MongoStorage) getAllIndexKeys(sctx mongo.SessionContext, col, prefix, if err != nil { return } - result = append(result, fieldResult.Map()[field].(string)) + keys = append(keys, fieldResult["key"].(string)) } - return result, iter.Close(sctx) + return keys, iter.Close(sctx) } -// GetKeysForPrefix implementation -func (ms *MongoStorage) GetKeysForPrefix(prefix string) (result []string, err error) { +// GetKeysForPrefix retrieves keys matching the specified prefix across different categories. +func (ms *MongoStorage) GetKeysForPrefix(prefix string) ([]string, error) { var category, subject string keyLen := len(utils.DESTINATION_PREFIX) if len(prefix) < keyLen { return nil, fmt.Errorf("unsupported prefix in GetKeysForPrefix: %s", prefix) } + var keys []string category = prefix[:keyLen] // prefix length tntID := utils.NewTenantID(prefix[keyLen:]) subject = "^" + prefix[keyLen:] // old way, no tenant support - err = ms.query(func(sctx mongo.SessionContext) (err error) { + err := ms.query(func(sctx mongo.SessionContext) (err error) { switch category { case utils.DESTINATION_PREFIX: - result, err = ms.getAllKeysMatchingField(sctx, ColDst, utils.DESTINATION_PREFIX, subject, "key") + keys, err = ms.getAllKeysMatchingField(sctx, ColDst, utils.DESTINATION_PREFIX, subject, "key") case utils.REVERSE_DESTINATION_PREFIX: - result, err = ms.getAllKeysMatchingField(sctx, ColRds, utils.REVERSE_DESTINATION_PREFIX, subject, "key") + keys, err = ms.getAllKeysMatchingField(sctx, ColRds, utils.REVERSE_DESTINATION_PREFIX, subject, "key") case utils.RATING_PLAN_PREFIX: - result, err = ms.getAllKeysMatchingField(sctx, ColRpl, utils.RATING_PLAN_PREFIX, subject, "key") + keys, err = ms.getAllKeysMatchingField(sctx, ColRpl, utils.RATING_PLAN_PREFIX, subject, "key") case utils.RATING_PROFILE_PREFIX: if strings.HasPrefix(prefix[keyLen:], utils.META_OUT) { // Rewrite the id as it starts with '*' (from "*out"). subject = "^\\" + prefix[keyLen:] } - result, err = ms.getAllKeysMatchingField(sctx, ColRpf, utils.RATING_PROFILE_PREFIX, subject, "id") + keys, err = ms.getAllKeysMatchingField(sctx, ColRpf, utils.RATING_PROFILE_PREFIX, subject, "id") case utils.ACTION_PREFIX: - result, err = ms.getAllKeysMatchingField(sctx, ColAct, utils.ACTION_PREFIX, subject, "key") + keys, err = ms.getAllKeysMatchingField(sctx, ColAct, utils.ACTION_PREFIX, subject, "key") case utils.ACTION_PLAN_PREFIX: - result, err = ms.getAllKeysMatchingField(sctx, ColApl, utils.ACTION_PLAN_PREFIX, subject, "key") + keys, err = ms.getAllKeysMatchingField(sctx, ColApl, utils.ACTION_PLAN_PREFIX, subject, "key") case utils.ACTION_TRIGGER_PREFIX: - result, err = ms.getAllKeysMatchingField(sctx, ColAtr, utils.ACTION_TRIGGER_PREFIX, subject, "key") + keys, err = ms.getAllKeysMatchingField(sctx, ColAtr, utils.ACTION_TRIGGER_PREFIX, subject, "key") case utils.SHARED_GROUP_PREFIX: - result, err = ms.getAllKeysMatchingField(sctx, ColShg, utils.SHARED_GROUP_PREFIX, subject, "id") + keys, err = ms.getAllKeysMatchingField(sctx, ColShg, utils.SHARED_GROUP_PREFIX, subject, "id") case utils.ACCOUNT_PREFIX: - result, err = ms.getAllKeysMatchingField(sctx, ColAcc, utils.ACCOUNT_PREFIX, subject, "id") + keys, err = ms.getAllKeysMatchingField(sctx, ColAcc, utils.ACCOUNT_PREFIX, subject, "id") case utils.ResourceProfilesPrefix: - result, err = ms.getAllKeysMatchingTenantID(sctx, ColRsP, utils.ResourceProfilesPrefix, subject, tntID) + keys, err = ms.getAllKeysMatchingTenantID(sctx, ColRsP, utils.ResourceProfilesPrefix, subject, tntID) case utils.ResourcesPrefix: - result, err = ms.getAllKeysMatchingTenantID(sctx, ColRes, utils.ResourcesPrefix, subject, tntID) + keys, err = ms.getAllKeysMatchingTenantID(sctx, ColRes, utils.ResourcesPrefix, subject, tntID) case utils.StatQueuePrefix: - result, err = ms.getAllKeysMatchingTenantID(sctx, ColSqs, utils.StatQueuePrefix, subject, tntID) + keys, err = ms.getAllKeysMatchingTenantID(sctx, ColSqs, utils.StatQueuePrefix, subject, tntID) case utils.StatQueueProfilePrefix: - result, err = ms.getAllKeysMatchingTenantID(sctx, ColSqp, utils.StatQueueProfilePrefix, subject, tntID) + keys, err = ms.getAllKeysMatchingTenantID(sctx, ColSqp, utils.StatQueueProfilePrefix, subject, tntID) case utils.AccountActionPlansPrefix: - result, err = ms.getAllKeysMatchingField(sctx, ColAAp, utils.AccountActionPlansPrefix, subject, "key") + keys, err = ms.getAllKeysMatchingField(sctx, ColAAp, utils.AccountActionPlansPrefix, subject, "key") case utils.TimingsPrefix: - result, err = ms.getAllKeysMatchingField(sctx, ColTmg, utils.TimingsPrefix, subject, "id") + keys, err = ms.getAllKeysMatchingField(sctx, ColTmg, utils.TimingsPrefix, subject, "id") case utils.FilterPrefix: - result, err = ms.getAllKeysMatchingTenantID(sctx, ColFlt, utils.FilterPrefix, subject, tntID) + keys, err = ms.getAllKeysMatchingTenantID(sctx, ColFlt, utils.FilterPrefix, subject, tntID) case utils.ThresholdPrefix: - result, err = ms.getAllKeysMatchingTenantID(sctx, ColThs, utils.ThresholdPrefix, subject, tntID) + keys, err = ms.getAllKeysMatchingTenantID(sctx, ColThs, utils.ThresholdPrefix, subject, tntID) case utils.ThresholdProfilePrefix: - result, err = ms.getAllKeysMatchingTenantID(sctx, ColTps, utils.ThresholdProfilePrefix, subject, tntID) + keys, err = ms.getAllKeysMatchingTenantID(sctx, ColTps, utils.ThresholdProfilePrefix, subject, tntID) case utils.SupplierProfilePrefix: - result, err = ms.getAllKeysMatchingTenantID(sctx, ColSpp, utils.SupplierProfilePrefix, subject, tntID) + keys, err = ms.getAllKeysMatchingTenantID(sctx, ColSpp, utils.SupplierProfilePrefix, subject, tntID) case utils.AttributeProfilePrefix: - result, err = ms.getAllKeysMatchingTenantID(sctx, ColAttr, utils.AttributeProfilePrefix, subject, tntID) + keys, err = ms.getAllKeysMatchingTenantID(sctx, ColAttr, utils.AttributeProfilePrefix, subject, tntID) case utils.ChargerProfilePrefix: - result, err = ms.getAllKeysMatchingTenantID(sctx, ColCpp, utils.ChargerProfilePrefix, subject, tntID) + keys, err = ms.getAllKeysMatchingTenantID(sctx, ColCpp, utils.ChargerProfilePrefix, subject, tntID) case utils.DispatcherProfilePrefix: - result, err = ms.getAllKeysMatchingTenantID(sctx, ColDpp, utils.DispatcherProfilePrefix, subject, tntID) + keys, err = ms.getAllKeysMatchingTenantID(sctx, ColDpp, utils.DispatcherProfilePrefix, subject, tntID) case utils.DispatcherHostPrefix: - result, err = ms.getAllKeysMatchingTenantID(sctx, ColDph, utils.DispatcherHostPrefix, subject, tntID) + keys, err = ms.getAllKeysMatchingTenantID(sctx, ColDph, utils.DispatcherHostPrefix, subject, tntID) case utils.AttributeFilterIndexes: - result, err = ms.getAllIndexKeys(sctx, ColRFI, utils.AttributeFilterIndexes, "key") + keys, err = ms.getAllIndexKeys(sctx, utils.AttributeFilterIndexes) case utils.ResourceFilterIndexes: - result, err = ms.getAllIndexKeys(sctx, ColRFI, utils.ResourceFilterIndexes, "key") + keys, err = ms.getAllIndexKeys(sctx, utils.ResourceFilterIndexes) case utils.StatFilterIndexes: - result, err = ms.getAllIndexKeys(sctx, ColRFI, utils.StatFilterIndexes, "key") + keys, err = ms.getAllIndexKeys(sctx, utils.StatFilterIndexes) case utils.ThresholdFilterIndexes: - result, err = ms.getAllIndexKeys(sctx, ColRFI, utils.ThresholdFilterIndexes, "key") + keys, err = ms.getAllIndexKeys(sctx, utils.ThresholdFilterIndexes) case utils.SupplierFilterIndexes: - result, err = ms.getAllIndexKeys(sctx, ColRFI, utils.SupplierFilterIndexes, "key") + keys, err = ms.getAllIndexKeys(sctx, utils.SupplierFilterIndexes) case utils.ChargerFilterIndexes: - result, err = ms.getAllIndexKeys(sctx, ColRFI, utils.ChargerFilterIndexes, "key") + keys, err = ms.getAllIndexKeys(sctx, utils.ChargerFilterIndexes) case utils.DispatcherFilterIndexes: - result, err = ms.getAllIndexKeys(sctx, ColRFI, utils.DispatcherFilterIndexes, "key") + keys, err = ms.getAllIndexKeys(sctx, utils.DispatcherFilterIndexes) default: err = fmt.Errorf("unsupported prefix in GetKeysForPrefix: %s", prefix) } return err }) - return + return keys, err } func (ms *MongoStorage) HasDataDrv(category, subject, tenant string) (has bool, err error) { @@ -670,21 +642,20 @@ func (ms *MongoStorage) HasDataDrv(category, subject, tenant string) (has bool, return has, err } -func (ms *MongoStorage) GetRatingPlanDrv(key string) (rp *RatingPlan, err error) { +func (ms *MongoStorage) GetRatingPlanDrv(key string) (*RatingPlan, error) { var kv struct { Key string Value []byte } - if err = ms.query(func(sctx mongo.SessionContext) (err error) { + err := ms.query(func(sctx mongo.SessionContext) (err error) { cur := ms.getCol(ColRpl).FindOne(sctx, bson.M{"key": key}) - if err := cur.Decode(&kv); err != nil { - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err + decodeErr := cur.Decode(&kv) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil - }); err != nil { + return decodeErr + }) + if err != nil { return nil, err } @@ -697,11 +668,13 @@ func (ms *MongoStorage) GetRatingPlanDrv(key string) (rp *RatingPlan, err error) if err != nil { return nil, err } - r.Close() - if err = ms.ms.Unmarshal(out, &rp); err != nil { + err = r.Close() + if err != nil { return nil, err } - return + var ratingPlan *RatingPlan + err = ms.ms.Unmarshal(out, &ratingPlan) + return ratingPlan, err } func (ms *MongoStorage) SetRatingPlanDrv(rp *RatingPlan) error { @@ -711,10 +684,16 @@ func (ms *MongoStorage) SetRatingPlanDrv(rp *RatingPlan) error { } var b bytes.Buffer w := zlib.NewWriter(&b) - w.Write(result) - w.Close() - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColRpl).UpdateOne(sctx, bson.M{"key": rp.Id}, + _, err = w.Write(result) + if err != nil { + return err + } + err = w.Close() + if err != nil { + return err + } + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColRpl).UpdateOne(sctx, bson.M{"key": rp.Id}, bson.M{"$set": struct { Key string Value []byte @@ -726,7 +705,7 @@ func (ms *MongoStorage) SetRatingPlanDrv(rp *RatingPlan) error { } func (ms *MongoStorage) RemoveRatingPlanDrv(key string) error { - return ms.query(func(sctx mongo.SessionContext) (err error) { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColRpl).DeleteMany(sctx, bson.M{"key": key}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -735,25 +714,22 @@ func (ms *MongoStorage) RemoveRatingPlanDrv(key string) error { }) } -func (ms *MongoStorage) GetRatingProfileDrv(key string) (rp *RatingProfile, err error) { - rp = new(RatingProfile) - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColRpf).FindOne(sctx, bson.M{"id": key}) - if err := cur.Decode(rp); err != nil { - rp = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err +func (ms *MongoStorage) GetRatingProfileDrv(key string) (*RatingProfile, error) { + rtProfile := new(RatingProfile) + err := ms.query(func(sctx mongo.SessionContext) (err error) { + sr := ms.getCol(ColRpf).FindOne(sctx, bson.M{"id": key}) + decodeErr := sr.Decode(rtProfile) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil + return decodeErr }) - return + return rtProfile, err } -func (ms *MongoStorage) SetRatingProfileDrv(rp *RatingProfile) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColRpf).UpdateOne(sctx, bson.M{"id": rp.Id}, +func (ms *MongoStorage) SetRatingProfileDrv(rp *RatingProfile) error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColRpf).UpdateOne(sctx, bson.M{"id": rp.Id}, bson.M{"$set": rp}, options.Update().SetUpsert(true), ) @@ -762,7 +738,7 @@ func (ms *MongoStorage) SetRatingProfileDrv(rp *RatingProfile) (err error) { } func (ms *MongoStorage) RemoveRatingProfileDrv(key string) error { - return ms.query(func(sctx mongo.SessionContext) (err error) { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColRpf).DeleteMany(sctx, bson.M{"id": key}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -772,7 +748,8 @@ func (ms *MongoStorage) RemoveRatingProfileDrv(key string) error { } func (ms *MongoStorage) GetDestinationDrv(key string, skipCache bool, - transactionID string) (result *Destination, err error) { + transactionID string, +) (*Destination, error) { if !skipCache { if x, ok := Cache.Get(utils.CacheDestinations, key); ok { if x == nil { @@ -785,18 +762,17 @@ func (ms *MongoStorage) GetDestinationDrv(key string, skipCache bool, Key string Value []byte } - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColDst).FindOne(sctx, bson.M{"key": key}) - if err := cur.Decode(&kv); err != nil { - if err == mongo.ErrNoDocuments { - Cache.Set(utils.CacheDestinations, key, nil, nil, - cacheCommit(transactionID), transactionID) - return utils.ErrNotFound - } - return err + err := ms.query(func(sctx mongo.SessionContext) (err error) { + sr := ms.getCol(ColDst).FindOne(sctx, bson.M{"key": key}) + decodeErr := sr.Decode(&kv) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + Cache.Set(utils.CacheDestinations, key, nil, nil, + cacheCommit(transactionID), transactionID) + return utils.ErrNotFound } - return nil - }); err != nil { + return decodeErr + }) + if err != nil { return nil, err } b := bytes.NewBuffer(kv.Value) @@ -808,26 +784,36 @@ func (ms *MongoStorage) GetDestinationDrv(key string, skipCache bool, if err != nil { return nil, err } - r.Close() - err = ms.ms.Unmarshal(out, &result) + err = r.Close() if err != nil { return nil, err } - Cache.Set(utils.CacheDestinations, key, result, nil, + var dst *Destination + err = ms.ms.Unmarshal(out, &dst) + if err != nil { + return nil, err + } + Cache.Set(utils.CacheDestinations, key, dst, nil, cacheCommit(transactionID), transactionID) - return + return dst, nil } -func (ms *MongoStorage) SetDestinationDrv(dest *Destination, transactionID string) (err error) { +func (ms *MongoStorage) SetDestinationDrv(dest *Destination, _ string) error { result, err := ms.ms.Marshal(dest) if err != nil { return err } var b bytes.Buffer w := zlib.NewWriter(&b) - w.Write(result) - w.Close() - return ms.query(func(sctx mongo.SessionContext) (err error) { + _, err = w.Write(result) + if err != nil { + return err + } + err = w.Close() + if err != nil { + return err + } + return ms.query(func(sctx mongo.SessionContext) error { _, err = ms.getCol(ColDst).UpdateOne(sctx, bson.M{"key": dest.Id}, bson.M{"$set": struct { Key string @@ -840,41 +826,49 @@ func (ms *MongoStorage) SetDestinationDrv(dest *Destination, transactionID strin } func (ms *MongoStorage) RemoveDestinationDrv(destID string, - transactionID string) (err error) { + transactionID string, +) error { // get destination for prefix list d, err := ms.GetDestinationDrv(destID, false, transactionID) if err != nil { - return + return err } - if err = ms.query(func(sctx mongo.SessionContext) (err error) { + err = ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColDst).DeleteOne(sctx, bson.M{"key": destID}) if dr.DeletedCount == 0 { return utils.ErrNotFound } return err - }); err != nil { + }) + if err != nil { return err } Cache.Remove(utils.CacheDestinations, destID, cacheCommit(transactionID), transactionID) for _, prefix := range d.Prefixes { - if err = ms.query(func(sctx mongo.SessionContext) (err error) { + err = ms.query(func(sctx mongo.SessionContext) (err error) { _, err = ms.getCol(ColRds).UpdateOne(sctx, bson.M{"key": prefix}, bson.M{"$pull": bson.M{"value": destID}}) return err - }); err != nil { + }) + if err != nil { + return err + } + _, err = ms.GetReverseDestinationDrv(prefix, true, transactionID) // it will recache the destination + if err != nil { return err } - ms.GetReverseDestinationDrv(prefix, true, transactionID) // it will recache the destination } - return + return nil } func (ms *MongoStorage) GetReverseDestinationDrv(prefix string, skipCache bool, - transactionID string) (ids []string, err error) { + transactionID string, +) ([]string, error) { if !skipCache { - if x, ok := Cache.Get(utils.CacheReverseDestinations, prefix); ok { + x, ok := Cache.Get(utils.CacheReverseDestinations, prefix) + if ok { if x == nil { return nil, utils.ErrNotFound } @@ -885,37 +879,35 @@ func (ms *MongoStorage) GetReverseDestinationDrv(prefix string, skipCache bool, Key string Value []string } - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColRds).FindOne(sctx, bson.M{"key": prefix}) - if err := cur.Decode(&result); err != nil { - if err == mongo.ErrNoDocuments { - Cache.Set(utils.CacheReverseDestinations, prefix, nil, nil, - cacheCommit(transactionID), transactionID) - return utils.ErrNotFound - } - return err + err := ms.query(func(sctx mongo.SessionContext) (err error) { + sr := ms.getCol(ColRds).FindOne(sctx, bson.M{"key": prefix}) + decodeErr := sr.Decode(&result) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + Cache.Set(utils.CacheReverseDestinations, prefix, nil, nil, + cacheCommit(transactionID), transactionID) + return utils.ErrNotFound } - return nil - }); err != nil { + return decodeErr + }) + if err != nil { return nil, err } - ids = result.Value - Cache.Set(utils.CacheReverseDestinations, prefix, ids, nil, + Cache.Set(utils.CacheReverseDestinations, prefix, result.Value, nil, cacheCommit(transactionID), transactionID) - return + return result.Value, nil } -func (ms *MongoStorage) SetReverseDestinationDrv(dest *Destination, - transactionID string) (err error) { +func (ms *MongoStorage) SetReverseDestinationDrv(dest *Destination, _ string) error { for _, p := range dest.Prefixes { - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColRds).UpdateOne(sctx, bson.M{"key": p}, + err := ms.query(func(sctx mongo.SessionContext) error { + _, queryErr := ms.getCol(ColRds).UpdateOne(sctx, + bson.M{"key": p}, bson.M{"$addToSet": bson.M{"value": dest.Id}}, options.Update().SetUpsert(true), ) - return err - }); err != nil { - + return queryErr + }) + if err != nil { return err } } @@ -923,8 +915,9 @@ func (ms *MongoStorage) SetReverseDestinationDrv(dest *Destination, } func (ms *MongoStorage) UpdateReverseDestinationDrv(oldDest, newDest *Destination, - transactionID string) error { - //log.Printf("Old: %+v, New: %+v", oldDest, newDest) + transactionID string, +) error { + // log.Printf("Old: %+v, New: %+v", oldDest, newDest) var obsoletePrefixes []string var addedPrefixes []string if oldDest == nil { @@ -955,17 +948,19 @@ func (ms *MongoStorage) UpdateReverseDestinationDrv(oldDest, newDest *Destinatio addedPrefixes = append(addedPrefixes, newPrefix) } } - //log.Print("Obsolete prefixes: ", obsoletePrefixes) - //log.Print("Added prefixes: ", addedPrefixes) + // log.Print("Obsolete prefixes: ", obsoletePrefixes) + // log.Print("Added prefixes: ", addedPrefixes) // remove id for all obsolete prefixes cCommit := cacheCommit(transactionID) var err error for _, obsoletePrefix := range obsoletePrefixes { - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColRds).UpdateOne(sctx, bson.M{"key": obsoletePrefix}, + err = ms.query(func(sctx mongo.SessionContext) error { + _, queryErr := ms.getCol(ColRds).UpdateOne(sctx, + bson.M{"key": obsoletePrefix}, bson.M{"$pull": bson.M{"value": oldDest.Id}}) - return err - }); err != nil { + return queryErr + }) + if err != nil { return err } Cache.Remove(utils.CacheReverseDestinations, obsoletePrefix, @@ -974,43 +969,40 @@ func (ms *MongoStorage) UpdateReverseDestinationDrv(oldDest, newDest *Destinatio // add the id to all new prefixes for _, addedPrefix := range addedPrefixes { - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColRds).UpdateOne(sctx, bson.M{"key": addedPrefix}, + err = ms.query(func(sctx mongo.SessionContext) error { + _, queryErr := ms.getCol(ColRds).UpdateOne(sctx, + bson.M{"key": addedPrefix}, bson.M{"$addToSet": bson.M{"value": newDest.Id}}, options.Update().SetUpsert(true), ) - return err - }); err != nil { + return queryErr + }) + if err != nil { return err } } return nil } -func (ms *MongoStorage) GetActionsDrv(key string) (as Actions, err error) { +func (ms *MongoStorage) GetActionsDrv(key string) (Actions, error) { var result struct { Key string Value Actions } - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColAct).FindOne(sctx, bson.M{"key": key}) - if err := cur.Decode(&result); err != nil { - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err + err := ms.query(func(sctx mongo.SessionContext) (err error) { + sr := ms.getCol(ColAct).FindOne(sctx, bson.M{"key": key}) + decodeErr := sr.Decode(&result) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil - }); err != nil { - return nil, err - } - as = result.Value - return + return decodeErr + }) + return result.Value, err } func (ms *MongoStorage) SetActionsDrv(key string, as Actions) error { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColAct).UpdateOne(sctx, bson.M{"key": key}, + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColAct).UpdateOne(sctx, bson.M{"key": key}, bson.M{"$set": struct { Key string Value Actions @@ -1022,7 +1014,7 @@ func (ms *MongoStorage) SetActionsDrv(key string, as Actions) error { } func (ms *MongoStorage) RemoveActionsDrv(key string) error { - return ms.query(func(sctx mongo.SessionContext) (err error) { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColAct).DeleteOne(sctx, bson.M{"key": key}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -1031,25 +1023,22 @@ func (ms *MongoStorage) RemoveActionsDrv(key string) error { }) } -func (ms *MongoStorage) GetSharedGroupDrv(key string) (sg *SharedGroup, err error) { - sg = new(SharedGroup) - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColShg).FindOne(sctx, bson.M{"id": key}) - if err := cur.Decode(sg); err != nil { - sg = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err +func (ms *MongoStorage) GetSharedGroupDrv(key string) (*SharedGroup, error) { + sg := new(SharedGroup) + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColShg).FindOne(sctx, bson.M{"id": key}) + decodeErr := sr.Decode(sg) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil + return decodeErr }) - return + return sg, err } -func (ms *MongoStorage) SetSharedGroupDrv(sg *SharedGroup) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColShg).UpdateOne(sctx, bson.M{"id": sg.Id}, +func (ms *MongoStorage) SetSharedGroupDrv(sg *SharedGroup) error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColShg).UpdateOne(sctx, bson.M{"id": sg.Id}, bson.M{"$set": sg}, options.Update().SetUpsert(true), ) @@ -1057,8 +1046,8 @@ func (ms *MongoStorage) SetSharedGroupDrv(sg *SharedGroup) (err error) { }) } -func (ms *MongoStorage) RemoveSharedGroupDrv(id string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { +func (ms *MongoStorage) RemoveSharedGroupDrv(id string) error { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColShg).DeleteOne(sctx, bson.M{"id": id}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -1067,20 +1056,17 @@ func (ms *MongoStorage) RemoveSharedGroupDrv(id string) (err error) { }) } -func (ms *MongoStorage) GetAccountDrv(key string) (result *Account, err error) { - result = new(Account) - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColAcc).FindOne(sctx, bson.M{"id": key}) - if err := cur.Decode(result); err != nil { - result = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err +func (ms *MongoStorage) GetAccountDrv(key string) (*Account, error) { + acc := new(Account) + err := ms.query(func(sctx mongo.SessionContext) (err error) { + sr := ms.getCol(ColAcc).FindOne(sctx, bson.M{"id": key}) + decodeErr := sr.Decode(acc) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil + return decodeErr }) - return + return acc, err } func (ms *MongoStorage) SetAccountDrv(acc *Account) error { @@ -1088,7 +1074,8 @@ func (ms *MongoStorage) SetAccountDrv(acc *Account) error { // UPDATE: if all balances expired and were cleaned it makes // sense to write empty balance map if len(acc.BalanceMap) == 0 { - if ac, err := ms.GetAccountDrv(acc.ID); err == nil && !ac.allBalancesExpired() { + ac, err := ms.GetAccountDrv(acc.ID) + if err == nil && !ac.allBalancesExpired() { ac.ActionTriggers = acc.ActionTriggers ac.UnitCounters = acc.UnitCounters ac.AllowNegative = acc.AllowNegative @@ -1097,8 +1084,8 @@ func (ms *MongoStorage) SetAccountDrv(acc *Account) error { } } acc.UpdateTime = time.Now() - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColAcc).UpdateOne(sctx, bson.M{"id": acc.ID}, + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColAcc).UpdateOne(sctx, bson.M{"id": acc.ID}, bson.M{"$set": acc}, options.Update().SetUpsert(true), ) @@ -1106,8 +1093,8 @@ func (ms *MongoStorage) SetAccountDrv(acc *Account) error { }) } -func (ms *MongoStorage) RemoveAccountDrv(key string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { +func (ms *MongoStorage) RemoveAccountDrv(key string) error { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColAcc).DeleteOne(sctx, bson.M{"id": key}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -1116,16 +1103,21 @@ func (ms *MongoStorage) RemoveAccountDrv(key string) (err error) { }) } -// Limit will only retrieve the last n items out of history, newest first +// GetLoadHistory retrieves the last n items from the load history, newest first. func (ms *MongoStorage) GetLoadHistory(limit int, skipCache bool, - transactionID string) (loadInsts []*utils.LoadInstance, err error) { + transactionID string, +) ([]*utils.LoadInstance, error) { if limit == 0 { return nil, nil } if !skipCache { - if x, ok := Cache.Get(utils.LOADINST_KEY, ""); ok { + x, ok := Cache.Get(utils.LOADINST_KEY, "") + if ok { if x != nil { - items := x.([]*utils.LoadInstance) + items, ok := x.([]*utils.LoadInstance) + if !ok { + return nil, errors.New("failed to cast value") + } if len(items) < limit || limit == -1 { return items, nil } @@ -1138,62 +1130,60 @@ func (ms *MongoStorage) GetLoadHistory(limit int, skipCache bool, Key string Value []*utils.LoadInstance } - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColLht).FindOne(sctx, bson.M{"key": utils.LOADINST_KEY}) - if err := cur.Decode(&kv); err != nil { - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColLht).FindOne(sctx, bson.M{"key": utils.LOADINST_KEY}) + decodeErr := sr.Decode(&kv) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil + return decodeErr }) cCommit := cacheCommit(transactionID) if err == nil { - loadInsts = kv.Value Cache.Remove(utils.LOADINST_KEY, "", cCommit, transactionID) - Cache.Set(utils.LOADINST_KEY, "", loadInsts, nil, cCommit, transactionID) + Cache.Set(utils.LOADINST_KEY, "", kv.Value, nil, cCommit, transactionID) } - if len(loadInsts) < limit || limit == -1 { - return loadInsts, nil + if len(kv.Value) < limit || limit == -1 { + return kv.Value, nil } - return loadInsts[:limit], nil + return kv.Value[:limit], nil } -// Adds a single load instance to load history +// AddLoadHistory adds a single load instance to the load history. func (ms *MongoStorage) AddLoadHistory(ldInst *utils.LoadInstance, - loadHistSize int, transactionID string) error { + loadHistSize int, transactionID string, +) error { if loadHistSize == 0 { // Load history disabled return nil } - // get existing load history + // Get existing load history. var existingLoadHistory []*utils.LoadInstance var kv struct { Key string Value []*utils.LoadInstance } - if err := ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColLht).FindOne(sctx, bson.M{"key": utils.LOADINST_KEY}) - if err := cur.Decode(&kv); err != nil { - if err == mongo.ErrNoDocuments { - return nil // utils.ErrNotFound - } - return err + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColLht).FindOne(sctx, bson.M{"key": utils.LOADINST_KEY}) + decodeErr := sr.Decode(&kv) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return nil // utils.ErrNotFound } - return nil - }); err != nil { + return decodeErr + }) + if err != nil { return err } if kv.Value != nil { existingLoadHistory = kv.Value } - _, err := guardian.Guardian.Guard(func() (any, error) { // Make sure we do it locked since other instance can modify history while we read it - // insert on first position + + // Make sure we do it locked since other instances can modify the history while we read it. + _, err = guardian.Guardian.Guard(func() (any, error) { + // Insert at the first position. existingLoadHistory = append(existingLoadHistory, nil) copy(existingLoadHistory[1:], existingLoadHistory[0:]) existingLoadHistory[0] = ldInst - //check length histLen := len(existingLoadHistory) if histLen >= loadHistSize { // Have hit maximum history allowed, remove oldest element in order to add new one existingLoadHistory = existingLoadHistory[:loadHistSize] @@ -1215,36 +1205,31 @@ func (ms *MongoStorage) AddLoadHistory(ldInst *utils.LoadInstance, return err } -func (ms *MongoStorage) GetActionTriggersDrv(key string) (atrs ActionTriggers, err error) { +func (ms *MongoStorage) GetActionTriggersDrv(key string) (ActionTriggers, error) { var kv struct { Key string Value ActionTriggers } - if err := ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColAtr).FindOne(sctx, bson.M{"key": key}) - if err := cur.Decode(&kv); err != nil { - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColAtr).FindOne(sctx, bson.M{"key": key}) + decodeErr := sr.Decode(&kv) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil - }); err != nil { - return nil, err - } - atrs = kv.Value - return + return decodeErr + }) + return kv.Value, err } -func (ms *MongoStorage) SetActionTriggersDrv(key string, atrs ActionTriggers) (err error) { +func (ms *MongoStorage) SetActionTriggersDrv(key string, atrs ActionTriggers) error { if len(atrs) == 0 { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColAtr).DeleteOne(sctx, bson.M{"key": key}) + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColAtr).DeleteOne(sctx, bson.M{"key": key}) return err }) } - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColAtr).UpdateOne(sctx, bson.M{"key": key}, + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColAtr).UpdateOne(sctx, bson.M{"key": key}, bson.M{"$set": struct { Key string Value ActionTriggers @@ -1256,8 +1241,7 @@ func (ms *MongoStorage) SetActionTriggersDrv(key string, atrs ActionTriggers) (e } func (ms *MongoStorage) RemoveActionTriggersDrv(key string) error { - - return ms.query(func(sctx mongo.SessionContext) (err error) { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColAtr).DeleteOne(sctx, bson.M{"key": key}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -1266,21 +1250,20 @@ func (ms *MongoStorage) RemoveActionTriggersDrv(key string) error { }) } -func (ms *MongoStorage) GetActionPlanDrv(key string) (ats *ActionPlan, err error) { +func (ms *MongoStorage) GetActionPlanDrv(key string) (*ActionPlan, error) { var kv struct { Key string Value []byte } - if err := ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColApl).FindOne(sctx, bson.M{"key": key}) - if err := cur.Decode(&kv); err != nil { - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColApl).FindOne(sctx, bson.M{"key": key}) + decodeErr := sr.Decode(&kv) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil - }); err != nil { + return decodeErr + }) + if err != nil { return nil, err } b := bytes.NewBuffer(kv.Value) @@ -1292,22 +1275,32 @@ func (ms *MongoStorage) GetActionPlanDrv(key string) (ats *ActionPlan, err error if err != nil { return nil, err } - r.Close() - err = ms.ms.Unmarshal(out, &ats) - return + err = r.Close() + if err != nil { + return nil, err + } + var ap *ActionPlan + err = ms.ms.Unmarshal(out, &ap) + return ap, err } -func (ms *MongoStorage) SetActionPlanDrv(key string, ats *ActionPlan) (err error) { +func (ms *MongoStorage) SetActionPlanDrv(key string, ats *ActionPlan) error { result, err := ms.ms.Marshal(ats) if err != nil { return err } var b bytes.Buffer w := zlib.NewWriter(&b) - w.Write(result) - w.Close() - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColApl).UpdateOne(sctx, bson.M{"key": key}, + _, err = w.Write(result) + if err != nil { + return err + } + err = w.Close() + if err != nil { + return err + } + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColApl).UpdateOne(sctx, bson.M{"key": key}, bson.M{"$set": struct { Key string Value []byte @@ -1319,13 +1312,13 @@ func (ms *MongoStorage) SetActionPlanDrv(key string, ats *ActionPlan) (err error } func (ms *MongoStorage) RemoveActionPlanDrv(key string) error { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColApl).DeleteOne(sctx, bson.M{"key": key}) + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColApl).DeleteOne(sctx, bson.M{"key": key}) return err }) } -func (ms *MongoStorage) GetAllActionPlansDrv() (ats map[string]*ActionPlan, err error) { +func (ms *MongoStorage) GetAllActionPlansDrv() (map[string]*ActionPlan, error) { keys, err := ms.GetKeysForPrefix(utils.ACTION_PLAN_PREFIX) if err != nil { return nil, err @@ -1333,41 +1326,36 @@ func (ms *MongoStorage) GetAllActionPlansDrv() (ats map[string]*ActionPlan, err if len(keys) == 0 { return nil, utils.ErrNotFound } - ats = make(map[string]*ActionPlan, len(keys)) + actionPlans := make(map[string]*ActionPlan, len(keys)) for _, key := range keys { ap, err := ms.GetActionPlanDrv(key[len(utils.ACTION_PLAN_PREFIX):]) if err != nil { return nil, err } - ats[key[len(utils.ACTION_PLAN_PREFIX):]] = ap + actionPlans[key[len(utils.ACTION_PLAN_PREFIX):]] = ap } - return + return actionPlans, nil } -func (ms *MongoStorage) GetAccountActionPlansDrv(acntID string) (aPlIDs []string, err error) { +func (ms *MongoStorage) GetAccountActionPlansDrv(acntID string) ([]string, error) { var kv struct { Key string Value []string } - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColAAp).FindOne(sctx, bson.M{"key": acntID}) - if err := cur.Decode(&kv); err != nil { - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColAAp).FindOne(sctx, bson.M{"key": acntID}) + decodeErr := sr.Decode(&kv) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil - }); err != nil { - return nil, err - } - aPlIDs = kv.Value - return + return decodeErr + }) + return kv.Value, err } -func (ms *MongoStorage) SetAccountActionPlansDrv(acntID string, aPlIDs []string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColAAp).UpdateOne(sctx, bson.M{"key": acntID}, +func (ms *MongoStorage) SetAccountActionPlansDrv(acntID string, aPlIDs []string) error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColAAp).UpdateOne(sctx, bson.M{"key": acntID}, bson.M{"$set": struct { Key string Value []string @@ -1379,8 +1367,8 @@ func (ms *MongoStorage) SetAccountActionPlansDrv(acntID string, aPlIDs []string) } // ToDo: check return len(aPlIDs) == 0 -func (ms *MongoStorage) RemAccountActionPlansDrv(acntID string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { +func (ms *MongoStorage) RemAccountActionPlansDrv(acntID string) error { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColAAp).DeleteOne(sctx, bson.M{"key": acntID}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -1396,45 +1384,38 @@ func (ms *MongoStorage) PushTask(t *Task) error { }) } -func (ms *MongoStorage) PopTask() (t *Task, err error) { +func (ms *MongoStorage) PopTask() (*Task, error) { v := struct { ID primitive.ObjectID `bson:"_id"` Task *Task }{} - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColTsk).FindOneAndDelete(sctx, bson.D{}) - if err := cur.Decode(&v); err != nil { - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColTsk).FindOneAndDelete(sctx, bson.D{}) + decodeErr := sr.Decode(&v) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil - }); err != nil { - return nil, err - } - return v.Task, nil -} - -func (ms *MongoStorage) GetResourceProfileDrv(tenant, id string) (rp *ResourceProfile, err error) { - rp = new(ResourceProfile) - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColRsP).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) - if err := cur.Decode(rp); err != nil { - rp = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err - } - return nil + return decodeErr }) - return + return v.Task, err } -func (ms *MongoStorage) SetResourceProfileDrv(rp *ResourceProfile) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColRsP).UpdateOne(sctx, bson.M{"tenant": rp.Tenant, "id": rp.ID}, +func (ms *MongoStorage) GetResourceProfileDrv(tenant, id string) (*ResourceProfile, error) { + rsProfile := new(ResourceProfile) + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColRsP).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) + decodeErr := sr.Decode(rsProfile) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound + } + return decodeErr + }) + return rsProfile, err +} + +func (ms *MongoStorage) SetResourceProfileDrv(rp *ResourceProfile) error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColRsP).UpdateOne(sctx, bson.M{"tenant": rp.Tenant, "id": rp.ID}, bson.M{"$set": rp}, options.Update().SetUpsert(true), ) @@ -1442,8 +1423,8 @@ func (ms *MongoStorage) SetResourceProfileDrv(rp *ResourceProfile) (err error) { }) } -func (ms *MongoStorage) RemoveResourceProfileDrv(tenant, id string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { +func (ms *MongoStorage) RemoveResourceProfileDrv(tenant, id string) error { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColRsP).DeleteOne(sctx, bson.M{"tenant": tenant, "id": id}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -1452,25 +1433,22 @@ func (ms *MongoStorage) RemoveResourceProfileDrv(tenant, id string) (err error) }) } -func (ms *MongoStorage) GetResourceDrv(tenant, id string) (r *Resource, err error) { - r = new(Resource) - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColRes).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) - if err := cur.Decode(r); err != nil { - r = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err +func (ms *MongoStorage) GetResourceDrv(tenant, id string) (*Resource, error) { + resource := new(Resource) + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColRes).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) + decodeErr := sr.Decode(resource) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil + return decodeErr }) - return + return resource, err } -func (ms *MongoStorage) SetResourceDrv(r *Resource) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColRes).UpdateOne(sctx, bson.M{"tenant": r.Tenant, "id": r.ID}, +func (ms *MongoStorage) SetResourceDrv(r *Resource) error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColRes).UpdateOne(sctx, bson.M{"tenant": r.Tenant, "id": r.ID}, bson.M{"$set": r}, options.Update().SetUpsert(true), ) @@ -1478,8 +1456,8 @@ func (ms *MongoStorage) SetResourceDrv(r *Resource) (err error) { }) } -func (ms *MongoStorage) RemoveResourceDrv(tenant, id string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { +func (ms *MongoStorage) RemoveResourceDrv(tenant, id string) error { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColRes).DeleteOne(sctx, bson.M{"tenant": tenant, "id": id}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -1488,25 +1466,22 @@ func (ms *MongoStorage) RemoveResourceDrv(tenant, id string) (err error) { }) } -func (ms *MongoStorage) GetTimingDrv(id string) (t *utils.TPTiming, err error) { - t = new(utils.TPTiming) - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColTmg).FindOne(sctx, bson.M{"id": id}) - if err := cur.Decode(t); err != nil { - t = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err +func (ms *MongoStorage) GetTimingDrv(id string) (*utils.TPTiming, error) { + timing := new(utils.TPTiming) + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColTmg).FindOne(sctx, bson.M{"id": id}) + decodeErr := sr.Decode(timing) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil + return decodeErr }) - return + return timing, err } -func (ms *MongoStorage) SetTimingDrv(t *utils.TPTiming) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColTmg).UpdateOne(sctx, bson.M{"id": t.ID}, +func (ms *MongoStorage) SetTimingDrv(t *utils.TPTiming) error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColTmg).UpdateOne(sctx, bson.M{"id": t.ID}, bson.M{"$set": t}, options.Update().SetUpsert(true), ) @@ -1514,8 +1489,8 @@ func (ms *MongoStorage) SetTimingDrv(t *utils.TPTiming) (err error) { }) } -func (ms *MongoStorage) RemoveTimingDrv(id string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { +func (ms *MongoStorage) RemoveTimingDrv(id string) error { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColTmg).DeleteOne(sctx, bson.M{"id": id}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -1524,94 +1499,79 @@ func (ms *MongoStorage) RemoveTimingDrv(id string) (err error) { }) } -// GetFilterIndexesDrv retrieves Indexes from dataDB -// filterType is used together with fieldName:Val +// GetFilterIndexesDrv retrieves indexes from the dataDB based on the specified parameters. +// filterType and fldNameVal are used together for specific searches. func (ms *MongoStorage) GetFilterIndexesDrv(cacheID, itemIDPrefix, filterType string, - fldNameVal map[string]string) (indexes map[string]utils.StringMap, err error) { + fldNameVal map[string]string, +) (map[string]utils.StringMap, error) { type result struct { Key string Value []string } var results []result - dbKey := utils.CacheInstanceToPrefix[cacheID] + itemIDPrefix - // If dealing with reverse filter indexes, the key differs and therefore - // we shouldn't use regex to search for it. - if strings.HasPrefix(dbKey, utils.ReverseFilterIndexes) { - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur, err := ms.getCol(ColRFI).Find(sctx, - bson.M{"key": utils.ConcatenatedKey(dbKey)}) + retrieveIndexesFromDB := func(queryKey string, isRegex bool) error { + return ms.query(func(sctx mongo.SessionContext) (err error) { + bsonFilter := bson.M{"key": queryKey} + if isRegex { + // For optimization, use a caret (^) in the regex pattern. + bsonFilter["key"] = primitive.Regex{ + Pattern: "^" + queryKey, + } + } + var cur *mongo.Cursor + cur, err = ms.getCol(ColRFI).Find(sctx, bsonFilter) if err != nil { return err } + defer func() { + closeErr := cur.Close(sctx) + if closeErr != nil && err == nil { + err = closeErr + } + }() + for cur.Next(sctx) { var elem result - if err := cur.Decode(&elem); err != nil { - return err - } - results = append(results, elem) - } - return cur.Close(sctx) - }); err != nil { - return nil, err - } - if len(results) == 0 { - return nil, utils.ErrNotFound - } - } else if len(fldNameVal) != 0 { // case for searching of a field:value - for fldName, fldValue := range fldNameVal { - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur, err := ms.getCol(ColRFI).Find(sctx, - bson.M{"key": utils.ConcatenatedKey(dbKey, filterType, fldName, fldValue)}) + err = cur.Decode(&elem) if err != nil { return err } - for cur.Next(sctx) { - var elem result - if err := cur.Decode(&elem); err != nil { - return err - } - results = append(results, elem) - } - return cur.Close(sctx) - }); err != nil { - return nil, err - } - if len(results) == 0 { - return nil, utils.ErrNotFound - } - } - } else { - for _, character := range []string{".", "*"} { - dbKey = strings.Replace(dbKey, character, `\`+character, strings.Count(dbKey, character)) - } - // For optimization, use a caret (^) in the regex pattern. - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur, err := ms.getCol(ColRFI).Find(sctx, - bson.M{ - "key": primitive.Regex{ - Pattern: "^" + dbKey}, - }, - ) - if err != nil { - return err - } - for cur.Next(sctx) { - var elem result - if err := cur.Decode(&elem); err != nil { - return err - } results = append(results, elem) } - return cur.Close(sctx) - }); err != nil { + return cur.Err() + }) + } + + dbKey := utils.CacheInstanceToPrefix[cacheID] + itemIDPrefix + switch { + default: + for _, character := range []string{".", "*"} { + dbKey = strings.ReplaceAll(dbKey, character, `\`+character) + } + err := retrieveIndexesFromDB(dbKey, true) + if err != nil { return nil, err } - if len(results) == 0 { - return nil, utils.ErrNotFound + // If dealing with reverse filter indexes, the key differs and therefore + // we shouldn't use regex to search for it. + case strings.HasPrefix(dbKey, utils.ReverseFilterIndexes): + err := retrieveIndexesFromDB(dbKey, false) + if err != nil { + return nil, err + } + case len(fldNameVal) != 0: // case for searching of a field:value + for fldName, fldValue := range fldNameVal { + err := retrieveIndexesFromDB(utils.ConcatenatedKey(dbKey, filterType, fldName, fldValue), false) + if err != nil { + return nil, err + } } } - indexes = make(map[string]utils.StringMap) + if len(results) == 0 { + return nil, utils.ErrNotFound + } + indexes := make(map[string]utils.StringMap) for _, res := range results { if len(res.Value) == 0 { continue @@ -1635,7 +1595,7 @@ func (ms *MongoStorage) GetFilterIndexesDrv(cacheID, itemIDPrefix, filterType st continue } indexKey := utils.ConcatenatedKey(keys[1], keys[2], keys[3]) - //check here if itemIDPrefix has context + // check here if itemIDPrefix has context if len(strings.Split(itemIDPrefix, ":")) == 2 { indexKey = utils.ConcatenatedKey(keys[2], keys[3], keys[4]) } @@ -1648,9 +1608,10 @@ func (ms *MongoStorage) GetFilterIndexesDrv(cacheID, itemIDPrefix, filterType st return indexes, nil } -// SetFilterIndexesDrv stores Indexes into DataDB +// SetFilterIndexesDrv stores indexes into the DataDB based on the specified parameters. func (ms *MongoStorage) SetFilterIndexesDrv(cacheID, itemIDPrefix string, - indexes map[string]utils.StringMap, commit bool, transactionID string) (err error) { + indexes map[string]utils.StringMap, commit bool, transactionID string, +) error { originKey := utils.CacheInstanceToPrefix[cacheID] + itemIDPrefix dbKey := originKey if transactionID != "" { @@ -1659,103 +1620,98 @@ func (ms *MongoStorage) SetFilterIndexesDrv(cacheID, itemIDPrefix string, if commit && transactionID != "" { regexKey := originKey for _, character := range []string{".", "*"} { - regexKey = strings.Replace(regexKey, character, `\`+character, strings.Count(regexKey, character)) + regexKey = strings.ReplaceAll(regexKey, character, `\`+character) } // For optimization, use a caret (^) in the regex pattern. - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColRFI).DeleteMany(sctx, + err := ms.query(func(sctx mongo.SessionContext) error { + _, queryErr := ms.getCol(ColRFI).DeleteMany(sctx, bson.M{ "key": primitive.Regex{ Pattern: "^" + regexKey, }, }, ) - return err - }); err != nil { + return queryErr + }) + if err != nil { return err } - var lastErr error for key, itmMp := range indexes { - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColRFI).UpdateOne(sctx, bson.M{"key": utils.ConcatenatedKey(originKey, key)}, + err = ms.query(func(sctx mongo.SessionContext) error { + _, queryErr := ms.getCol(ColRFI).UpdateOne(sctx, bson.M{"key": utils.ConcatenatedKey(originKey, key)}, bson.M{"$set": bson.M{"key": utils.ConcatenatedKey(originKey, key), "value": itmMp.Slice()}}, options.Update().SetUpsert(true), ) - return err - }); err != nil { - lastErr = err - } + return queryErr + }) } - if lastErr != nil { - return lastErr + if err != nil { + return err } oldKey := "tmp_" + utils.ConcatenatedKey(originKey, transactionID) for _, character := range []string{".", "*"} { - oldKey = strings.Replace(oldKey, character, `\`+character, strings.Count(oldKey, character)) + oldKey = strings.ReplaceAll(oldKey, character, `\`+character) } // For optimization, use a caret (^) in the regex pattern. - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColRFI).DeleteMany(sctx, + return ms.query(func(sctx mongo.SessionContext) (queryErr error) { + _, queryErr = ms.getCol(ColRFI).DeleteMany(sctx, bson.M{ "key": primitive.Regex{ Pattern: "^" + oldKey, }, }, ) - return err + return queryErr + }) + } + + var err error + // forming reverse filter indexes (the format of those is different from normal indexes) + if strings.HasPrefix(dbKey, utils.ReverseFilterIndexes) { + replaceItmMP := make(utils.StringMap) + err = ms.query(func(sctx mongo.SessionContext) error { + var queryErr error + for key, itmMp := range indexes { + for itemID := range itmMp { + replaceItmMP.Copy(utils.StringMap{ + utils.ConcatenatedKey(key, itemID): true, + }) + } + } + if len(replaceItmMP) == 0 { // remove from DB if we set it with empty indexes + _, queryErr = ms.getCol(ColRFI).DeleteOne(sctx, + bson.M{"key": dbKey}) + } else { + _, queryErr = ms.getCol(ColRFI).UpdateOne(sctx, bson.M{"key": dbKey}, + bson.M{"$set": bson.M{"key": dbKey, "value": replaceItmMP.Slice()}}, + options.Update().SetUpsert(true), + ) + } + return queryErr }) } else { - var lastErr error - // forming reverse filter indexes (the format of those is different from normal indexes) - if strings.HasPrefix(dbKey, utils.ReverseFilterIndexes) { - replaceItmMP := make(utils.StringMap) - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - for key, itmMp := range indexes { - for itemID := range itmMp { - replaceItmMP.Copy(utils.StringMap{ - utils.ConcatenatedKey(key, itemID): true, - }) - } - } - if len(replaceItmMP) == 0 { // remove from DB if we set it with empty indexes - _, err = ms.getCol(ColRFI).DeleteOne(sctx, - bson.M{"key": dbKey}) + // forming normal indexes + for key, itmMp := range indexes { + err = ms.query(func(sctx mongo.SessionContext) error { + var queryErr error + idxDbkey := utils.ConcatenatedKey(dbKey, key) + if len(itmMp) == 0 { // remove from DB if we set it with empty indexes + _, queryErr = ms.getCol(ColRFI).DeleteOne(sctx, + bson.M{"key": idxDbkey}) } else { - _, err = ms.getCol(ColRFI).UpdateOne(sctx, bson.M{"key": dbKey}, - bson.M{"$set": bson.M{"key": dbKey, "value": replaceItmMP.Slice()}}, + _, queryErr = ms.getCol(ColRFI).UpdateOne(sctx, bson.M{"key": idxDbkey}, + bson.M{"$set": bson.M{"key": idxDbkey, "value": itmMp.Slice()}}, options.Update().SetUpsert(true), ) } - return err - }); err != nil { - return err - } - } else { - // forming normal indexes - for key, itmMp := range indexes { - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - var idxDbkey string - idxDbkey = utils.ConcatenatedKey(dbKey, key) - if len(itmMp) == 0 { // remove from DB if we set it with empty indexes - _, err = ms.getCol(ColRFI).DeleteOne(sctx, - bson.M{"key": idxDbkey}) - } else { - _, err = ms.getCol(ColRFI).UpdateOne(sctx, bson.M{"key": idxDbkey}, - bson.M{"$set": bson.M{"key": idxDbkey, "value": itmMp.Slice()}}, - options.Update().SetUpsert(true), - ) - } - return err - }); err != nil { - lastErr = err - } - } + return queryErr + }) } - return lastErr } + return err } -func (ms *MongoStorage) RemoveFilterIndexesDrv(cacheID, itemIDPrefix string) (err error) { +func (ms *MongoStorage) RemoveFilterIndexesDrv(cacheID, itemIDPrefix string) error { regexKey := utils.CacheInstanceToPrefix[cacheID] + itemIDPrefix for _, character := range []string{".", "*"} { regexKey = strings.Replace(regexKey, character, `\`+character, strings.Count(regexKey, character)) @@ -1774,48 +1730,45 @@ func (ms *MongoStorage) RemoveFilterIndexesDrv(cacheID, itemIDPrefix string) (er } func (ms *MongoStorage) MatchFilterIndexDrv(cacheID, itemIDPrefix, - filterType, fldName, fldVal string) (itemIDs utils.StringMap, err error) { + filterType, fldName, fldVal string, +) (utils.StringMap, error) { var result struct { Key string Value []string } dbKey := utils.CacheInstanceToPrefix[cacheID] + itemIDPrefix - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColRFI).FindOne(sctx, bson.M{"key": utils.ConcatenatedKey(dbKey, filterType, fldName, fldVal)}) - if err := cur.Decode(&result); err != nil { - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColRFI).FindOne(sctx, bson.M{"key": utils.ConcatenatedKey(dbKey, filterType, fldName, fldVal)}) + decodeErr := sr.Decode(&result) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil - }); err != nil { + return decodeErr + }) + if err != nil { return nil, err } return utils.StringMapFromSlice(result.Value), nil } -// GetStatQueueProfileDrv retrieves a StatQueueProfile from dataDB -func (ms *MongoStorage) GetStatQueueProfileDrv(tenant string, id string) (sq *StatQueueProfile, err error) { - sq = new(StatQueueProfile) - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColSqp).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) - if err := cur.Decode(sq); err != nil { - sq = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err +// GetStatQueueProfileDrv retrieves a StatQueueProfile from the dataDB based on the specified tenant and ID. +func (ms *MongoStorage) GetStatQueueProfileDrv(tenant, id string) (*StatQueueProfile, error) { + sqProfile := new(StatQueueProfile) + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColSqp).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) + decodeErr := sr.Decode(sqProfile) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil + return decodeErr }) - return + return sqProfile, err } -// SetStatQueueProfileDrv stores a StatsQueue into DataDB -func (ms *MongoStorage) SetStatQueueProfileDrv(sq *StatQueueProfile) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColSqp).UpdateOne(sctx, bson.M{"tenant": sq.Tenant, "id": sq.ID}, +// SetStatQueueProfileDrv stores a StatQueueProfile into the DataDB. +func (ms *MongoStorage) SetStatQueueProfileDrv(sq *StatQueueProfile) error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColSqp).UpdateOne(sctx, bson.M{"tenant": sq.Tenant, "id": sq.ID}, bson.M{"$set": sq}, options.Update().SetUpsert(true), ) @@ -1823,9 +1776,9 @@ func (ms *MongoStorage) SetStatQueueProfileDrv(sq *StatQueueProfile) (err error) }) } -// RemStatQueueProfileDrv removes a StatsQueue from dataDB -func (ms *MongoStorage) RemStatQueueProfileDrv(tenant, id string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { +// RemStatQueueProfileDrv removes a StatQueueProfile from the dataDB based on the specified tenant and ID. +func (ms *MongoStorage) RemStatQueueProfileDrv(tenant, id string) error { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColSqp).DeleteOne(sctx, bson.M{"tenant": tenant, "id": id}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -1834,30 +1787,27 @@ func (ms *MongoStorage) RemStatQueueProfileDrv(tenant, id string) (err error) { }) } -// GetStatQueueDrv retrieves a StoredStatQueue -func (ms *MongoStorage) GetStatQueueDrv(tenant, id string) (sq *StatQueue, err error) { +// GetStatQueueDrv retrieves a StoredStatQueue from the dataDB based on the specified tenant and ID. +func (ms *MongoStorage) GetStatQueueDrv(tenant, id string) (*StatQueue, error) { ssq := new(StoredStatQueue) - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColSqs).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) - if err := cur.Decode(ssq); err != nil { - sq = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColSqs).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) + decodeErr := sr.Decode(ssq) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil - }); err != nil { - return + return decodeErr + }) + if err != nil { + return nil, err } - sq, err = ssq.AsStatQueue(ms.ms) - return + return ssq.AsStatQueue(ms.ms) } -// SetStatQueueDrv stores the metrics for a StoredStatQueue -func (ms *MongoStorage) SetStatQueueDrv(ssq *StoredStatQueue, sq *StatQueue) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColSqs).UpdateOne(sctx, bson.M{"tenant": ssq.Tenant, "id": ssq.ID}, +// SetStatQueueDrv stores the metrics for a StoredStatQueue into the dataDB. +func (ms *MongoStorage) SetStatQueueDrv(ssq *StoredStatQueue, _ *StatQueue) error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColSqs).UpdateOne(sctx, bson.M{"tenant": ssq.Tenant, "id": ssq.ID}, bson.M{"$set": ssq}, options.Update().SetUpsert(true), ) @@ -1865,9 +1815,10 @@ func (ms *MongoStorage) SetStatQueueDrv(ssq *StoredStatQueue, sq *StatQueue) (er }) } -// RemStatQueueDrv removes stored metrics for a StoredStatQueue -func (ms *MongoStorage) RemStatQueueDrv(tenant, id string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { +// RemStatQueueDrv removes stored metrics for a StoredStatQueue from the dataDB based +// on the specified tenant and ID. +func (ms *MongoStorage) RemStatQueueDrv(tenant, id string) error { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColSqs).DeleteOne(sctx, bson.M{"tenant": tenant, "id": id}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -1876,36 +1827,33 @@ func (ms *MongoStorage) RemStatQueueDrv(tenant, id string) (err error) { }) } -// GetThresholdProfileDrv retrieves a ThresholdProfile from dataDB -func (ms *MongoStorage) GetThresholdProfileDrv(tenant, ID string) (tp *ThresholdProfile, err error) { - tp = new(ThresholdProfile) - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColTps).FindOne(sctx, bson.M{"tenant": tenant, "id": ID}) - if err := cur.Decode(tp); err != nil { - tp = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err +// GetThresholdProfileDrv retrieves a ThresholdProfile from the dataDB based on the specified tenant and ID. +func (ms *MongoStorage) GetThresholdProfileDrv(tenant, id string) (*ThresholdProfile, error) { + thProfile := new(ThresholdProfile) + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColTps).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) + decodeErr := sr.Decode(thProfile) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil + return decodeErr }) - return + return thProfile, err } -// SetThresholdProfileDrv stores a ThresholdProfile into DataDB -func (ms *MongoStorage) SetThresholdProfileDrv(tp *ThresholdProfile) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColTps).UpdateOne(sctx, bson.M{"tenant": tp.Tenant, "id": tp.ID}, +// SetThresholdProfileDrv stores a ThresholdProfile into the DataDB. +func (ms *MongoStorage) SetThresholdProfileDrv(tp *ThresholdProfile) error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColTps).UpdateOne(sctx, bson.M{"tenant": tp.Tenant, "id": tp.ID}, bson.M{"$set": tp}, options.Update().SetUpsert(true), ) return err }) } -// RemoveThresholdProfile removes a ThresholdProfile from dataDB/cache -func (ms *MongoStorage) RemThresholdProfileDrv(tenant, id string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { +// RemThresholdProfileDrv removes a ThresholdProfile from the dataDB based on the specified tenant and ID. +func (ms *MongoStorage) RemThresholdProfileDrv(tenant, id string) error { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColTps).DeleteOne(sctx, bson.M{"tenant": tenant, "id": id}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -1914,25 +1862,22 @@ func (ms *MongoStorage) RemThresholdProfileDrv(tenant, id string) (err error) { }) } -func (ms *MongoStorage) GetThresholdDrv(tenant, id string) (r *Threshold, err error) { - r = new(Threshold) - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColThs).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) - if err := cur.Decode(r); err != nil { - r = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err +func (ms *MongoStorage) GetThresholdDrv(tenant, id string) (*Threshold, error) { + th := new(Threshold) + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColThs).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) + decodeErr := sr.Decode(th) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil + return decodeErr }) - return + return th, err } -func (ms *MongoStorage) SetThresholdDrv(r *Threshold) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColThs).UpdateOne(sctx, bson.M{"tenant": r.Tenant, "id": r.ID}, +func (ms *MongoStorage) SetThresholdDrv(r *Threshold) error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColThs).UpdateOne(sctx, bson.M{"tenant": r.Tenant, "id": r.ID}, bson.M{"$set": r}, options.Update().SetUpsert(true), ) @@ -1940,8 +1885,8 @@ func (ms *MongoStorage) SetThresholdDrv(r *Threshold) (err error) { }) } -func (ms *MongoStorage) RemoveThresholdDrv(tenant, id string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { +func (ms *MongoStorage) RemoveThresholdDrv(tenant, id string) error { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColThs).DeleteOne(sctx, bson.M{"tenant": tenant, "id": id}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -1950,26 +1895,25 @@ func (ms *MongoStorage) RemoveThresholdDrv(tenant, id string) (err error) { }) } -func (ms *MongoStorage) GetFilterDrv(tenant, id string) (r *Filter, err error) { - r = new(Filter) - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColFlt).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) - if err := cur.Decode(r); err != nil { - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err +func (ms *MongoStorage) GetFilterDrv(tenant, id string) (*Filter, error) { + fltr := new(Filter) + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColFlt).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) + decodeErr := sr.Decode(fltr) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil - }); err != nil { + return decodeErr + }) + if err != nil { return nil, err } - return + return fltr, err } -func (ms *MongoStorage) SetFilterDrv(r *Filter) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColFlt).UpdateOne(sctx, bson.M{"tenant": r.Tenant, "id": r.ID}, +func (ms *MongoStorage) SetFilterDrv(r *Filter) error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColFlt).UpdateOne(sctx, bson.M{"tenant": r.Tenant, "id": r.ID}, bson.M{"$set": r}, options.Update().SetUpsert(true), ) @@ -1977,8 +1921,8 @@ func (ms *MongoStorage) SetFilterDrv(r *Filter) (err error) { }) } -func (ms *MongoStorage) RemoveFilterDrv(tenant, id string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { +func (ms *MongoStorage) RemoveFilterDrv(tenant, id string) error { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColFlt).DeleteOne(sctx, bson.M{"tenant": tenant, "id": id}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -1987,25 +1931,22 @@ func (ms *MongoStorage) RemoveFilterDrv(tenant, id string) (err error) { }) } -func (ms *MongoStorage) GetSupplierProfileDrv(tenant, id string) (r *SupplierProfile, err error) { - r = new(SupplierProfile) - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColSpp).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) - if err := cur.Decode(r); err != nil { - r = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err +func (ms *MongoStorage) GetSupplierProfileDrv(tenant, id string) (*SupplierProfile, error) { + supplierProfile := new(SupplierProfile) + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColSpp).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) + decodeErr := sr.Decode(supplierProfile) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil + return decodeErr }) - return + return supplierProfile, err } -func (ms *MongoStorage) SetSupplierProfileDrv(r *SupplierProfile) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColSpp).UpdateOne(sctx, bson.M{"tenant": r.Tenant, "id": r.ID}, +func (ms *MongoStorage) SetSupplierProfileDrv(r *SupplierProfile) error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColSpp).UpdateOne(sctx, bson.M{"tenant": r.Tenant, "id": r.ID}, bson.M{"$set": r}, options.Update().SetUpsert(true), ) @@ -2013,8 +1954,8 @@ func (ms *MongoStorage) SetSupplierProfileDrv(r *SupplierProfile) (err error) { }) } -func (ms *MongoStorage) RemoveSupplierProfileDrv(tenant, id string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { +func (ms *MongoStorage) RemoveSupplierProfileDrv(tenant, id string) error { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColSpp).DeleteOne(sctx, bson.M{"tenant": tenant, "id": id}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -2023,25 +1964,22 @@ func (ms *MongoStorage) RemoveSupplierProfileDrv(tenant, id string) (err error) }) } -func (ms *MongoStorage) GetAttributeProfileDrv(tenant, id string) (r *AttributeProfile, err error) { - r = new(AttributeProfile) - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColAttr).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) - if err := cur.Decode(r); err != nil { - r = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err +func (ms *MongoStorage) GetAttributeProfileDrv(tenant, id string) (*AttributeProfile, error) { + attrProfile := new(AttributeProfile) + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColAttr).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) + decodeErr := sr.Decode(attrProfile) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil + return decodeErr }) - return + return attrProfile, err } -func (ms *MongoStorage) SetAttributeProfileDrv(r *AttributeProfile) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColAttr).UpdateOne(sctx, bson.M{"tenant": r.Tenant, "id": r.ID}, +func (ms *MongoStorage) SetAttributeProfileDrv(r *AttributeProfile) error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColAttr).UpdateOne(sctx, bson.M{"tenant": r.Tenant, "id": r.ID}, bson.M{"$set": r}, options.Update().SetUpsert(true), ) @@ -2049,8 +1987,8 @@ func (ms *MongoStorage) SetAttributeProfileDrv(r *AttributeProfile) (err error) }) } -func (ms *MongoStorage) RemoveAttributeProfileDrv(tenant, id string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { +func (ms *MongoStorage) RemoveAttributeProfileDrv(tenant, id string) error { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColAttr).DeleteOne(sctx, bson.M{"tenant": tenant, "id": id}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -2059,25 +1997,22 @@ func (ms *MongoStorage) RemoveAttributeProfileDrv(tenant, id string) (err error) }) } -func (ms *MongoStorage) GetChargerProfileDrv(tenant, id string) (r *ChargerProfile, err error) { - r = new(ChargerProfile) - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColCpp).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) - if err := cur.Decode(r); err != nil { - r = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err +func (ms *MongoStorage) GetChargerProfileDrv(tenant, id string) (*ChargerProfile, error) { + chargerProfile := new(ChargerProfile) + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColCpp).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) + decodeErr := sr.Decode(chargerProfile) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil + return decodeErr }) - return + return chargerProfile, err } -func (ms *MongoStorage) SetChargerProfileDrv(r *ChargerProfile) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColCpp).UpdateOne(sctx, bson.M{"tenant": r.Tenant, "id": r.ID}, +func (ms *MongoStorage) SetChargerProfileDrv(r *ChargerProfile) error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColCpp).UpdateOne(sctx, bson.M{"tenant": r.Tenant, "id": r.ID}, bson.M{"$set": r}, options.Update().SetUpsert(true), ) @@ -2085,8 +2020,8 @@ func (ms *MongoStorage) SetChargerProfileDrv(r *ChargerProfile) (err error) { }) } -func (ms *MongoStorage) RemoveChargerProfileDrv(tenant, id string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { +func (ms *MongoStorage) RemoveChargerProfileDrv(tenant, id string) error { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColCpp).DeleteOne(sctx, bson.M{"tenant": tenant, "id": id}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -2095,25 +2030,22 @@ func (ms *MongoStorage) RemoveChargerProfileDrv(tenant, id string) (err error) { }) } -func (ms *MongoStorage) GetDispatcherProfileDrv(tenant, id string) (r *DispatcherProfile, err error) { - r = new(DispatcherProfile) - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColDpp).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) - if err := cur.Decode(r); err != nil { - r = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err +func (ms *MongoStorage) GetDispatcherProfileDrv(tenant, id string) (*DispatcherProfile, error) { + dspProfile := new(DispatcherProfile) + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColDpp).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) + decodeErr := sr.Decode(dspProfile) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil + return decodeErr }) - return + return dspProfile, err } -func (ms *MongoStorage) SetDispatcherProfileDrv(r *DispatcherProfile) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColDpp).UpdateOne(sctx, bson.M{"tenant": r.Tenant, "id": r.ID}, +func (ms *MongoStorage) SetDispatcherProfileDrv(r *DispatcherProfile) error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColDpp).UpdateOne(sctx, bson.M{"tenant": r.Tenant, "id": r.ID}, bson.M{"$set": r}, options.Update().SetUpsert(true), ) @@ -2121,8 +2053,8 @@ func (ms *MongoStorage) SetDispatcherProfileDrv(r *DispatcherProfile) (err error }) } -func (ms *MongoStorage) RemoveDispatcherProfileDrv(tenant, id string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { +func (ms *MongoStorage) RemoveDispatcherProfileDrv(tenant, id string) error { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColDpp).DeleteOne(sctx, bson.M{"tenant": tenant, "id": id}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -2131,25 +2063,22 @@ func (ms *MongoStorage) RemoveDispatcherProfileDrv(tenant, id string) (err error }) } -func (ms *MongoStorage) GetDispatcherHostDrv(tenant, id string) (r *DispatcherHost, err error) { - r = new(DispatcherHost) - err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColDph).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) - if err := cur.Decode(r); err != nil { - r = nil - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err +func (ms *MongoStorage) GetDispatcherHostDrv(tenant, id string) (*DispatcherHost, error) { + dspHost := new(DispatcherHost) + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColDph).FindOne(sctx, bson.M{"tenant": tenant, "id": id}) + decodeErr := sr.Decode(dspHost) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil + return decodeErr }) - return + return dspHost, err } -func (ms *MongoStorage) SetDispatcherHostDrv(r *DispatcherHost) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColDph).UpdateOne(sctx, bson.M{"tenant": r.Tenant, "id": r.ID}, +func (ms *MongoStorage) SetDispatcherHostDrv(r *DispatcherHost) error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColDph).UpdateOne(sctx, bson.M{"tenant": r.Tenant, "id": r.ID}, bson.M{"$set": r}, options.Update().SetUpsert(true), ) @@ -2157,8 +2086,8 @@ func (ms *MongoStorage) SetDispatcherHostDrv(r *DispatcherHost) (err error) { }) } -func (ms *MongoStorage) RemoveDispatcherHostDrv(tenant, id string) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { +func (ms *MongoStorage) RemoveDispatcherHostDrv(tenant, id string) error { + return ms.query(func(sctx mongo.SessionContext) error { dr, err := ms.getCol(ColDph).DeleteOne(sctx, bson.M{"tenant": tenant, "id": id}) if dr.DeletedCount == 0 { return utils.ErrNotFound @@ -2167,43 +2096,43 @@ func (ms *MongoStorage) RemoveDispatcherHostDrv(tenant, id string) (err error) { }) } -func (ms *MongoStorage) GetItemLoadIDsDrv(itemIDPrefix string) (loadIDs map[string]int64, err error) { +func (ms *MongoStorage) GetItemLoadIDsDrv(itemIDPrefix string) (map[string]int64, error) { fop := options.FindOne() if itemIDPrefix != "" { fop.SetProjection(bson.M{itemIDPrefix: 1, "_id": 0}) } else { fop.SetProjection(bson.M{"_id": 0}) } - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColLID).FindOne(sctx, bson.D{}, fop) - if err := cur.Decode(&loadIDs); err != nil { - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err + loadIDs := make(map[string]int64) + err := ms.query(func(sctx mongo.SessionContext) error { + sr := ms.getCol(ColLID).FindOne(sctx, bson.D{}, fop) + decodeErr := sr.Decode(&loadIDs) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil - }); err != nil { + return decodeErr + }) + if err != nil { return nil, err } if len(loadIDs) == 0 { return nil, utils.ErrNotFound } - return + return loadIDs, nil } -func (ms *MongoStorage) SetLoadIDsDrv(loadIDs map[string]int64) (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColLID).UpdateOne(sctx, bson.D{}, bson.M{"$set": loadIDs}, +func (ms *MongoStorage) SetLoadIDsDrv(loadIDs map[string]int64) error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColLID).UpdateOne(sctx, bson.D{}, bson.M{"$set": loadIDs}, options.Update().SetUpsert(true), ) return err }) } -func (ms *MongoStorage) RemoveLoadIDsDrv() (err error) { - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColLID).DeleteMany(sctx, bson.M{}) +func (ms *MongoStorage) RemoveLoadIDsDrv() error { + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColLID).DeleteMany(sctx, bson.M{}) return err }) } diff --git a/engine/storage_mongo_stordb.go b/engine/storage_mongo_stordb.go index 868e9f2fe..db4b825e1 100644 --- a/engine/storage_mongo_stordb.go +++ b/engine/storage_mongo_stordb.go @@ -20,6 +20,7 @@ package engine import ( "context" + "errors" "fmt" "regexp" "strings" @@ -82,7 +83,8 @@ func (ms *MongoStorage) GetTpIds(colName string) (tpids []string, err error) { } func (ms *MongoStorage) GetTpTableIds(tpid, table string, distinctIDs utils.TPDistinctIds, - filter map[string]string, pag *utils.PaginatorWithSearch) ([]string, error) { + filter map[string]string, pag *utils.PaginatorWithSearch, +) ([]string, error) { findMap := bson.M{} if tpid != "" { findMap["tpid"] = tpid @@ -129,18 +131,17 @@ func (ms *MongoStorage) GetTpTableIds(tpid, table string, distinctIDs utils.TPDi fop.SetProjection(selectors) distinctIds := make(utils.StringMap) - if err := ms.query(func(sctx mongo.SessionContext) (err error) { - cur, err := ms.getCol(table).Find(sctx, findMap, fop) - if err != nil { - return err + err := ms.query(func(sctx mongo.SessionContext) error { + cur, queryErr := ms.getCol(table).Find(sctx, findMap, fop) + if queryErr != nil { + return queryErr } for cur.Next(sctx) { - var elem bson.D - err := cur.Decode(&elem) - if err != nil { - return err + var item bson.M + queryErr = cur.Decode(&item) + if queryErr != nil { + return queryErr } - item := elem.Map() var id string last := len(distinctIDs) - 1 @@ -155,7 +156,8 @@ func (ms *MongoStorage) GetTpTableIds(tpid, table string, distinctIDs utils.TPDi distinctIds[id] = true } return cur.Close(sctx) - }); err != nil { + }) + if err != nil { return nil, err } return distinctIds.Slice(), nil @@ -220,29 +222,32 @@ func (ms *MongoStorage) GetTPRates(tpid, id string) ([]*utils.TPRate, error) { if id != "" { filter["id"] = id } - var results []*utils.TPRate - err := ms.query(func(sctx mongo.SessionContext) (err error) { - cur, err := ms.getCol(utils.TBLTPRates).Find(sctx, filter) - if err != nil { - return err + var tpRates []*utils.TPRate + err := ms.query(func(sctx mongo.SessionContext) error { + cur, queryErr := ms.getCol(utils.TBLTPRates).Find(sctx, filter) + if queryErr != nil { + return queryErr } for cur.Next(sctx) { var el utils.TPRate - err := cur.Decode(&el) - if err != nil { - return err + queryErr = cur.Decode(&el) + if queryErr != nil { + return queryErr } for _, rs := range el.RateSlots { - rs.SetDurations() + queryErr = rs.SetDurations() + if queryErr != nil { + return queryErr + } } - results = append(results, &el) + tpRates = append(tpRates, &el) } - if len(results) == 0 { + if len(tpRates) == 0 { return utils.ErrNotFound } return cur.Close(sctx) }) - return results, err + return tpRates, err } func (ms *MongoStorage) GetTPDestinationRates(tpid, id string, pag *utils.Paginator) ([]*utils.TPDestinationRate, error) { @@ -559,7 +564,7 @@ func (ms *MongoStorage) GetTPAccountActions(tp *utils.TPAccountActions) ([]*util } func (ms *MongoStorage) RemTpData(table, tpid string, args map[string]string) error { - if len(table) == 0 { // Remove tpid out of all tables + if table == "" { // Remove tpid out of all tables return ms.query(func(sctx mongo.SessionContext) error { col, err := ms.DB().ListCollections(sctx, bson.D{}, options.ListCollections().SetNameOnly(true)) if err != nil { @@ -644,7 +649,7 @@ func (ms *MongoStorage) SetTPRates(tps []*utils.TPRate) error { m := make(map[string]bool) return ms.query(func(sctx mongo.SessionContext) (err error) { for _, tp := range tps { - if found, _ := m[tp.ID]; !found { + if found := m[tp.ID]; !found { m[tp.ID] = true _, err := ms.getCol(utils.TBLTPRates).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}) if err != nil { @@ -667,7 +672,7 @@ func (ms *MongoStorage) SetTPDestinationRates(tps []*utils.TPDestinationRate) er m := make(map[string]bool) return ms.query(func(sctx mongo.SessionContext) (err error) { for _, tp := range tps { - if found, _ := m[tp.ID]; !found { + if found := m[tp.ID]; !found { m[tp.ID] = true _, err := ms.getCol(utils.TBLTPDestinationRates).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}) if err != nil { @@ -690,7 +695,7 @@ func (ms *MongoStorage) SetTPRatingPlans(tps []*utils.TPRatingPlan) error { m := make(map[string]bool) return ms.query(func(sctx mongo.SessionContext) (err error) { for _, tp := range tps { - if found, _ := m[tp.ID]; !found { + if found := m[tp.ID]; !found { m[tp.ID] = true _, err := ms.getCol(utils.TBLTPRatingPlans).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}) if err != nil { @@ -734,7 +739,7 @@ func (ms *MongoStorage) SetTPSharedGroups(tps []*utils.TPSharedGroups) error { m := make(map[string]bool) return ms.query(func(sctx mongo.SessionContext) (err error) { for _, tp := range tps { - if found, _ := m[tp.ID]; !found { + if found := m[tp.ID]; !found { m[tp.ID] = true _, err := ms.getCol(utils.TBLTPSharedGroups).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}) if err != nil { @@ -757,7 +762,7 @@ func (ms *MongoStorage) SetTPActions(tps []*utils.TPActions) error { m := make(map[string]bool) return ms.query(func(sctx mongo.SessionContext) (err error) { for _, tp := range tps { - if found, _ := m[tp.ID]; !found { + if found := m[tp.ID]; !found { m[tp.ID] = true if _, err := ms.getCol(utils.TBLTPActions).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}); err != nil { return err @@ -778,7 +783,7 @@ func (ms *MongoStorage) SetTPActionPlans(tps []*utils.TPActionPlan) error { m := make(map[string]bool) return ms.query(func(sctx mongo.SessionContext) (err error) { for _, tp := range tps { - if found, _ := m[tp.ID]; !found { + if found := m[tp.ID]; !found { m[tp.ID] = true if _, err := ms.getCol(utils.TBLTPActionPlans).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}); err != nil { return err @@ -799,7 +804,7 @@ func (ms *MongoStorage) SetTPActionTriggers(tps []*utils.TPActionTriggers) error m := make(map[string]bool) return ms.query(func(sctx mongo.SessionContext) (err error) { for _, tp := range tps { - if found, _ := m[tp.ID]; !found { + if found := m[tp.ID]; !found { m[tp.ID] = true if _, err := ms.getCol(utils.TBLTPActionTriggers).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}); err != nil { return err @@ -993,22 +998,21 @@ func (ms *MongoStorage) cleanEmptyFilters(filters bson.M) { } } -// _, err := col(ColCDRs).UpdateAll(bson.M{CGRIDLow: bson.M{"$in": cgrIds}}, bson.M{"$set": bson.M{"deleted_at": time.Now()}}) -func (ms *MongoStorage) GetCDRs(qryFltr *utils.CDRsFilter, remove bool) ([]*CDR, int64, error) { +func (ms *MongoStorage) GetCDRs(qryFltr *utils.CDRsFilter, remove bool) (cdrs []*CDR, n int64, err error) { var minUsage, maxUsage *time.Duration - if len(qryFltr.MinUsage) != 0 { - if parsed, err := utils.ParseDurationWithNanosecs(qryFltr.MinUsage); err != nil { + if qryFltr.MinUsage != "" { + parsedDur, err := utils.ParseDurationWithNanosecs(qryFltr.MinUsage) + if err != nil { return nil, 0, err - } else { - minUsage = &parsed } + minUsage = &parsedDur } - if len(qryFltr.MaxUsage) != 0 { - if parsed, err := utils.ParseDurationWithNanosecs(qryFltr.MaxUsage); err != nil { + if qryFltr.MaxUsage != "" { + parsedDur, err := utils.ParseDurationWithNanosecs(qryFltr.MaxUsage) + if err != nil { return nil, 0, err - } else { - maxUsage = &parsed } + maxUsage = &parsedDur } filters := bson.M{ CGRIDLow: bson.M{"$in": qryFltr.CGRIDs, "$nin": qryFltr.NotCGRIDs}, @@ -1028,20 +1032,20 @@ func (ms *MongoStorage) GetCDRs(qryFltr *utils.CDRsFilter, remove bool) ([]*CDR, CreatedAtLow: bson.M{"$gte": qryFltr.CreatedAtStart, "$lt": qryFltr.CreatedAtEnd}, UpdatedAtLow: bson.M{"$gte": qryFltr.UpdatedAtStart, "$lt": qryFltr.UpdatedAtEnd}, UsageLow: bson.M{"$gte": minUsage, "$lt": maxUsage}, - //CostDetailsLow + "." + AccountLow: bson.M{"$in": qryFltr.RatedAccounts, "$nin": qryFltr.NotRatedAccounts}, - //CostDetailsLow + "." + SubjectLow: bson.M{"$in": qryFltr.RatedSubjects, "$nin": qryFltr.NotRatedSubjects}, + // CostDetailsLow + "." + AccountLow: bson.M{"$in": qryFltr.RatedAccounts, "$nin": qryFltr.NotRatedAccounts}, + // CostDetailsLow + "." + SubjectLow: bson.M{"$in": qryFltr.RatedSubjects, "$nin": qryFltr.NotRatedSubjects}, } - //file, _ := os.CreateTemp(os.TempDir(), "debug") - //file.WriteString(fmt.Sprintf("FILTER: %v\n", utils.ToIJSON(qryFltr))) - //file.WriteString(fmt.Sprintf("BEFORE: %v\n", utils.ToIJSON(filters))) + // file, _ := os.CreateTemp(os.TempDir(), "debug") + // file.WriteString(fmt.Sprintf("FILTER: %v\n", utils.ToIJSON(qryFltr))) + // file.WriteString(fmt.Sprintf("BEFORE: %v\n", utils.ToIJSON(filters))) ms.cleanEmptyFilters(filters) if len(qryFltr.DestinationPrefixes) != 0 { var regexpRule string for _, prefix := range qryFltr.DestinationPrefixes { - if len(prefix) == 0 { + if prefix == "" { continue } - if len(regexpRule) != 0 { + if regexpRule != "" { regexpRule += "|" } regexpRule += "^(" + regexp.QuoteMeta(prefix) + ")" @@ -1063,7 +1067,7 @@ func (ms *MongoStorage) GetCDRs(qryFltr *utils.CDRsFilter, remove bool) ([]*CDR, filters["$and"] = make([]bson.M, 0) } for _, prefix := range qryFltr.NotDestinationPrefixes { - if len(prefix) == 0 { + if prefix == "" { continue } filters["$and"] = append(filters["$and"].([]bson.M), @@ -1117,17 +1121,17 @@ func (ms *MongoStorage) GetCDRs(qryFltr *utils.CDRsFilter, remove bool) ([]*CDR, filters[CostLow] = bson.M{"$lt": *qryFltr.MaxCost} } } - //file.WriteString(fmt.Sprintf("AFTER: %v\n", utils.ToIJSON(filters))) - //file.Close() + // file.WriteString(fmt.Sprintf("AFTER: %v\n", utils.ToIJSON(filters))) + // file.Close() if remove { var chgd int64 - err := ms.query(func(sctx mongo.SessionContext) (err error) { - dr, err := ms.getCol(ColCDRs).DeleteMany(sctx, filters) - if err != nil { - return err + err = ms.query(func(sctx mongo.SessionContext) (queryErr error) { + dr, queryErr := ms.getCol(ColCDRs).DeleteMany(sctx, filters) + if queryErr != nil { + return queryErr } chgd = dr.DeletedCount - return err + return queryErr }) return nil, chgd, err } @@ -1148,7 +1152,6 @@ func (ms *MongoStorage) GetCDRs(qryFltr *utils.CDRsFilter, remove bool) ([]*CDR, ordVal := 1 if len(separateVals) == 2 && separateVals[1] == "desc" { ordVal = -1 - // orderVal += "-" } switch separateVals[0] { case utils.OrderID: @@ -1162,26 +1165,27 @@ func (ms *MongoStorage) GetCDRs(qryFltr *utils.CDRsFilter, remove bool) ([]*CDR, case utils.Cost: orderVal += "cost" default: - return nil, 0, fmt.Errorf("Invalid value : %s", separateVals[0]) + return nil, 0, fmt.Errorf("invalid value : %s", separateVals[0]) } fop = fop.SetSort(bson.M{orderVal: ordVal}) } if qryFltr.Count { var cnt int64 - if err := ms.query(func(sctx mongo.SessionContext) (err error) { - cnt, err = ms.getCol(ColCDRs).CountDocuments(sctx, filters, cop) - return err - }); err != nil { + err = ms.query(func(sctx mongo.SessionContext) error { + var queryErr error + cnt, queryErr = ms.getCol(ColCDRs).CountDocuments(sctx, filters, cop) + return queryErr + }) + if err != nil { return nil, 0, err } return nil, cnt, nil } // Execute query - var cdrs []*CDR - err := ms.query(func(sctx mongo.SessionContext) (err error) { - cur, err := ms.getCol(ColCDRs).Find(sctx, filters, fop) - if err != nil { - return err + err = ms.query(func(sctx mongo.SessionContext) error { + cur, queryErr := ms.getCol(ColCDRs).Find(sctx, filters, fop) + if queryErr != nil { + return queryErr } for cur.Next(sctx) { cdr := CDR{} @@ -1555,37 +1559,40 @@ func (ms *MongoStorage) SetTPDispatcherHosts(tpDPPs []*utils.TPDispatcherHost) ( }) } -func (ms *MongoStorage) GetVersions(itm string) (vrs Versions, err error) { +func (ms *MongoStorage) GetVersions(itm string) (Versions, error) { fop := options.FindOne() if itm != "" { fop.SetProjection(bson.M{itm: 1, "_id": 0}) } else { fop.SetProjection(bson.M{"_id": 0}) } - if err = ms.query(func(sctx mongo.SessionContext) (err error) { - cur := ms.getCol(ColVer).FindOne(sctx, bson.D{}, fop) - if err := cur.Decode(&vrs); err != nil { - if err == mongo.ErrNoDocuments { - return utils.ErrNotFound - } - return err + var vrs Versions + err := ms.query(func(sctx mongo.SessionContext) (err error) { + sr := ms.getCol(ColVer).FindOne(sctx, bson.D{}, fop) + decodeErr := sr.Decode(&vrs) + if errors.Is(decodeErr, mongo.ErrNoDocuments) { + return utils.ErrNotFound } - return nil - }); err != nil { + return decodeErr + }) + if err != nil { return nil, err } if len(vrs) == 0 { return nil, utils.ErrNotFound } - return + return vrs, nil } -func (ms *MongoStorage) SetVersions(vrs Versions, overwrite bool) (err error) { +func (ms *MongoStorage) SetVersions(vrs Versions, overwrite bool) error { if overwrite { - ms.RemoveVersions(nil) + err := ms.RemoveVersions(nil) + if err != nil && !errors.Is(err, utils.ErrNotFound) { + return err + } } - return ms.query(func(sctx mongo.SessionContext) (err error) { - _, err = ms.getCol(ColVer).UpdateOne(sctx, bson.D{}, bson.M{"$set": vrs}, + return ms.query(func(sctx mongo.SessionContext) error { + _, err := ms.getCol(ColVer).UpdateOne(sctx, bson.D{}, bson.M{"$set": vrs}, options.Update().SetUpsert(true), ) return err