diff --git a/src/server/routes/obvius.js b/src/server/routes/obvius.js index 19bad6443..d2a7ad785 100644 --- a/src/server/routes/obvius.js +++ b/src/server/routes/obvius.js @@ -100,7 +100,7 @@ function handleStatus(req, res) { /** * Logs the Obvius request and sets the req.IP field to be the ip address. */ -function obviusLog(req, res, next){ +function obviusLog(req, res, next) { // Log the IP of the requester const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; req.IP = ip; @@ -111,7 +111,7 @@ function obviusLog(req, res, next){ /** * Verifies an Obvius request via username and password. */ -function verifyObviusUser(req, res, next){ +function verifyObviusUser(req, res, next) { // First we ensure that the password and username parameters are provided. const password = req.param('password'); // TODO This is allowing for backwards compatibility if previous obvius meters are using the'email' parameter @@ -157,6 +157,7 @@ router.all('/', obviusLog, verifyObviusUser, async (req, res) => { return; } const conn = getConnection(); + const loadLogfilePromises = []; for (const fx of req.files) { log.info(`Received ${fx.fieldname}: ${fx.originalname}`); // Logfiles are always gzipped. @@ -168,9 +169,19 @@ router.all('/', obviusLog, verifyObviusUser, async (req, res) => { failure(req, res, `Unable to gunzip incoming buffer: ${err}`); return; } - loadLogfileToReadings(req.param('serialnumber'), ip, data, conn); + // The original code did not await for the Promise to finish. The new version + // allows the files to run in parallel (as before) but then wait for them all + // to finish before returning. + loadLogfilePromises.push(loadLogfileToReadings(req.param('serialnumber'), ip, data, conn)); } - success(req, res, 'Logfile Upload IS PROVISIONAL'); + // TODO This version returns an error. Should check all usage to be sure it is properly handled. + Promise.all(loadLogfilePromises).then(() => { + success(req, res, 'Logfile Upload IS PROVISIONAL'); + }).catch((err) => { + log.warn(`Logfile Upload had issues from ip: ${ip}`, err) + failure(req, res, 'Logfile Upload had issues'); + }); + // This return may not be needed. return; } diff --git a/src/server/test/web/obviusTest.js b/src/server/test/web/obviusTest.js index 68cb47a10..48630a27a 100644 --- a/src/server/test/web/obviusTest.js +++ b/src/server/test/web/obviusTest.js @@ -9,6 +9,8 @@ const { chai, mocha, expect, app, testDB, testUser } = require('../common'); const User = require('../../models/User'); const Configfile = require('../../models/obvius/Configfile'); const bcrypt = require('bcryptjs'); +const { insertUnits } = require('../../util/insertData'); +const Unit = require('../../models/Unit'); mocha.describe('Obvius API', () => { mocha.describe('upload: ', () => { @@ -60,8 +62,25 @@ mocha.describe('Obvius API', () => { } }); mocha.describe('obvius request modes', async () => { - mocha.it('should reject requests without a mode', async () => { + mocha.beforeEach(async () => { const conn = testDB.getConnection(); + // The kWh unit is not used in all tests but easier to just put in. + const unitData = [ + { + name: 'kWh', + identifier: '', + unitRepresent: Unit.unitRepresentType.QUANTITY, + secInRate: 3600, + typeOfUnit: Unit.unitType.UNIT, + suffix: '', + displayable: Unit.displayableType.ALL, + preferredDisplay: true, + note: 'OED created standard unit' + } + ]; + await insertUnits(unitData, false, conn); + }); + mocha.it('should reject requests without a mode', async () => { const password = 'password'; const hashedPassword = await bcrypt.hash(password, 10); const obviusUser = new User(undefined, 'obivus@example.com', hashedPassword, User.role.OBVIUS); @@ -74,7 +93,6 @@ mocha.describe('Obvius API', () => { expect(res.text).equals(`
\nRequest must include mode parameter.\n
\n`); }); mocha.it('should accept status requests', async () => { - const conn = testDB.getConnection(); const password = 'password'; const hashedPassword = await bcrypt.hash(password, 10); const obviusUser = new User(undefined, 'obivus@example.com', hashedPassword, User.role.OBVIUS); @@ -88,20 +106,15 @@ mocha.describe('Obvius API', () => { expect(res.text).equals("
\nSUCCESS\n
\n"); }); mocha.it('should accept valid logfile uploads', async () => { - //PromiseRejectionHandledWarning originates here - const conn = testDB.getConnection(); const password = 'password'; const hashedPassword = await bcrypt.hash(password, 10); const obviusUser = new User(undefined, 'obvius@example.com', hashedPassword, User.role.OBVIUS); await obviusUser.insert(conn); obviusUser.password = password; const logfileRequestMode = 'LOGFILEUPLOAD'; - const configFileRequestMode = 'CONFIGFILEUPLOAD'; // Adapted from ../obvius/README.md const logfilePath = 'src/server/test/web/obvius/mb-001.log.gz'; - const configFilePath = 'src/server/test/web/obvius/mb-001.ini.gz'; - //the upload of a logfile is the subject of the test const res = await chai.request(app) @@ -111,7 +124,6 @@ mocha.describe('Obvius API', () => { .field('mode', logfileRequestMode) .field('serialnumber', 'mb-001') .attach('files', logfilePath); - //should respond with 200, success expect(res).to.have.status(200); //should also return expected message @@ -119,7 +131,6 @@ mocha.describe('Obvius API', () => { }); mocha.it('should accept valid config file uploads', async () => { - const conn = testDB.getConnection(); const password = 'password'; const hashedPassword = await bcrypt.hash(password, 10); const obviusUser = new User(undefined, 'obvius@example.com', hashedPassword, User.role.OBVIUS); @@ -145,7 +156,6 @@ mocha.describe('Obvius API', () => { expect(res.text).equals("
\nSUCCESS\nAcquired config log with (pseudo)filename mb-001-mb-1234.ini.
\n"); }); mocha.it('should return accurate config file manifests', async () => { - const conn = testDB.getConnection(); const password = 'password'; const hashedPassword = await bcrypt.hash(password, 10); const obviusUser = new User(undefined, 'obvius@example.com', hashedPassword, User.role.OBVIUS);