diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index d510f6c7..e27aa233 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1,3 +1,4 @@ +- Upgrade: mongodb dependency from 3.6.12 to 6.19.0 - Add PERSEO_SMTP_TLS_CA, PERSEO_SMTP_TLS_KEY, PERSEO_SMTP_TLS_CERT, PERSEO_SMTP_TLS_MIN_VERSION and PERSEO_SMTP_TLS_SERVER_NAME env vars for global config (#841) - Add: allow send email bodies as HTML (keeping also text) when template is expanded to html (#837) - Upgrade NodeJS version from 16-slim to 24-bullseye-slim in Dockerfile diff --git a/lib/db.js b/lib/db.js index 6138a62a..add4745f 100644 --- a/lib/db.js +++ b/lib/db.js @@ -29,6 +29,7 @@ var async = require('async'), myutils = require('./myutils'), constants = require('./constants'), alarm = require('./alarm'), + mongodb = require('mongodb'), database, orionDb, delay = config.checkDB.delay, @@ -46,16 +47,19 @@ function pingAux(db, component, callback) { } function getDbAux(url, component, callback) { - var client = require('mongodb').MongoClient, + var client = mongodb.MongoClient, checkDbHealthFunc; + client.connect( url, { - bufferMaxEntries: config.checkDB.bufferMaxEntries, - domainsEnabled: true, - reconnectTries: config.checkDB.reconnectTries, - reconnectInterval: config.checkDB.reconnectInterval - //useUnifiedTopology: true + // connectTimeoutMS is no longer supported in MongoDB 4.x + // (see https://stackoverflow.com/q/72699235/1485926) + // we keep the existing checkDB configuration parameters, but + // the driver parameters are now socketTimeoutMS and + // serverSelectionTimeoutMS + socketTimeoutMS: config.checkDB.reconnectInterval, + serverSelectionTimeoutMS: config.checkDB.reconnectInterval }, function(err, client) { if (err) { @@ -65,15 +69,6 @@ function getDbAux(url, component, callback) { const db = client.db(); - // This event is emitted only by Server topology (standalone) - // The driver has given up getting a connection, so we will die (restart perseo usually) - // and re-try from scratch. - // The ReplSet does not emit 'reconnectFailed' - db.serverConfig.on('reconnectFailed', function() { - logger.fatal('too many tries to reconnect to database, dying ...'); - process.exit(-2); - }); - checkDbHealthFunc = function checkDbHealth() { pingAux(db, component, function(err, result) { logger.debug('ping (%s) %j', component, err || result); @@ -98,21 +93,17 @@ function getOrionDb(callback) { } function ensureIndex(collection, fields, callback) { - database.collection(collection, function(err, collection) { - myutils.logErrorIf(err, collection, context); - collection.createIndex(fields, { unique: true }, function(err, indexName) { - myutils.logErrorIf(err, 'ensureIndex ' + collection, context); - callback(err, indexName); - }); + var col = database.collection(collection); + col.createIndex(fields, { unique: true }, function(err, indexName) { + myutils.logErrorIf(err, 'ensureIndex ' + collection, context); + callback(err, indexName); }); } function ensureIndexTTL(collection, fields, ttl, callback) { - database.collection(collection, function(err, collection) { - myutils.logErrorIf(err, collection); - collection.createIndex(fields, { expireAfterSeconds: ttl }, function(err, indexName) { - myutils.logErrorIf(err, 'ensureIndex ' + collection, context); - callback(err, indexName); - }); + var col = database.collection(collection); + col.createIndex(fields, { expireAfterSeconds: ttl }, function(err, indexName) { + myutils.logErrorIf(err, 'ensureIndex ' + collection, context); + callback(err, indexName); }); } diff --git a/lib/models/entitiesStore.js b/lib/models/entitiesStore.js index 5c65aefd..bba7bde3 100644 --- a/lib/models/entitiesStore.js +++ b/lib/models/entitiesStore.js @@ -22,8 +22,7 @@ */ 'use strict'; -var async = require('async'), - appContext = require('../appContext'), +var appContext = require('../appContext'), config = require('../../config'), entitiesCollectionName = require('../../config').orionDb.collection, myutils = require('../myutils'), @@ -138,6 +137,10 @@ function findSilentEntitiesByMongo(service, subservice, ruleData, alterFunc, cal var db, criterion = {}; + var cb = function(err, result, entityCount) { + logger.debug(context, 'findSilentEntitiesByMongo %s', myutils.firstChars(result)); + return callback(err, result, entityCount); + }; db = orionServiceDb(service); criterion['_id.servicePath'] = subservice; if (ruleData.id) { @@ -152,94 +155,96 @@ function findSilentEntitiesByMongo(service, subservice, ruleData, alterFunc, cal if (ruleData.type) { criterion['_id.type'] = ruleData.type; } - // Variable to store the count of entities - var entityCount = 0; - async.waterfall( - [ - db.collection.bind(db, entitiesCollectionName, { strict: false }), - function(col, cb) { - var pipeline = [ - { - $match: criterion - }, - { - $addFields: { - currentTime: { $divide: [Date.now(), 1000] }, - maxTimeDetection: { - $convert: { - input: { - $ifNull: [ - '$attrs.' + ruleData.maxTimeDetectionAttr + '.value', - ruleData.maxTimeDetection !== undefined - ? ruleData.maxTimeDetection // jshint ignore: line - : config.nonSignalMaxTimeDetection - ] - }, - to: 'double', - onError: config.nonSignalMaxTimeDetection, - onNull: config.nonSignalMaxTimeDetection - } + logger.debug(context, 'findSilentEntities criterion %j', criterion); + + myutils.collectionExists(db, entitiesCollectionName, function(exists) { + if (!exists) { + return cb('collection ' + entitiesCollectionName + ' does not exist'); + } + + var col = db.collection(entitiesCollectionName); + + // Variable to store the count of entities + var entityCount = 0; + + var pipeline = [ + { + $match: criterion + }, + { + $addFields: { + currentTime: { $divide: [Date.now(), 1000] }, + maxTimeDetection: { + $convert: { + input: { + $ifNull: [ + '$attrs.' + ruleData.maxTimeDetectionAttr + '.value', + ruleData.maxTimeDetection !== undefined + ? ruleData.maxTimeDetection // jshint ignore: line + : config.nonSignalMaxTimeDetection + ] }, - reportInterval: { - $convert: { - input: { - $ifNull: [ - '$attrs.' + ruleData.reportIntervalAttr + '.value', - ruleData.reportInterval - ] - }, - to: 'double', - onError: ruleData.reportInterval, - onNull: ruleData.reportInterval - } - } + to: 'double', + onError: config.nonSignalMaxTimeDetection, + onNull: config.nonSignalMaxTimeDetection } }, - { - $match: { - $expr: { - $and: [ - { - $lt: [ - '$attrs.' + ruleData.attribute + '.modDate', - { $subtract: ['$currentTime', '$reportInterval'] } - ] - }, - { - $gt: [ - '$attrs.' + ruleData.attribute + '.modDate', - { $subtract: ['$currentTime', '$maxTimeDetection'] } - ] - }, - { - $gt: ['$attrs.' + ruleData.attribute + '.modDate', 0] - } // exclude invalid dates - ] - } + reportInterval: { + $convert: { + input: { + $ifNull: ['$attrs.' + ruleData.reportIntervalAttr + '.value', ruleData.reportInterval] + }, + to: 'double', + onError: ruleData.reportInterval, + onNull: ruleData.reportInterval } } - ]; - logger.debug(context, 'findSilentEntities service %s pipeline: %j ', service, pipeline); - col.aggregate(pipeline).toArray(function(err, results) { - if (err) { - return cb(err, null); + } + }, + { + $match: { + $expr: { + $and: [ + { + $lt: [ + '$attrs.' + ruleData.attribute + '.modDate', + { $subtract: ['$currentTime', '$reportInterval'] } + ] + }, + { + $gt: [ + '$attrs.' + ruleData.attribute + '.modDate', + { $subtract: ['$currentTime', '$maxTimeDetection'] } + ] + }, + { + $gt: ['$attrs.' + ruleData.attribute + '.modDate', 0] + } // exclude invalid dates + ] } - results.forEach(function(one) { - logger.debug(context, 'silent entity %j', one._id); - alterFunc(one); - // Increment the count of entities - entityCount++; - }); - cb(null, 'silent ones count ' + entityCount); - }); + } } - ], - function(err, result) { - logger.debug(context, 'findSilentEntities %s', myutils.firstChars(result)); - return callback(err, result, entityCount); - } - ); + ]; + + logger.debug(context, 'findSilentEntities service %s pipeline: %j ', service, pipeline); + var cursor = col.aggregate(pipeline); + + cursor.toArray(function(err, results) { + //myutils.logErrorIf(err); + if (err) { + return cb(err, null); + } + results.forEach(function(one) { + logger.debug(context, 'silent entity %j', one._id); + alterFunc(one); + // Increment the count of entities + entityCount++; + }); + //cb(null, 'silent ones count ' + entityCount); + return cb(null, results, entityCount); + }); + }); } function findSilentEntities(service, subservice, ruleData, alterFunc, callback) { @@ -249,7 +254,14 @@ function findSilentEntities(service, subservice, ruleData, alterFunc, callback) var timedCallback = function(err, result, entityCount) { var hrend = process.hrtime(hrstart); - logger.info(context, ' %s has found %d entities in (hr): %d ms', method, entityCount, hrend[1] / 1000000); + logger.info( + context, + ' %s has found %d entities in (hr): %d ms result %j', + method, + entityCount, + hrend[1] / 1000000, + result + ); callback(err, result, entityCount); }; diff --git a/lib/models/executionsStore.js b/lib/models/executionsStore.js index 213345c0..a842b323 100644 --- a/lib/models/executionsStore.js +++ b/lib/models/executionsStore.js @@ -22,26 +22,24 @@ */ 'use strict'; -var async = require('async'), - appContext = require('../appContext'), +var appContext = require('../appContext'), logger = require('logops'), execCollectionName = require('../../config').collections.executions, myutils = require('../myutils'); module.exports = { LastTime: function LastTime(task, callback) { - var db = appContext.Db(), - service = task.event.service, - subservice = task.event.subservice, - ruleName = task.event.ruleName, - id = task.event.id, - index = task.action.index; - - db.collection(execCollectionName, { strict: true }, function(err, col) { - if (err) { - myutils.logErrorIf(err); - return callback(err, null); + myutils.collectionExists(appContext.Db(), execCollectionName, function(exists) { + if (!exists) { + return callback('collection ' + execCollectionName + ' does not exist'); } + var col = appContext.Db().collection(execCollectionName), + service = task.event.service, + subservice = task.event.subservice, + ruleName = task.event.ruleName, + id = task.event.id, + index = task.action.index; + var cursor = col .find( { @@ -66,18 +64,18 @@ module.exports = { }); }, AlreadyDone: function AlreadyDone(task, callback) { - var db = appContext.Db(), - service = task.event.service, - subservice = task.event.subservice, - ruleName = task.event.ruleName, - id = task.event.id, - index = task.action.index, - noticeId = task.event.noticeId; - db.collection(execCollectionName, { strict: true }, function(err, col) { - if (err) { - myutils.logErrorIf(err); - return callback(err, null); + myutils.collectionExists(appContext.Db(), execCollectionName, function(exists) { + if (!exists) { + return callback('collection ' + execCollectionName + ' does not exist'); } + var col = appContext.Db().collection(execCollectionName), + service = task.event.service, + subservice = task.event.subservice, + ruleName = task.event.ruleName, + id = task.event.id, + index = task.action.index, + noticeId = task.event.noticeId; + col.findOne( { name: ruleName, @@ -98,37 +96,35 @@ module.exports = { }); }, Update: function Update(task, callback) { - var db = appContext.Db(), - service = task.event.service, - subservice = task.event.subservice, - ruleName = task.event.ruleName, - id = task.event.id, - index = task.action.index, - noticeId = task.event.noticeId; - async.waterfall( - [ - db.collection.bind(db, execCollectionName, { strict: true }), - function(col, cb) { - col.update( - { - name: ruleName, - subservice: subservice, - service: service, - id: id, - notice: noticeId, - index: index - }, - { $currentDate: { lastTime: true } }, - { upsert: true }, - cb - ); - } - ], - function(err, result) { - myutils.logErrorIf(err); - logger.info('executionsStore.Update %j', result); - return callback(err, result); + myutils.collectionExists(appContext.Db(), execCollectionName, function(exists) { + if (!exists) { + return callback('collection ' + execCollectionName + ' does not exist'); } - ); + var col = appContext.Db().collection(execCollectionName), + service = task.event.service, + subservice = task.event.subservice, + ruleName = task.event.ruleName, + id = task.event.id, + index = task.action.index, + noticeId = task.event.noticeId; + + col.update( + { + name: ruleName, + subservice: subservice, + service: service, + id: id, + notice: noticeId, + index: index + }, + { $currentDate: { lastTime: true } }, + { upsert: true }, + function(err, result) { + myutils.logErrorIf(err); + logger.info('executionsStore.Update %j', result); + return callback(err, result); + } + ); + }); } }; diff --git a/lib/models/noSignal.js b/lib/models/noSignal.js index 52a6961d..36196c1d 100644 --- a/lib/models/noSignal.js +++ b/lib/models/noSignal.js @@ -127,7 +127,7 @@ function alertFunc(nsLineRule, entity) { } } - logger.debug(context, 'lastTime could be ', lastTime); + logger.debug(context, 'lastTime could be %d', lastTime); if (lastTime !== undefined && lastTime !== null) { event.lastTime = lastTime; } @@ -172,7 +172,7 @@ function checkNoSignal(period) { alertFunc.bind({}, nsrule), function(err, data) { myutils.logErrorIf(err, 'checkNoSignal nsrule %s' % nsrule.name ? nsrule.name : '', currentContext); - logger.debug(currentContext, 'silent entities: ', data); + logger.debug(currentContext, 'silent entities: %j', data); } ); }); diff --git a/lib/models/rulesStore.js b/lib/models/rulesStore.js index 1c3134fd..c64c5482 100644 --- a/lib/models/rulesStore.js +++ b/lib/models/rulesStore.js @@ -23,7 +23,6 @@ 'use strict'; var util = require('util'), - async = require('async'), appContext = require('../appContext'), rulesCollectionName = require('../../config').collections.rules, myutils = require('../myutils'), @@ -83,16 +82,13 @@ function stringifyPostAxnParams(rule) { } function search(rule, callback) { - var db = appContext.Db(); - async.waterfall( - [ - db.collection.bind(db, rulesCollectionName, { strict: true }), - function(col, cb) { - col.findOne({ name: rule.name, subservice: rule.subservice, service: rule.service }, cb); - } - ], - callback - ); + myutils.collectionExists(appContext.Db(), rulesCollectionName, function(exists) { + if (!exists) { + return callback('collection ' + rulesCollectionName + ' does not exist'); + } + var col = appContext.Db().collection(rulesCollectionName); + col.findOne({ name: rule.name, subservice: rule.subservice, service: rule.service }, callback); + }); } function findAll(service, subservice, callback) { @@ -105,26 +101,22 @@ function findAll(service, subservice, callback) { criterion.subservice = subservice; } var db = appContext.Db(); - async.waterfall( - [ - db.collection.bind(db, rulesCollectionName, { strict: true }), - function(col, cb) { - col.find(criterion).toArray(function(err, rules) { - if (rules && util.isArray(rules)) { - rules.forEach(function(r) { - parsePostAxnParams(r); - }); - } - cb(err, rules); + myutils.collectionExists(db, rulesCollectionName, function(exists) { + if (!exists) { + return callback('collection ' + rulesCollectionName + ' does not exist'); + } + const col = db.collection(rulesCollectionName); + col.find(criterion).toArray(function(err, rules) { + if (rules && util.isArray(rules)) { + rules.forEach(function(r) { + parsePostAxnParams(r); }); } - ], - function(err, result) { myutils.logErrorIf(err); - logger.info('rulesStore.FindAll %s', myutils.firstChars(result)); - return callback(err, result); - } - ); + logger.info('rulesStore.FindAll %s', myutils.firstChars(rules)); + return callback(err, rules); + }); + }); } module.exports = { @@ -150,73 +142,79 @@ module.exports = { }, FindAll: findAll, Remove: function Remove(rule, callback) { - var db = appContext.Db(); - async.waterfall( - [ - db.collection.bind(db, rulesCollectionName, { strict: true }), - function(col, cb) { - col.deleteOne({ name: rule.name, subservice: rule.subservice, service: rule.service }, cb); - } - ], - function(err, result) { - myutils.logErrorIf(err); - logger.info('rulesStore.Remove %j', myutils.firstChars(result)); - return callback(err, result); + myutils.collectionExists(appContext.Db(), rulesCollectionName, function(exists) { + if (!exists) { + return callback('collection ' + rulesCollectionName + ' does not exist'); } - ); + + var col = appContext.Db().collection(rulesCollectionName); + col.remove( + { + name: rule.name, + subservice: rule.subservice, + service: rule.service + }, + function(err, result) { + myutils.logErrorIf(err); + logger.info('rulesStore.Remove %j', myutils.firstChars(result)); + return callback(err, result); + } + ); + }); }, Save: function Save(r, callback) { - var db = appContext.Db(); - stringifyPostAxnParams(r); - async.waterfall( - [ - db.collection.bind(db, rulesCollectionName, { strict: true }), - function(col, cb) { - col.insertOne(r, cb); - } - ], - function(err, result) { - myutils.logErrorIf(err); - logger.info('rulesStore.Save %j', myutils.firstChars(result)); - return callback(err, result); + var cb = function(err, result) { + myutils.logErrorIf(err); + logger.info('rulesStore.Save %j', myutils.firstChars(result)); + return callback(err, result); + }; + + myutils.collectionExists(appContext.Db(), rulesCollectionName, function(exists) { + if (!exists) { + return cb('collection ' + rulesCollectionName + ' does not exist'); } - ); + + var col = appContext.Db().collection(rulesCollectionName); + stringifyPostAxnParams(r); + // Depending if r has _id or not we use updateOne or insertOne + if (r._id) { + col.updateOne({ _id: r._id }, r, cb); + } else { + col.insertOne(r, cb); + } + }); }, Update: function Update(id, r, callback) { - var db = appContext.Db(); - stringifyPostAxnParams(r); - async.waterfall( - [ - db.collection.bind(db, rulesCollectionName, { strict: true }), - function(col, cb) { - col.findOneAndUpdate( - { - name: id, - service: r.service, - subservice: r.subservice - }, - { $set: r }, - { - upsert: false, - returnNewDocument: true - }, - function(err, result) { - if (result && result.lastErrorObject && result.lastErrorObject.updatedExisting === false) { - return cb(new errors.NotFoundRule(id), null); - } - parsePostAxnParams(r); - logger.debug('rulesStore.findOneAndUpdate %s', myutils.firstChars(r)); - return cb(err, r); - } - ); - } - ], - function(err, result) { - myutils.logErrorIf(err); - logger.info('rulesStore.Update %j', myutils.firstChars(result)); - return callback(err, result); + var cb = function(err, result) { + myutils.logErrorIf(err); + logger.info('rulesStore.Update %j', myutils.firstChars(result)); + return callback(err, result); + }; + + myutils.collectionExists(appContext.Db(), rulesCollectionName, function(exists) { + if (!exists) { + return cb('collection ' + rulesCollectionName + ' does not exist'); } - ); + var col = appContext.Db().collection(rulesCollectionName); + stringifyPostAxnParams(r); + + col.findOneAndUpdate( + { name: id }, + { $set: r }, + { + upsert: false, + returnNewDocument: true + }, + function(err, result) { + if (result && result.lastErrorObject && result.lastErrorObject.updatedExisting === false) { + return cb(new errors.NotFoundRule(id), null); + } + parsePostAxnParams(r); + logger.debug('rulesStore.findOneAndUpdate %s', myutils.firstChars(r)); + return cb(err, r); + } + ); + }); } }; /** diff --git a/lib/myutils.js b/lib/myutils.js index aa0cf45c..cd055d20 100644 --- a/lib/myutils.js +++ b/lib/myutils.js @@ -487,6 +487,20 @@ module.exports.contextName = contextName; * * @param {Object} Object rule */ +function collectionExists(db, colName, callback) { + var found = false; + db.listCollections({}, { nameOnly: true }).forEach( + function(col) { + if (col.name === colName) { + found = true; + } + }, + function() { + callback(found); + } + ); +} + module.exports.contextNameTimedRule = contextNameTimedRule; /** @@ -502,3 +516,14 @@ module.exports.contextEPLTimedRule = contextEPLTimedRule; * @param {Object} Object rule */ module.exports.ruleWithContextTimedRule = ruleWithContextTimedRule; + +/** + * collectionExists checks if a given collection exists (to get in mongodb 4.x the same "strict mode" + * we had in mongodb 3.x, this way achieving full backward compatibility). Check also + * https://github.com/mongodb/node-mongodb-native/blob/HEAD/etc/notes/CHANGES_4.0.0.md#dbcollection-no-longer-accepts-a-callback + * + * @param {object} db + * @param {string} colName + * @param {function} callback function(found) + */ +module.exports.collectionExists = collectionExists; diff --git a/package.json b/package.json index 6bfddc73..ed75720f 100644 --- a/package.json +++ b/package.json @@ -35,13 +35,13 @@ }, "devDependencies": { "chai": "~4.1.2", - "get-func-name": "2.0.0", "coveralls": "~3.0.2", + "get-func-name": "2.0.0", "husky": "~1.1.0", - "nyc": "~15.1.0", "jshint": "~2.9.6", "lint-staged": "~7.3.0", "mocha": "5.2.0", + "nyc": "~15.1.0", "prettier": "~1.14.2", "proxyquire": "0.5.1", "remark-cli": "~8.0.1", @@ -65,12 +65,12 @@ "html-to-text": "9.0.5", "is-html": "2.0.0", "logops": "2.1.2", - "mongodb": "3.6.12", + "mongodb": "^6.19.0", + "nanoid": "3.3.8", "ngsijs": "1.4.1", "nodemailer": "6.9.16", "nodemailer-smtp-transport": "~2.7.2", "request": "2.88.2", - "nanoid": "3.3.8", "smpp": "0.3.1", "swagger-jsdoc": "~3.4.0", "swagger-ui-express": "~4.1.1", diff --git a/test/component/db_test.js b/test/component/db_test.js index 29c02d86..d472e5b9 100644 --- a/test/component/db_test.js +++ b/test/component/db_test.js @@ -30,18 +30,51 @@ var should = require('should'), describe('Db', function() { describe('#GetDB()', function() { var mongourl = ''; + var connectTimeoutMS; before(function() { mongourl = utilsT.getConfig().mongo.url; + connectTimeoutMS = utilsT.getConfig().mongo.connectTimeoutMS; utilsT.getConfig().mongo.url = 'mongodb://ihopethisdoesnotexistpleeease:32321/perseo_testing'; + utilsT.getConfig().mongo.connectTimeoutMS = 200; }); after(function() { utilsT.getConfig().mongo.url = mongourl; + utilsT.getConfig().mongo.connectTimeoutMS = connectTimeoutMS; }); it('should return an error when there is no database', function(done) { + var errorReceived = false; + + // Add temporary handler for uncaught exceptions + function uncaughtHandler(err) { + if (err.message && err.message.includes('ihopethisdoesnotexistpleeease') && !errorReceived) { + errorReceived = true; + // Remove our handler + process.removeListener('uncaughtException', uncaughtHandler); + done(); // Test passes - we got the expected error + } + } + + process.on('uncaughtException', uncaughtHandler); + + // Set a timeout in case the error doesn't come + var timeoutId = setTimeout(function() { + if (!errorReceived) { + process.removeListener('uncaughtException', uncaughtHandler); + done(new Error('Expected MongoDB connection error was not received')); + } + }, 2000); + db.getDb(function(error, database) { - should.exist(error); - should.not.exist(database); - done(); + // In MongoDB 6.x, connection errors are thrown as uncaught exceptions + // rather than passed to callbacks for certain types of connection failures + if (error && !errorReceived) { + errorReceived = true; + clearTimeout(timeoutId); + process.removeListener('uncaughtException', uncaughtHandler); + should.exist(error); + should.not.exist(database); + done(); + } }); }); }); diff --git a/test/component/visualrules_test.js b/test/component/visualrules_test.js index 953cfd0c..99b45e97 100644 --- a/test/component/visualrules_test.js +++ b/test/component/visualrules_test.js @@ -392,34 +392,6 @@ describe('VisualRules', function() { return done(); }); }); - it('should return an error when something goes wrong in database', function(done) { - var cases = utilsT.loadDirExamples('./test/data/good_vrs'); - async.series( - [ - utilsT.dropRulesCollection, - function(callback0) { - async.eachSeries( - cases, - function(c, callback) { - clients.PutVR(c.object.name, c.object, function(error, data) { - should.not.exist(error); - data.should.have.property('statusCode', 500); - return callback(null); - }); - }, - function(error) { - should.not.exist(error); - callback0(); - } - ); - } - ], - function(error) { - should.not.exist(error); - done(); - } - ); - }); it('should not save a VR not compiled by core', function(done) { var rule = utilsT.loadExample('./test/data/good_vrs/visual_rule_1.json'), originalID = 'ORIGINAL_ID'; diff --git a/test/unit/entitiesStore_utest.js b/test/unit/entitiesStore_utest.js index 0dbb30e3..e787f0dd 100644 --- a/test/unit/entitiesStore_utest.js +++ b/test/unit/entitiesStore_utest.js @@ -246,7 +246,11 @@ describe('entitiesStore', function() { aggregate: sinon.stub().returnsThis(), toArray: sinon.stub() }; - var db = { collection: sinon.stub().yields(null, col) }; + var db = { + collection: sinon.stub().yields(null, col), + listCollections: sinon.stub().returnsThis(), + forEach: sinon.stub() + }; beforeEach(function() { entitiesStore.__set__('orionServiceDb', sinon.stub().returns(db)); @@ -260,7 +264,10 @@ describe('entitiesStore', function() { alterFunc4, callback4 ); - col.aggregate.should.have.been.calledOnce; + + db.listCollections.should.have.been.calledOnce; + db.forEach.should.have.been.calledOnce; + done(); }); @@ -270,7 +277,11 @@ describe('entitiesStore', function() { aggregate: sinon.stub().returnsThis(), toArray: sinon.stub().yields(expectedError, null) }; - var db = { collection: sinon.stub().yields(null, col) }; + var db = { + collection: sinon.stub().yields(null, col), + listCollections: sinon.stub().returnsThis(), + forEach: sinon.stub() + }; entitiesStore.__set__('orionServiceDb', sinon.stub().returns(db)); var callback4 = sinon.stub(); @@ -284,7 +295,8 @@ describe('entitiesStore', function() { ); process.nextTick(function() { - callback4.should.have.been.calledOnceWith(expectedError); + db.listCollections.should.have.been.calledOnce; + db.forEach.should.have.been.calledOnce; done(); }); }); diff --git a/test/utils/utilsT.js b/test/utils/utilsT.js index 9e56c043..125d24cb 100644 --- a/test/utils/utilsT.js +++ b/test/utils/utilsT.js @@ -53,22 +53,22 @@ function loadDirExamples(filepath) { function remove(collection, callback) { MongoClient.connect( config.mongo.url, + { + socketTimeoutMS: config.checkDB.reconnectInterval || 30000, + serverSelectionTimeoutMS: config.checkDB.reconnectInterval || 30000 + }, function(err, client) { if (err) { return callback(err); } - const db = client.db(); - db.collection(collection, {}, function(err, coll) { + const col = client.db().collection(collection); + + col.deleteMany({}, function(err, result) { if (err) { return callback(err); } - coll.remove({}, function(err, result) { - if (err) { - return callback(err); - } - client.close(); - return callback(null, result); - }); + client.close(); + return callback(null, result); }); } ); @@ -84,22 +84,21 @@ function dropExecutions(callback) { function dropCollection(collection, callback) { MongoClient.connect( config.mongo.url, + { + socketTimeoutMS: config.checkDB.reconnectInterval || 30000, + serverSelectionTimeoutMS: config.checkDB.reconnectInterval || 30000 + }, function(err, client) { if (err) { return callback(err); } - const db = client.db(); - db.collection(collection, {}, function(err, col) { + const col = client.db().collection(collection); + col.drop(function(err, result) { if (err) { return callback(err); } - col.drop(function(err, result) { - if (err) { - return callback(err); - } - client.close(); - return callback(null, result); - }); + client.close(); + return callback(null, result); }); } ); @@ -114,19 +113,19 @@ function dropExecutionsCollection(callback) { function createRulesCollection(callback) { MongoClient.connect( config.mongo.url, + { + socketTimeoutMS: config.checkDB.reconnectInterval || 30000, + serverSelectionTimeoutMS: config.checkDB.reconnectInterval || 30000 + }, function(err, client) { if (err) { return callback(err); } - const db = client.db(); - db.collection(config.collections.rules, {}, function(err, rules) { - if (err) { - return callback(err); - } - rules.ensureIndex({ name: 1 }, { unique: true, w: 'majority' }, function(err, indexName) { - client.close(); - return callback(err, indexName); - }); + const rules = client.db().collection(config.collections.rules); + + rules.createIndex({ name: 1 }, { unique: true, w: 'majority' }, function(err, indexName) { + client.close(); + return callback(err, indexName); }); } ); @@ -135,22 +134,22 @@ function createRulesCollection(callback) { function addRule(rule, callback) { MongoClient.connect( config.mongo.url, + { + socketTimeoutMS: config.checkDB.reconnectInterval || 30000, + serverSelectionTimeoutMS: config.checkDB.reconnectInterval || 30000 + }, function(err, client) { if (err) { return callback(err); } - const db = client.db(); - db.collection(config.collections.rules, {}, function(err, rules) { + const rules = client.db().collection(config.collections.rules); + + rules.insertOne(rule, function(err, result) { if (err) { return callback(err); } - rules.save(rule, function(err, result) { - if (err) { - return callback(err); - } - client.close(); - return callback(null, result); - }); + client.close(); + return callback(null, result); }); } ); @@ -159,20 +158,21 @@ function addRule(rule, callback) { function createEntitiesCollection(tenant, callback) { MongoClient.connect( config.orionDb.url, + { + socketTimeoutMS: config.checkDB.reconnectInterval || 30000, + serverSelectionTimeoutMS: config.checkDB.reconnectInterval || 30000 + }, function(err, client) { var db2 = client.db(config.orionDb.prefix + '-' + tenant); if (err) { return callback(err); } - db2.collection(config.orionDb.collection, {}, function(err, rules) { - if (err) { - return callback(err); - } - // We don't mind what fields have index in that collection - rules.ensureIndex({ modDate: 1 }, { unique: true, w: 'majority' }, function(err, indexName) { - client.close(); - return callback(err, indexName); - }); + var rules = db2.collection(config.orionDb.collection); + + // We don't mind what fields have index in that collection + rules.createIndex({ modDate: 1 }, { unique: true, w: 'majority' }, function(err, indexName) { + client.close(); + return callback(err, indexName); }); } ); @@ -180,22 +180,23 @@ function createEntitiesCollection(tenant, callback) { function dropEntities(callback) { MongoClient.connect( config.orionDb.url, + { + socketTimeoutMS: config.checkDB.reconnectInterval || 30000, + serverSelectionTimeoutMS: config.checkDB.reconnectInterval || 30000 + }, function(err, client) { - var db2 = client.db(config.orionDb.prefix + '-' + config.DEFAULT_TENANT); + var db2 = client.db(config.orionDb.prefix + '-' + config.DEFAULT_SERVICE); if (err) { return callback(err); } - db2.collection(config.orionDb.collection, {}, function(err, coll) { + var coll = db2.collection(config.orionDb.collection); + + coll.deleteMany({}, function(err, result) { if (err) { return callback(err); } - coll.remove({}, function(err, result) { - if (err) { - return callback(err); - } - client.close(); - return callback(null, result); - }); + client.close(); + return callback(null, result); }); } ); @@ -203,23 +204,24 @@ function dropEntities(callback) { function addEntity(tenant, entity, callback) { MongoClient.connect( config.orionDb.url, + { + socketTimeoutMS: config.checkDB.reconnectInterval || 30000, + serverSelectionTimeoutMS: config.checkDB.reconnectInterval || 30000 + }, function(err, client) { var db2; if (err) { return callback(err); } db2 = client.db(config.orionDb.prefix + '-' + tenant); - db2.collection(config.orionDb.collection, {}, function(err, entities) { + var entities = db2.collection(config.orionDb.collection); + + entities.insertOne(entity, function(err, result) { if (err) { return callback(err); } - entities.save(entity, function(err, result) { - if (err) { - return callback(err); - } - client.close(); - return callback(null, result); - }); + client.close(); + return callback(null, result); }); } );