javascriptnode.jsexpresstedious

Express.js how to allow multiple requests to be executed without blocking them


I have a website made with express js that receives numerous post requests. These requests do not take that long to satisfy (despite interacting with a sql database) so no problem here. However, when a request is made that runs a query that takes several minutes before it is satisfied the server hangs until the database provides a response.

The code I use for database queries has a structure like this:

Server.js:

//declaration of a lib developed by myself
var machineDataAnalysis = require('./MachineDataAnalysis.js')    

//handle post request
app.post('/loadAllEvents', function (req, res) {
  machineDataAnalysis.getAllEvents(function (resp) {
    res.status(200).send(JSON.stringify(resp));
  })
  res.status(401);
})

MachineDataAnalysis.js

//declaration of a lib developed by myself
var SQLServer = require('./lib/SQLServer.js');

getAllEvents function (simplified):

var query = `SELECT *
        FROM [JobViewerCurrent].[dbo].[dbEvents]`;

SQLServer.newQuery(query, QuerySettings.configMachineDatabase(), function (result) {
      callback(result);
})

SQLServer.js:

var Connection = require('tedious').Connection;
var Request = require('tedious').Request;

module.exports = {
newQuery: function (query, config, callback) {
    var connection = new Connection(config);
    var resultValue = {
        columnTitle: [],
        line: []
    };
    //
    // Setup event handler when the connection is established. 
    connection.on('connect', function (err) {
        var result = [];

        if (err) {
            console.log('Error: ', err)
        }
        // If no error, then good to go...
        request = new Request(query, function (err, rowCount) {
            if (err) {
                console.log(err);
            } else {
                //console.log(rowCount + ' rows');
            }
        });

        request.on('row', function (columns) {
            result = [];
            columns.forEach(function (column) {//cycle every filed of a row
                if (column.value === null) {
                    result.push('NULL');
                } else {
                    result.push(column.value);
                }
            });
            resultValue.line.push(result);
        });

        request.on("requestCompleted", function (rowCount, more) {
            //resultValue.result = result;
            connection.close()
            connection.cancel()
        });

        request.on('columnMetadata', function (columns) {

            var names = [];
            columns.forEach(function (column) {//cycle every filed of a row
                names.push(column.colName);
            });
            resultValue.columnTitle.push(names);
        });

        connection.execSql(request);
    });

    // Initialize the connection.
    connection.connect(connected);

    connection.on('end', end);


    function end() {
        callback(resultValue)
    }

    function connected(err) {
        if (err) {
             console.log('error');
        }

        process.stdin.resume();

        process.stdin.on('data', function (chunk) {
            exec(chunk);
        });

        process.stdin.on('end', function () {
        });
    }
}


};

I remain available for clarification.

Thanks

Luke


Solution

  • I modified the code with the changes you suggested but nothing changed.

    (I also removed MachineDataAnalysis.js)

    Server.js

    var QuerySettings = require('./SqlConfig.js');
    var databaseTest = require('./lib/SQL');
    databaseTest.connect(QuerySettings.configMachineDatabase()).then(
      console.log("Connection established!")
    )
    
    app.post('/loadAllEvents', async (req, res) => {
      var query = `SELECT  *
      FROM [JobViewerCurrent].[dbo].[dbEvents]
        `;
    
      databaseTest.query(query).then(function (a) {
          res.status(200).send(JSON.stringify(a))
      }, res.status(500))
    
    })
    

    SQL.js

    var Connection = require('tedious').Connection;
    var Request = require('tedious').Request;
    
    var connection;
    
    function connect(config) {
       return new Promise(function (resolve, reject) {
           connection = new Connection(config);
    
        connection.connect(function(err){
            if (err) {
    
            } else {
                resolve("done")
            }
        });
    })
    };
    
    function disconnect() {
      return new Promise(function (resolve, reject) {
        connection.close()
        connection.cancel()
    
        connection.on('end', function (err) {
            resolve("done")
        });
        //connection.on('error', reject("Error"))
      });
    };
    
    
    function query(query) {
      return new Promise(function (resolve, reject) {
        var result = [];
        var resultValue = {
            columnTitle: [],
            line: []
        };
        // If no error, then good to go...
        const request = new Request(query, function (err, rowCount) {
            if (err) {
                console.log(err);
            } else {
                //console.log(rowCount + ' rows');
            }
        });
    
        request.on('row', function (columns) {
            result = [];
            columns.forEach(function (column) {//cycle every filed of a row
                if (column.value === null) {
                    result.push('NULL');
                } else {
                    result.push(column.value);
                }
            });
            resultValue.line.push(result);
        });
    
        request.on("requestCompleted", function (rowCount, more) {
            resolve(resultValue)
        });
    
        request.on('columnMetadata', function (columns) {
    
            var names = [];
            columns.forEach(function (column) {//cycle every filed of a row
                names.push(column.colName);
            });
            resultValue.columnTitle.push(names);
        });
    
        connection.execSql(request);
    
      });
    }
    
    exports.connect = connect;
    exports.disconnect = disconnect;
    exports.query = query;