I want to test the jobs I'm running with agenda. I have written the following test but then I realized that all the expect()... functions are not getting called before it determines that the test had passed or failed. I put some console.log() by all the expect() functions and they do get called just not before it determines if the tests result. I tried adding expect.assertions(6); at the top of the test but it didn't make the test wait longer, it just failed saying it didn't find all 6.
How do I make jest wait for the whole test to finish?
This is the code I want to test:
rules.js
const Account = require("./../models/user.account");
const Listing = require("./../models/user.account.listing");
const Message = require("./../models/user.account.listing.message");
const MessageRule = require("./../models/user.account.listing.messageRule");
const Reservation = require("./../models/user.account.listing.reservation");
const Core = require("./../core");
const moment = require("moment-timezone");
require("colors");
module.exports = function(agenda) {
agenda.define("send message", {priority: "highest"}, async (job, done) => {
try {
console.time("send message " + job.attrs._id);
const userID = job.attrs.data.userID;
const listingID = job.attrs.data.listingID;
const reservationID = job.attrs.data.reservationID;
const messageRuleID = job.attrs.data.messageRuleID;
const sendDate = job.attrs.data.sendDate;
//console.log("Rule Job:".cyan + " send message - listingID: " + listingID);
let messageQuery = {
userID,
listingID,
reservationID,
messageRuleID
};
let message = await Message.findOne(messageQuery);
if (message) {
throw new Error(
"Message has already been sent. userID: " +
userID +
" listingID: " +
listingID +
" reservationID: " +
reservationID +
" messageRuleID: " +
messageRuleID +
" message._id: " +
message._id +
" message.sendDate: " +
message.sendDate +
" message.sentDate: " +
message.sentDate
);
} else {
const isLastMinuteMessage = false;
let listing = await Listing.findById(listingID);
let account = await Account.findById(listing.accountID);
let messageRule = await MessageRule.findById(messageRuleID);
let reservation = await Reservation.findById(reservationID);
// Check that it found all of the required documents
if (!listing || !listing._id) {
throw new Error("Missing the listing document. userID: " + userID + " listingID: " + listingID);
}
if (!account || !account._id) {
throw new Error(
"Missing the account document. userID: " + userID + " accountID: " + listing.accountID
);
}
if (!messageRule || !messageRule._id) {
throw new Error(
"Missing the messageRule document. userID: " + userID + " messageRuleID: " + messageRuleID
);
}
if (!reservation || !reservation._id) {
throw new Error(
"Missing the reservation document. userID: " + userID + " reservationID: " + reservationID
);
}
// Double check the send date by recalculating it then checking comparing them
if (messageRule.event == "checkin" || messageRule.event == "checkout") {
let sendDateCheck = moment.tz(
reservation.startDate + " " + messageRule.time,
"YYYY-MM-DD H",
listing.timeZone
);
if (messageRule.event == "checkout") {
sendDateCheck = sendDateCheck.add(reservation.nights, "day");
}
sendDateCheck = sendDateCheck.add(messageRule.days, "day");
if (!sendDateCheck.isSame(sendDate)) {
throw new Error(
"Message send date and calculated send date don't match. userID: " +
userID +
" listingID: " +
listingID +
" reservationID: " +
reservationID +
" messageRuleID: " +
messageRuleID +
" sendDate: " +
moment(sendDate).format() +
" sendDateCheck: " +
moment(sendDateCheck).format()
);
}
}
await Core.buildMessage(account, listing, messageRule, reservation, isLastMinuteMessage);
}
console.timeEnd("send message " + job.attrs._id);
done();
} catch (error) {
console.error("Rule Job: send message", error);
return done(error);
}
});
};
And here is my test:
rules.test.js
const Account = require("./../models/user.account");
const Listing = require("./../models/user.account.listing");
const Message = require("./../models/user.account.listing.message");
const MessageRule = require("./../models/user.account.listing.messageRule");
const Reservation = require("./../models/user.account.listing.reservation");
const Core = require("./../core");
const Rules = require("./rules");
const Docs = require("./../tests/docs");
describe("Tests for rules.js", () => {
// Mock moment()
Date.now = jest.fn(() => 1538794832371); //October 5th 2018 8pm PST
beforeEach(() => {
jest.clearAllMocks();
});
describe("rules()", () => {
it("should send a message, message exists but is enabled", async () => {
// Mock Message
// Message.findOne()
const MessageFindOneMock = jest.spyOn(Message, "findOne");
const MessageFindOneResult = Docs.messageReviewReminderDisabledThenEnabled;
const MessageFindOne = jest.fn(() => MessageFindOneResult);
MessageFindOneMock.mockImplementation(MessageFindOne);
const userID = Docs.userID;
const reservation = Docs.reservationInTheFuture;
const messageRule = Docs.messageRuleCheckUp;
const accountID = Docs.listing.accountID;
const listingID = Docs.listing._id;
const reservationID = reservation._id;
const messageRuleID = messageRule._id;
// Mock Listing
// Listing.findById()
const ListingFindByIdMock = jest.spyOn(Listing, "findById");
const ListingFindByIdResult = Docs.listing;
const ListingFindById = jest.fn(() => ListingFindByIdResult);
ListingFindByIdMock.mockImplementation(ListingFindById);
// Mock Account
// Account.findById()
const AccountFindByIdMock = jest.spyOn(Account, "findById");
const AccountFindByIdResult = {_id: accountID};
const AccountFindById = jest.fn(() => AccountFindByIdResult);
AccountFindByIdMock.mockImplementation(AccountFindById);
// Mock MessageRule
// MessageRule.findById()
const MessageRuleFindByIdMock = jest.spyOn(MessageRule, "findById");
const MessageRuleFindByIdResult = messageRule;
const MessageRuleFindById = jest.fn(() => MessageRuleFindByIdResult);
MessageRuleFindByIdMock.mockImplementation(MessageRuleFindById);
// Mock Reservation
// Reservation.findById()
const ReservationFindByIdMock = jest.spyOn(Reservation, "findById");
const ReservationFindByIdResult = reservation;
const ReservationFindById = jest.fn(() => ReservationFindByIdResult);
ReservationFindByIdMock.mockImplementation(ReservationFindById);
// Mock Core
// Core.buildMessage()
const CoreBuildMessageMock = jest.spyOn(Core, "buildMessage");
const CoreBuildMessage = jest.fn((account, listing, messageRule, reservation, isLastMinuteMessage) => {
expect(account._id).toBe(accountID);
expect(listing._id).toBe(listingID);
expect(messageRule._id).toBe(messageRuleID);
expect(reservation._id).toBe(reservationID);
});
CoreBuildMessageMock.mockImplementation(CoreBuildMessage);
// Run test
const sendDate = "2018-11-08T10:00:00-06:00";
const done = jest.fn(error => {
expect(error).toBeFalsy();
expect(CoreBuildMessage).toHaveBeenCalledTimes(10);
});
const job = {
attrs: {
data: {
userID,
listingID,
reservationID,
messageRuleID,
sendDate
}
}
};
let agenda = {
define: jest.fn((name, options, callback) => {
if (name == "send message") {
callback(job, done);
}
})
};
Rules(agenda);
});
});
});
In your rules.js you have defined your callback as an async function:
agenda.define("send message", {priority: "highest"}, async (job, done) // <--- this
However you are calling it with:
define: jest.fn((name, options, callback) => {
if (name == "send message") {
callback(job, done);
}
})
So there is no await there ...
Which explains why you get stuff running but not awaiting for it to finish.
Should be something like:
define: await jest.fn((name, options, callback) => {
if (name == "send message") {
await callback(job, done);
}
})
Azure IoT Hub on server side and Azure IoT Client SDK on Device side, we are found 60-65 seconds delay and
drop between device sent a status message over MQTT and message was received by IoT Hub.
In some cases, we are seeing 1-2 minutes delay when IoT Hub enqueued the message.
Below is the code for communication with device to device
//'use strict';
//DeviceToCloudMessages libraries
var EventHubClient = require('azure-event-hubs').Client;
//var base64 = require('base-64');
//*NK+1 19-02-18 CloudToDeviceMessage Libraries
var Registry = require('azure-iothub').Registry;
//CloudToDeviceMessage libraries
var Client = require('azure-iothub').Client;
var Message = require('azure-iot-common').Message;
//*NK+1 13-03-18 Get constant values stored in GlobalConstants js
var constant = require('./GlobalConstants');
var connectionString = constant.connectionString;
var serviceClient = Client.fromConnectionString(connectionString);
//*NK+ 16-03-18 Open service cline
serviceClient.open(function (err) {
if (err) {
console.error('Could not connect: ' + err.message);
} else {
console.log('Open connection: ');
}
});
//*NK+1 19-02-18 Create registry for connection string
var registry = Registry.fromConnectionString(connectionString);
//To prevent memory leak
require('events').EventEmitter.defaultMaxListeners = Infinity;
//To check device connection state
var request = require('request');
auth = constant.authorization;
//Datetime library
date = require('date-and-time');
var moment = require("moment");
//For log
const fs = require('fs');
var datetime = require('node-datetime');
//For database connection
var sql = require('mssql');
var config =
{
user: constant.sUsername, // update me
password: constant.sPassword, // update me
server: constant.sServer, // update me
database: constant.sDatabase,
options: {
encrypt: true
},
//*start 30-01-18 set resource request timeout
connectionTimeout: 0,
requestTimeout: 0,
pool: {
max: 100,
min: 1,
idleTimeoutMillis: 30000
}
//*end 30-01-18 set resource request timeout
}
//*NK+1 23-03-18 declare flag false
//var isLog = false;
// sql.close();
//SQL starts
sql.connect(config).then(function (err) {
if (err) {
//console.log('sql CONNECTION ERROR');
console.log(err);
}
console.log('Opening connection');
var printError = function (err) {
logmsg(err.message);
logmsg('Error from event hub:', err.message);
startReceiver();
};
function logmsg(msg)
{
//if(isLog){
try {
//console.log(msg);
var dt = datetime.create();
var formatted = dt.format('Y-m-d H:M:S');
var date = dt.format('Y-m-d');
var checkhr = dt.format('H');
var filepath = 'D:/home/site/wwwroot/WebJobLogs/SendD2DMsgLog_' +date +'_' +checkhr + '-00-00' +'.txt';
fs.appendFile(filepath, formatted + " " + msg + "\n");
} catch(error) {
//console.log(error);
}
//}
}
function printResultFor(op) {
try {
return function printResult(err, res) {
if (err)
{
logmsg(op + ' error: ' + err.toString());
}
if (res)
{
logmsg(op + ' status: ' + res.constructor.name);
}
};
} catch (exception) {
logmsg("Print result function " + exception)
}
}
function receiveFeedback(err, receiver) {
receiver.on('message', function (msg) {
logmsg('IOT Feedback message:')
logmsg(msg.getData().toString('utf-8'));
});
}
//*NK+start 19-02-18 for firmware update
function queryTwinFWUpdateReported(deviceToUpdate) {
logmsg('deviceToUpdate : ' + deviceToUpdate);
logmsg('deviceToUpdate : ' + deviceToUpdate);
registry.getTwin(deviceToUpdate, function(err, twin){
if (err) {
//console.error('Could not query twins: ' + err.constructor.name + ': ' + err.message);
logmsg('Could not query twins: ' + err.constructor.name + ': ' + err.message);
} else {
//console.log('queryTwinFWUpdateReported: ' + (JSON.stringify(twin.properties.reported.iothubDM.firmwareUpdate)) + "\n");
//logmsg((JSON.stringify(twin.properties.reported.iothubDM.firmwareUpdate)) + "\n");
}
});
}
function startFirmwareUpdateDevice (linkString, deviceToUpdate) {
//console.log('linkString: ' + linkString);
var params = {
FwPackageUri: linkString
};
var methodName1 = "FirmwareUpdate";
var payloadData = JSON.stringify(params);
var payloadData1 = JSON.parse(payloadData);
logmsg('payloadData : ' + payloadData1);
var methodParams = {
methodName: methodName1,
payload: payloadData1,
timeoutInSeconds: 3600//,
//responseTimeoutInSeconds: 3600
};
//var methodParamsTest = JSON.stringify(methodParams);
//var objmethodParams = JSON.parse(methodParamsTest);
logmsg('methodParams : ' + JSON.stringify(methodParams));
//console.log('methodParams : ' + JSON.stringify(methodParams));
serviceClient.invokeDeviceMethod(deviceToUpdate, methodParams, function(err, result) {
if (err) {
//console.log('Could not start the firmware update on the device: ' + err.message);
//console.log('Device: ' + err.stack);
logmsg('Could not start the firmware update on the device: ' + err.message);
}else{
logmsg('success result : ' + JSON.stringify(result));
//console.log('success result : ' + JSON.stringify(result));
}
});
}
//*NK+end 19-02-18 for firmware update
var printMessage = function (message) {
logmsg('Message received: ');
try {
var chunk_msg = JSON.stringify(message.body);
logmsg(chunk_msg);
var obj = JSON.parse(chunk_msg);
//*NK+start 19-02-18 firmware update code
if(obj.hasOwnProperty('firmwareUpdate')){
var firmwaretype= obj.controllerName;
var firmwaremodel= obj.modelNumber;
var firmwareDeviceId = obj.firmwareUpdate;
var appDeviceId = obj.appDeviceId;
new sql.Request()
.query("SELECT f.fw_version, f.[loc] FROM <<table>> f WHERE f.[Type] = '" + firmwaretype + "' ").then(function (recordset) {
var statusLocation = JSON.stringify(recordset);
var obj = JSON.parse(statusLocation);
var result = obj.recordset;
logmsg('result: ' + result);
console.log('result: ' + result);
if(result.length > 0){
console.log('fw_version: ' + result[0].fw_version);
console.log('loc: ' + result[0].loc);
console.log('obj.firmwareUpdate : ' + firmwareDeviceId);
console.log('obj.appDeviceId : ' + appDeviceId);
new sql.Request()
.query("select TOP 1 * from <<table>> where Id = '" + firmwareDeviceId + "' order by id desc ").then(function (recordset) {
var status = JSON.stringify(recordset);
var objstatus = JSON.parse(status);
var resultstatus = objstatus.recordset;
var datastatus = resultstatus[0];
var chunkstatus = JSON.stringify(datastatus);
var objnewstatus = JSON.parse(chunkstatus);
var endDate = objnewstatus.last_update;
logmsg('controller last status date ' + endDate);
console.log('controller last status date ' + endDate);
now = new Date();
var currentDate = date.format(now, 'YYYY-MM-DD HH:mm:ss');
logmsg('server current date ' + currentDate);
console.log('server current date ' + currentDate);
var start_date = moment(currentDate, 'YYYY-MM-DD HH:mm:ss');
var end_date = moment(endDate, 'YYYY-MM-DD HH:mm:ss');
var duration = moment.duration(start_date.diff(end_date));
var hours = duration.asHours();
//var seconds = Math.abs(hours * 3600);
var seconds = Math.abs(hours * 3600);
logmsg('difference in seconds ' + seconds);
console.log('difference in seconds ' + seconds);
if (seconds < 40)
{
logmsg('fw_version: ' + result[0].fw_version);
logmsg('loc: ' + result[0].loc);
console.log('fw_version: ' + result[0].fw_version);
console.log('loc: ' + result[0].loc);
startFirmwareUpdateDevice(result[0].loc, firmwareDeviceId);
setInterval(function() {queryTwinFWUpdateReported(firmwareDeviceId);}, 1000);
}
else{
//format failure msg to send to app
var result = '{"response_status":"true","device_id":"' + firmwareDeviceId + '"}';
logmsg('Sending message to app:' + result);
console.log('Sending message to app:' + result);
var message = new Message(result);
serviceClient.send(appDeviceId, message, printResultFor('send'));
logmsg('Feedback Message for firmware upgrade failure sent to app ' + appDeviceId);
console.log('Feedback Message for firmware upgrade failure sent to app ' + appDeviceId);
}
}).catch(function (err) {
logmsg('firmware upgrade: ' + err);
});
}
}).catch(function (err) {
logmsg(err);
});
}
//*NK+end 19-02-18
if (obj.hasOwnProperty('command'))
{
logmsg('command exist');
console.log('command exist');
//Send Msg to device
//serviceClient.open(function (err) {
//if (err) {
// console.error('Could not connect: ' + err.message);
//} else {
// logmsg('Service client connected');
//*NK+1 23-03-18 Commented feedback receiver
//serviceClient.getFeedbackReceiver(receiveFeedback);
message.ack = 'full';
//message.messageId = "My Message ID";
//*NK+1 20-02-18 Update messageId
console.log('obj.messageId : ' + obj.messageId);
message.messageId = obj.messageId;
//Check the status of controller before sending message and return message to user in case of failure
var targetDevice = obj.deviceId;
new sql.Request()
.query("select TOP 1 * from <<table>> where Id = '" + targetDevice + "' order by id desc ").then(function (recordset) {
var status = JSON.stringify(recordset);
var objstatus = JSON.parse(status);
var resultstatus = objstatus.recordset;
var datastatus = resultstatus[0];
var chunkstatus = JSON.stringify(datastatus);
var objnewstatus = JSON.parse(chunkstatus);
var endDate = objnewstatus.last_update;
logmsg('controller last status date ' + endDate);
console.log('controller last status date ' + endDate);
now = new Date();
var currentDate = date.format(now, 'YYYY-MM-DD HH:mm:ss');
logmsg('server current date ' + currentDate);
console.log('server current date ' + currentDate);
var start_date = moment(currentDate, 'YYYY-MM-DD HH:mm:ss');
var end_date = moment(endDate, 'YYYY-MM-DD HH:mm:ss');
var duration = moment.duration(start_date.diff(end_date));
var hours = duration.asHours();
//var seconds = Math.abs(hours * 3600);
var seconds = Math.abs(hours * 3600);
logmsg('difference in seconds ' + seconds);
console.log('difference in seconds ' + seconds);
if (seconds <= 65)
{
var data = obj.command;
//format msg to send to controller
var str1 = '{"Name":"Play","Parameters":{"Data":"';
var res = str1.concat(data);
var str2 = '"}}';
var result = res.concat(str2);
var message = new Message(result);
logmsg('Sending message to controller: ' + message.getData());
console.log('Sending message to controller: ' + message.getData());
serviceClient.send(targetDevice, message, printResultFor('send'));
logmsg('Message sent to controller ' + targetDevice);
console.log('Message sent to controller ' + targetDevice);
}
else
{
//*NK+start 29-03-18 Check reset command and send to the server
var data_command = obj.command;
if(data_command == "<<RESETDEVICECOMMAD>>"){
//format msg to send to controller
var str1 = '{"Name":"Play","Parameters":{"Data":"';
var res = str1.concat(data_command);
var str2 = '"}}';
var result = res.concat(str2);
var message = new Message(result);
logmsg('Reset message is: ' + message.getData());
console.log('Reset message is: ' + message.getData());
serviceClient.send(targetDevice, message, printResultFor('send'));
logmsg('Reset message sent to controller ' + targetDevice);
console.log('Reset message sent to controller ' + targetDevice);
}
//*NK+start 29-03-18 Check reset command and send to the server
if (obj.hasOwnProperty('appDeviceId'))
{
//Get app device id
var AppDeviceId = obj.appDeviceId;
//format failure msg to send to app
var result = '{"response_status":"false","device_id":"' + targetDevice + '"}';
logmsg('Sending message to app:' + result);
console.log('Sending message to app:' + result);
var message = new Message(result);
serviceClient.send(AppDeviceId, message, printResultFor('send'));
logmsg('Feedback Message for command failure sent to app ' + AppDeviceId);
console.log('Feedback Message for command failure sent to app ' + AppDeviceId);
}
}
}).catch(function (err) {
logmsg(err);
});
// }
//});
}
else if (obj.hasOwnProperty('u32SH'))
{
// console.log('json exist');
var deviceId = obj.deviceId;
var data = chunk_msg;
var datetime = new Date();
//SQL to get list of device ids
new sql.Request()
.query("select * from <<table>> where id in (select id from <<table>> where id in (select id from <<table>> where Id = '" + deviceId + "')) and connectionState = 'Connected' ").then(function (recordset) {
var chunk = JSON.stringify(recordset);
var obj = JSON.parse(chunk);
var result = obj.recordset;
var message = new Message(chunk_msg);
message.ack = 'full';
message.messageId = "My Message ID";
logmsg('Sending message: ' + message.getData());
for (var i = 0, len = result.length; i < len; i++)
{
var data = result[i];
var chunk1 = JSON.stringify(data);
var obj1 = JSON.parse(chunk1);
//Get device id of user
var targetDevice = obj1.device_id;
serviceClient.send(targetDevice, message, printResultFor('send'));
logmsg('Message sent to user ' + targetDevice);
} //for loop ends
}).catch(function (err) {
logmsg(err);
}); //1st sql ends
} //else if for json object check ends
//*NK++ 06-03-18 update controller table
var macId = obj.deviceId;
updateControllerFirmwareVersion(macId);
} catch (exception) {
logmsg("Handling exception....");
logmsg(exception);
}
}; //printMessage function ends
//*NK+start 05-03-18 update controller firmware version
function updateControllerFirmwareVersion(deviceId){
registry.getTwin(deviceId, function(err, twin){
if (err) {
//console.log('Could not query twins: ' + err.constructor.name + ': ' + err.message);
console.error('Could not query twins: ' + err.constructor.name + ': ' + err.message);
} else {
logmsg((JSON.stringify(twin.properties.reported.AzureFwVersion)) + "\n");
//console.log((JSON.stringify(twin.properties.reported.AzureFwVersion)) + "\n");
//var azureFwVersion = twin.properties.reported.AzureFwVersion.replace('Azure_Sns_DM V','');
var azureFwVersion = twin.properties.reported.AzureFwVersion;
var s = azureFwVersion.lastIndexOf(".");
var res = azureFwVersion.substring(s+1, azureFwVersion.length);
//console.log('azureFwVersion: ' + res);
var firmwareV = Number(res).toString(16).toUpperCase() + '00';
//console.log('hex : ' + firmwareV);
logmsg('hex : ' + firmwareV);
new sql.Request()
.query("select fw_version from <<table>> where Id = '" + deviceId + "'").then(function (recordset) {
logmsg('Get current controller table firmware version');
var currentData = JSON.stringify(recordset);
var obj = JSON.parse(currentData);
var resultstatus = obj.recordset;
var datastatus = resultstatus[0];
var chunkstatus = JSON.stringify(datastatus);
var objnewstatus = JSON.parse(chunkstatus);
if(objnewstatus.fw_version != firmwareV){
console.log('Available firmware is ' + firmwareV);
logmsg('Available firmware is ' + firmwareV);
new sql.Request()
.query("UPDATE <<table>> SET fw_version = '" + firmwareV + "' where Id = '" + deviceId + "'").then(function (recordset) {
logmsg('Updated Controller table for firmware');
//console.log('Updated Controller table for firmware');
}).catch(function (err) {
logmsg('Qry to update Controller table for firmware' + err);
//console.log('Qry to update Controller table for firmware' + err);
});
}
}).catch(function (err) {
logmsg('Qry to update Controller table for firmware' + err);
//console.log('Qry to update Controller table for firmware' + err);
});
}
});
}
//*NK+end 05-03-18 update controller firmware version
var startReceiver = function () {
try {
logmsg('Receiver on');
var client = EventHubClient.fromConnectionString(connectionString);
client.open()
.then(client.getPartitionIds.bind(client))
.then(function (partitionIds) {
return partitionIds.map(function (partitionId) {
return client.createReceiver('$Default', partitionId, {'startAfterTime': Date.now()}).then(function (receiver) {
logmsg('Created partition receiver: ' + partitionId)
// receiver.on('errorReceived', printError);
// receiver.on('message', printMessage);
receiver.on('errorReceived', function callback() {
// console.log('Error Received in receiver');
client.close()
startReceiver()
});
receiver.on('message', printMessage);
});
})
})
// .catch(printError);
.catch(function callback() {
logmsg('Error Received in catch');
client.close()
startReceiver()
});
} catch (exception) {
logmsg("startReceiver function " + exception)
}
};
startReceiver();
}); //sql connection ends
Question:
1. What is the reason for this late/delay/drop in message reaching to IoT Hub?
2. Is there any issue on node js code?
I am using following node js packages :
{
"name": "Haven",
"version": "1.0.0",
"description": "",
"main": "AppToServerToDevice.js",
"dependencies": {
"azure-event-hubs": "0.0.8",
"azure-iot-device": "^1.2.1",
"azure-iot-device-mqtt": "^1.2.2",
"azure-iothub": "^1.2.3",
"base-64": "^0.1.0",
"date-and-time": "^0.6.2",
"heapdump": "^0.3.9",
"moment": "^2.20.1",
"mssql": "^4.1.0",
"tedious": "^2.1.1"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
IOT Hub details :
IoT Hub details:
Pricing tier: S2 standard
IoT Hub units: 1
SQL database Pricing tier is Standard: S3
Please suggest.
Please see below sample log.
2018-04-02 14:00:18 Message received:
2018-04-02 14:00:23 send status: MessageEnqueued
2018-04-02 14:00:23 send status: MessageEnqueued
2018-04-02 14:00:23 send status: MessageEnqueued
2018-04-02 14:00:23 send status: MessageEnqueued
2018-04-02 14:00:25 {"deviceId":"<<FAKE_ID>>","messageId":54,"u32SH":1094861843,"u32SVN":1215,"u32CVN":645,"u32SRS":2,"u32EVT_ID":9,"u8RSSI":94,"u8C1TID":0,"u8C1ETID":1,"u8C1STId":0,"u8C1ATId":1,"u8C1Rt":3,"u8C1B":36,"u8C1WL":0,"u8C1WB":36,"u8C1SB":68,"u8C1PB":0,"u8C2TID":0,"u8C2ETID":1,"u8C2STId":0,"u8C2ATId":2,"u8C2Rt":11,"u8C2B":99,"u8C2WL":11,"u8C2WB":99,"u8C2SB":99,"u8C2PB":99,"ts":"2018-04-02T14:00:23Z"}
2018-04-02 14:00:25 Message sent to user <<FAKE_ID>>
2018-04-02 14:00:25 Message sent to user <<FAKE_ID>>
2018-04-02 14:00:26 IOT Feedback message:
2018-04-02 14:00:26 [{"originalMessageId":"My Message ID","description":"Success","deviceGenerationId":"636573862820707504","deviceId":"34cebb0dd9eab292","enqueuedTimeUtc":"2018-04-02T14:00:18.6513817Z","statusCode":"Success"},{"originalMessageId":"My Message ID","description":"Success","deviceGenerationId":"636573862820707504","deviceId":"34cebb0dd9eab292","enqueuedTimeUtc":"2018-04-02T14:00:22.9953077Z","statusCode":"Success"}]
Im working on react and node project. Im new to both technologies, and i developed a system for my internship. But I feel like, I didn't handle the server side (Node part) properly. This is my server side file. It container almost 700 lines. Do I have to break this page in to several pages? If so, how exactly I should do it? Can someone give me a suggestion please. The application is working as expected. I just want to clean the code in the server side. I used express framework with node.
var express = require('express');
var mysql = require('mysql');
var _ = require('underscore');
var crypto = require('crypto');
var app = express();
var connections = [];
var title = 'Fishery Logistics';
var flds = [];
var currentFld = '';
var fldDetails = [];
var lfrSaved = false;
var userSiteInfoSaved = false;
var userList = [];
var userTypes = [];
var validUserName = false;
var fldNumbers = [];
var productCodes = [];
var containerTypes = [];
var areaCodes = [];
var fldRows = 0;
var fldInfo = {};
var productInfo = {};
var weighInList = {};
var weighInSaved = false;
var weighInNumbers = [];
var weighInWeights = [];
var fldHeaderInfo = [];
var weighInHeaderInfo = [];
var fldWeights = [];
var userDeleted = false;
// From where express should access our files
app.use(express.static('./public'));
app.use(express.static('./node_modules/bootstrap/dist'));
var server = app.listen(process.env.PORT || 3000);
// Creating a socket server which is also listeing to localhost:<port>
var io = require('socket.io').listen(server);
var connection = mysql.createConnection({
host: "localhost",
user: "root",
password: '',
database: 'fish_landing'
});
io.sockets.on('connection', function(socket) {
// Load fld list relevant to a LFR
socket.on('lfrFldListLoad', function(payload) {
var lfr_id = payload.lfrId;
var sql_lfr_fld_list = 'SELECT F.fld_id, F.fld_number, DATE_FORMAT(F.landed_date, "%Y-%m-%d") AS "landed_date", F.vessel_name, F.port_name, F.transport_company_name, F.driver_name, truck_number, FS.status ' +
'FROM fld F, fld_status FS, lfr L ' +
'WHERE F.status_id = FS.status_id ' +
'AND F.lfr_id = L.lfr_id ' +
'AND L.lfr_id = ' + lfr_id +
' ORDER BY F.fld_id DESC';
connection.query(sql_lfr_fld_list, function(error, result) {
if (error) {
console.log(error);
}
if (result.length !== 0) {
flds = result;
io.sockets.emit('lfrFldListLoaded', flds);
} else {
console.log('No Records Found')
}
});
});
// Load fld with all the details
socket.on('fldViewLoad', function(payload) {
var fld_id = payload.fldId;
var sql_fld_by_id =
'SELECT F.fld_id, F.fld_number, DATE_FORMAT(F.landed_date, "%Y-%m-%d") AS "landed_date", DATE_FORMAT(F.landed_date, "%T") AS "landed_time", ' +
'F.port_name, F.vessel_name, F.skipper_name, F.transport_company_name, F.truck_number, F.driver_name, F.driver_license, F.vehicle_clean, ' +
'F.vehicle_refrigerated, F.containers_clean, F.containers_iced, F.skipper_signature, F.supervisor_signature, F.lfr_staff_signature, ' +
'F.skipper_signature_time, F.supervisor_signature_time, F.lfr_staff_signature_time, F.comment, FS.status, CONCAT(U.first_name, " ", U.last_name) AS "full_name", ' +
'DATE_FORMAT(F.fld_created_time, "%Y-%m-%d") AS "fld_created_date", DATE_FORMAT(F.fld_created_time, "%T") AS "fld_created_time" ' +
'FROM fld F, fld_status FS, user_personal_info U ' +
'WHERE F.status_id = FS.status_id ' +
'AND F.fld_created_user_id = U.user_id ' +
'AND F.fld_id = "' + fld_id + '"';
var sql_fld_detail_list =
'SELECT FD.fld_detail_id, SP.species, PS.state, C.container, FD.no_of_containers, FD.fld_id ' +
'FROM fld_details FD, species SP, processed_state PS, container C, fld F ' +
'WHERE F.fld_id = FD.fld_id ' +
'AND SP.species_id = FD.species_id ' +
'AND PS.state_id = FD.state_id ' +
'AND C.container_id = FD.container_id ' +
'AND F.fld_id = "' + fld_id + '"';
connection.query(sql_fld_by_id, function(errorFld, resultFld) {
if (errorFld) {
console.log(errorFld);
}
if (resultFld.length !== 0) {
currentFld = resultFld;
connection.query(sql_fld_detail_list, function(errorFldDetails, resultFldDetails) {
if (errorFldDetails) {
console.log(errorFldDetails);
} else {
fldDetails = resultFldDetails;
io.sockets.emit('fldViewLoaded', currentFld, fldDetails);
}
});
} else {
console.log('Fld Length Error')
}
});
});
// Save company info
socket.on('saveCompanyInfo', function(payload) {
var companyName = payload.companyName;
var registrationNo = payload.registrationNo;
var landlineNo = payload.landlineNo;
var mobileNo = payload.mobileNo;
var emailAddress = payload.emailAddress;
var companyLogo = payload.companyLogo;
var jsonFile = payload.jsonFile;
var sql_save_company_info =
`INSERT INTO lfr (lfr_name, registration_number, landline_number, mobile_number, email_address, lfr_logo, json_file)
VALUES ('${companyName}', '${registrationNo}', '${landlineNo}', '${mobileNo}', '${emailAddress}', '${companyLogo}', '${jsonFile}')`;
connection.query(sql_save_company_info, function(errorLfrInfo, resultLfrInfo) {
if (errorLfrInfo) {
lfrSaved = false;
console.log(errorLfrInfo);
}
if (resultLfrInfo) {
lfrSaved = true;
} else {
lfrSaved = false;
}
io.sockets.emit('companyInfoSaved', lfrSaved);
});
});
// Load user list for lfr
socket.on('userListLoad', function(payload) {
var lfrId = payload.lfrId;
var load_user_list =
`SELECT USI.user_id, USI.user_name, UT.user_type, USI.email_address, USI.passcord, US.status_type
FROM user_site_info USI, user_types UT, user_status US
WHERE USI.user_type_id = UT.user_type_id
AND USI.user_status_id = US.user_status_id
AND lfr_id = ${lfrId}`;
connection.query(load_user_list, function(errorUserList, resultUserList) {
if (errorUserList) {
console.log(errorUserList);
} else {
userList = resultUserList;
io.sockets.emit('userListLoaded', userList);
}
});
});
// Load organization form
socket.on('loadOrganization', function() {
io.sockets.emit('organizationLoaded');
});
// Load main form
socket.on('loadMain', function() {
io.sockets.emit('mainLoaded');
});
// Delete user
socket.on('deleteUser', function(payload) {
var lfrId = payload.lfrId;
var userId = payload.userId;
var delete_user =
`UPDATE user_site_info
SET user_status_id = '2'
WHERE user_id = ${userId}`;
var load_user_list =
`SELECT USI.user_id, USI.user_name, UT.user_type, USI.email_address, USI.passcord, US.status_type
FROM user_site_info USI, user_types UT, user_status US
WHERE USI.user_type_id = UT.user_type_id
AND USI.user_status_id = US.user_status_id
AND lfr_id = ${lfrId}`;
connection.query(delete_user, function(error, result) {
if (error) {
console.log(error);
}
if (result) {
connection.query(load_user_list, function(errorUserList, resultUserList) {
if (errorUserList) {
console.log(errorUserList);
} else {
userDeleted = true;
userList = resultUserList;
io.sockets.emit('userDeleted', userDeleted, userList);
}
});
} else {
userDeleted = false;
}
});
});
// Delete weigh in
socket.on('deleteWeighIn', function(payload) {
var weighInId = payload.weighInId;
var sql_delete_weigh_in =
`DELETE FROM weigh_in
WHERE weigh_in_id = ${weighInId}`;
var sql_delete_weigh_in_details =
`DELETE FROM weigh_in_details
WHERE weigh_in_id = ${weighInId}`;
connection.query(sql_delete_weigh_in, function(errorDeleteWightIn, resultDeleteWightIn) {
if (errorDeleteWightIn) {
console.log(errorDeleteWightIn);
}
connection.query(sql_delete_weigh_in_details, function(errorDeleteWightInDetails, resultDeleteWightInDetails) {
if (errorDeleteWightInDetails) {
console.log(errorDeleteWightInDetails);
}
if (resultDeleteWightInDetails) {
io.sockets.emit('weighInDeleted');
} else {
console.log('Weigh-In Deletion Error');
}
});
});
});
// Reset weigh-in list
socket.on('resetWeighInList', function() {
io.sockets.emit('weighInListReset');
});
// Save user site info
socket.on('saveUserSiteInfo', function(payload) {
var userName = payload.userName;
var userTypeId = payload.userType;
var emailAddress = payload.emailAddress;
var passcord = crypto.createHash('sha1').update(payload.passcord).digest("hex");
var userStatusId = 1;
var lfrId = payload.lfrId;
var sql_user_site_info =
`INSERT INTO user_site_info (user_name, user_type_id, email_address, passcord, user_status_id, lfr_id)
VALUES ('${userName}','${userTypeId}', '${emailAddress}', '${(passcord)}','${userStatusId}', '${lfrId}')`;
var load_user_list =
`SELECT USI.user_id, USI.user_name, UT.user_type, USI.email_address, USI.passcord, US.status_type
FROM user_site_info USI, user_types UT, user_status US
WHERE USI.user_type_id = UT.user_type_id
AND USI.user_status_id = US.user_status_id
AND lfr_id = ${lfrId}`;
connection.query(sql_user_site_info, function(errorUserInfo, resultUserInfo) {
if (errorUserInfo) {
userSiteInfoSaved = false;
console.log(errorUserInfo);
}
if (resultUserInfo) {
userSiteInfoSaved = true;
connection.query(load_user_list, function(errorUserList, resultUserList) {
if (errorUserList) {
console.log(errorUserList);
} else {
userList = resultUserList;
io.sockets.emit('userSiteInfoSaved', userSiteInfoSaved, userList);
}
});
} else {
console.log('User Info Saving Error')
}
});
});
// Save weigh in info
socket.on('saveWeighInRecord', function(payload) {
var fldId = payload.fldId;
var weighInId = payload.fldId;
var productId = payload.productId;
var containerId = payload.containerId;
var amount = payload.amount;
var netWeight = payload.netWeight;
var areaId = payload.areaId;
var userId = payload.userId;
// Check if the record is the first of the weigh in id,
var sql_check_weigh_in =
`SELECT * FROM weigh_in
WHERE weigh_in_id = '${weighInId}'`;
connection.query(sql_check_weigh_in, function(errorCheck, resultCheck) {
if (errorCheck) {
console.log(errorCheck);
}
// If there is no recrod related to weigh in id, create the weigh in id
if (resultCheck.length === 0) {
var sql_weigh_in_header =
`INSERT INTO weigh_in (weigh_in_id, fld_id, logged_user_id, created_time)
VALUES('${weighInId}', '${fldId}', '${userId}', NOW())`;
connection.query(sql_weigh_in_header, function(errorHeader, resultHeader) {
if (errorHeader) {
console.log(errorHeader);
}
});
}
});
var sql_weigh_in_record =
`INSERT INTO weigh_in_details (product_id, container_id, number_of_containers, net_weight, area_id, weigh_in_id)
VALUES ('${productId}', '${containerId}','${amount}','${netWeight}','${areaId}','${weighInId}')`;
var sql_load_records =
`SELECT P.product_code, C.container, WD.number_of_containers, WD.net_weight, S.species_code, PS.state_code, G.grade, A.area_code
FROM product P, container C, species S, processed_state PS, grade G, area A, weigh_in_details WD
WHERE WD.product_id = P.product_id
AND WD.container_id = C.container_id
AND WD.area_id = A.area_id
AND P.species_id = S.species_id
AND P.state_id = PS.state_id
AND P.grade_id = G.grade_id
AND weigh_in_id = '${weighInId}'
ORDER BY weigh_in_detail_id ASC`;
connection.query(sql_weigh_in_record, function(errorRecord, resultRecord) {
if (errorRecord) {
console.log(errorRecord);
}
if (resultRecord) {
connection.query(sql_load_records, function(errorList, resultList) {
if (errorList) {
console.log(errorList);
} else {
weighInList = resultList;
io.sockets.emit('weighInRecordSaved', weighInList);
}
});
} else {
console.log('Weigh In Saving Error')
}
});
});
// Load user types
socket.on('loadUserTypes', function() {
var sql_user_types =
`SELECT user_type_id, user_type FROM user_types
ORDER BY user_type ASC`;
connection.query(sql_user_types, function(error, result) {
if (error) {
console.log(error);
}
if (result.length !== 0) {
userTypes = result;
io.sockets.emit('userTypesLoaded', userTypes);
} else {
console.log('User Type Error')
}
});
});
// Load weigh-in numbers
socket.on('loadWeighInNumbers', function(payload) {
var lfrId = payload.lfrId
var sql_load_weigh_in =
`SELECT W.weigh_in_id
FROM weigh_in W, fld F
WHERE W.weigh_in_id = F.fld_id
AND F.lfr_id = ${lfrId}`;
connection.query(sql_load_weigh_in, function(error, result) {
if (error) {
console.log(error);
}
if (result.length !== 0) {
weighInNumbers = result;
io.sockets.emit('weighInNumbersLoaded', weighInNumbers);
} else {
console.log('Weigh-In Error')
}
});
});
// Load fld, weigh-in weights
socket.on('loadWeighInWeights', function(payload) {
// weigh_in table weigh_in_id and fld table fld_id are same
var weighInId = payload.weighInId;
var sql_load_fld_weights =
`SELECT S.species, S.species_code, SUM(FD.no_of_containers * C.content_weight) AS 'fld_weight'
FROM fld_details FD, species S, container C
WHERE S.species_id = FD.species_id
AND FD.container_id = C.container_id
AND FD.fld_id = '${weighInId}'
GROUP BY S.species_code, 'fld_weight'
ORDER BY S.species_code`;
var sql_load_weigh_in_weights =
`SELECT S.species, S.species_code, SUM(WD.net_weight) AS 'weigh_in_weight'
FROM weigh_in_details WD, species S, product P, container C
WHERE P.species_id = S.species_id
AND WD.product_id = P.product_id
AND WD.container_id = C.container_id
AND WD.weigh_in_id = '${weighInId}'
GROUP BY S.species_code, 'weigh_in_weight'
ORDER BY S.species_code`;
var sql_load_fld_info =
`SELECT DATE_FORMAT(F.fld_created_time, "%Y-%m-%d") AS "fld_created_date", CONCAT(U.first_name, " ", U.last_name) AS "fld_created_by", COUNT(FD.fld_id) AS "fld_records"
FROM fld F, user_personal_info U, fld_details FD
WHERE F.fld_created_user_id = U.user_id
AND F.fld_id = FD.fld_id
AND F.fld_id = '${weighInId}'`;
var sql_load_weigh_info =
`SELECT DATE_FORMAT(created_time, "%Y-%m-%d") AS "weigh_in_created_date", CONCAT(U.first_name, " ", U.last_name) AS "weigh_in_created_by", COUNT(WD.weigh_in_id) AS "weigh_in_records"
FROM weigh_in W, user_personal_info U, weigh_in_details WD
WHERE W.logged_user_id = U.user_id
AND W.weigh_in_id = WD.weigh_in_id
AND W.weigh_in_id = '${weighInId}'`;
connection.query(sql_load_fld_weights, function(errorFldWeights, resultFldWeights) {
if (errorFldWeights) {
console.log(errorFldWeights);
}
if (resultFldWeights.length !== 0) {
connection.query(sql_load_weigh_in_weights, function(errorweighInWeights, resultWeighInWeights) {
if (errorweighInWeights) {
console.log(errorweighInWeights);
}
if (resultWeighInWeights.length !== 0) {
connection.query(sql_load_fld_info, function(errorFldInfo, resultFldInfo) {
connection.query(sql_load_weigh_info, function(errorWeighInInfo, resultWeighInInfo) {
fldWeights = resultFldWeights;
weighInWeights = resultWeighInWeights;
fldHeaderInfo = resultFldInfo;
weighInHeaderInfo = resultWeighInInfo;
io.sockets.emit('weighInWeightsLoaded', fldWeights, weighInWeights, fldHeaderInfo, weighInHeaderInfo);
});
});
} else {
console.log('Weigh-In Weights Error')
}
});
}
});
});
// Load weigh in combo boxes
socket.on('loadWeighInComboBoxes', function(payload) {
var lfr_id = payload.lfr_id;
var sql_load_fld_numbers = `
SELECT fld_id, fld_number FROM fld WHERE lfr_id = '${lfr_id}'
ORDER BY fld_number DESC `;
var sql_load_product_codes = `
SELECT product_id, product_code FROM product ORDER BY product_code ASC `;
var sql_load_containers = `
SELECT container_id, container FROM container WHERE lfr_id = ${lfr_id} ORDER BY container ASC`;
var sql_load_area_codes = `
SELECT area_id, area_code FROM area ORDER BY area_code ASC `;
connection.query(sql_load_fld_numbers, function(errorFld, resultFld) {
if (errorFld) {
console.log(errorFld);
}
connection.query(sql_load_product_codes, function(errorProducts, resultProducts) {
if (errorProducts) {
console.log(errorProducts);
}
connection.query(sql_load_containers, function(errorContainer, resultContainer) {
if (errorContainer) {
console.log(errorContainer);
}
connection.query(sql_load_area_codes, function(errorArea, resultArea) {
if (errorArea) {
console.log(errorArea);
}
fldNumbers = resultFld;
productCodes = resultProducts;
containerTypes = resultContainer;
areaCodes = resultArea;
io.sockets.emit('weighInComboBoxesLoaded', fldNumbers, productCodes, containerTypes, areaCodes);
});
});
});
});
});
// Get fld info and weigh in records that are relavent to weighInId
socket.on('loadFldWeighInInfo', function(payload) {
var fldId = payload.fldId;
var weighInId = payload.fldId;
var sql_get_fld_count =
`SELECT COUNT( * ) AS 'fld_rows'
FROM fld_details WHERE fld_id = '${fldId}'`;
var sql_get_fld_info =
`SELECT DATE_FORMAT(F.fld_created_time, "%Y-%m-%d") AS "fld_created_date", DATE_FORMAT(F.fld_created_time, "%T") AS "fld_created_time", CONCAT(U.first_name, " ", U.last_name) AS "created_by"
FROM fld F, user_personal_info U
WHERE F.fld_created_user_id = U.user_id
AND F.fld_id = '${fldId}'`;
var sql_load_records =
`SELECT P.product_code, C.container, WD.number_of_containers, WD.net_weight, S.species_code, PS.state_code, G.grade, A.area_code
FROM product P, container C, species S, processed_state PS, grade G, area A, weigh_in_details WD
WHERE WD.product_id = P.product_id
AND WD.container_id = C.container_id
AND WD.area_id = A.area_id
AND P.species_id = S.species_id
AND P.state_id = PS.state_id
AND P.grade_id = G.grade_id
AND weigh_in_id = '${weighInId}'
ORDER BY weigh_in_detail_id ASC `;
connection.query(sql_get_fld_count, function(errorFldCount, resultFldCount) {
if (errorFldCount) {
console.log(errorFldCount);
}
connection.query(sql_get_fld_info, function(errorFldInfo, resultFldInfo) {
if (errorFldInfo) {
console.log(errorFldInfo);
}
connection.query(sql_load_records, function(errorList, resultList) {
if (errorList) {
console.log(errorList);
} else {
fldRows = resultFldCount;
fldInfo = resultFldInfo;
weighInList = resultList;
io.sockets.emit('fldWeighInInfoLoaded', fldRows, fldInfo, weighInList);
}
});
});
});
});
// Get product info
socket.on('loadProductInfo', function(payload) {
var productId = payload.productId;
var sql_get_product_info =
`SELECT P.product_code, S.species_code, PS.state_code, G.grade
FROM product P, species S, processed_state PS, grade G
WHERE P.species_id = S.species_id
AND P.state_id = PS.state_id
AND P.grade_id = G.grade_id
AND P.product_id = '${productId}'`;
connection.query(sql_get_product_info, function(error, result) {
if (error) {
console.log(error);
}
if (result.length !== 0) {
productInfo = result;
io.sockets.emit('productInfoLoaded', productInfo);
} else {
console.log('No Records Found')
}
});
});
// Load user types
socket.on('checkUserName', function(payload) {
var userName = payload.userName;
var sql_check_user_name =
`SELECT * from user_site_info
WHERE user_name = '${userName}'`;
connection.query(sql_check_user_name, function(error, result) {
if (error) {
console.log(error);
}
if (result.length !== 0) {
validUserName = false;
} else {
validUserName = true;
}
io.sockets.emit('userNameChecked', validUserName);
});
});
// socket.emit => emit events that are handled by the client
socket.emit('welcome', {
title: title,
flds: flds,
currentFld: currentFld,
fldDetails: fldDetails,
lfrSaved: lfrSaved,
userSiteInfoSaved: userSiteInfoSaved,
userList: userList,
userTypes: userTypes,
fldNumbers: fldNumbers,
productCodes: productCodes,
containerTypes: containerTypes,
areaCodes: areaCodes,
fldRows: fldRows,
fldInfo: fldInfo,
productInfo: productInfo,
weighInList: weighInList,
weighInNumbers: weighInNumbers,
weighInWeights: weighInWeights,
fldHeaderInfo: fldHeaderInfo,
weighInHeaderInfo: weighInHeaderInfo,
fldWeights: fldWeights,
userDeleted: userDeleted
});
connections.push(socket);
});
console.log(`Fishery Logistics is running at port ${ server.address().port }`);
You should definitely break this into several modules. Rule of thumb is to have controller modules and models.