根据mysql节点

时间:2016-09-13 18:31:02

标签: mysql node.js node-mysql

我有一张叫Vaccines的桌子。对于每种疫苗,都有一定数量的批次和一定数量的病理学,因此我为批次(VacLots)创建了一个表,为病理学(VacPathologies)创建了一个表。

VacLots和VacPathologies均使用疫苗标识符编制索引。

要创建疫苗我然后进行查询以检索所有疫苗(针对特定国家/地区)以及每个标识符我需要执行两个额外查询:一个用于识别其批次,另一个用于识别其病毒。

代码: 这是用于使用指定参数执行查询的函数。

executeQueryWithParams(queryToExecute, queryArgs, processRow) {
    this.pool.getConnection((err, conn) => {
        if (err) {
            console.log(`${err} executing the query ${queryToExecute} for database ${this.pool}`);
            cb({reason: 'Failed to get connection', err});
        } else {
            let query = conn.query(queryToExecute, queryArgs, (error, rows) => {
                conn.release();
                if (error) {
                    cb({reason: `Failed to execute query ${queryToExecute}`, error});
                } else {
                    cb(null , rows);
                }
        });
}

这是接收国家ID并负责创建疫苗对象的函数。

getVaccinesForCountryID = function (countryID) {
 return new Promise((resolve, reject) => {
   database.executeQueryWithParams(queries[GET_VACCINE_QUERY_INDEX], [countryID], function(err, rows) {
     if (err || rows.length == 0) {
       reject(utils.isNullOrUndefined(err) ? new Error('Empty results') : err);
     } else {
       resolve(processResultRows(rows));
     }
   });
 });

过程结果功能。

function processResultRows(rows) {
  const promiseArray = [];
  for (const row of rows) {
    const vaccine = instantiateVaccine(row);
    promiseArray.push(hydrateVaccine(vaccine));
  }
  return Promise.all(promiseArray);
}

instantiateVaccine函数只会创建一个Vaccine对象,其中包含行中已有的一些信息。

function hydrateVaccine(vaccine) {
    return getLotsForVaccine(vaccine).then(data => getPathologiesForVaccine(data));
}

检索特定疫苗的批次。

function getLotsForVaccine(vaccine) {
  return getDetailsVaccine(GET_VACCINE_LOTS_QUERY_INDEX, vaccine, (vac, rows) => {
    const lotsArray = [];
    for (const row of rows) {
      lotsArray.push({lot: row.lot});
    }
    vac.lots = lotsArray;
  });
}

检索特定疫苗的病理学。

function getPathologiesForVaccine(vaccine) {
  return getDetailsVaccine(GET_VACCINE_PATHOLOGIES_QUERY_INDEX, vaccine, (vac, rows) => {
    const pathologiesArray = [];
    for (const row of rows) {
      pathologiesArray.push({pathology: row.pathology});
    }
    vac.pathologies = pathologiesArray;
  });
}

检索一些细节(批次或病理)的通用函数

function getDetailsVaccine(queryIndex, vaccine, hydrateFunction) {
  return new Promise((resolve, reject) => {
    database.executeQueryWithParams(queries[queryIndex], [vaccine.identifier], (err, rows) => {
      if (err) {
        reject({error: err, query: queries[queryIndex], identifier: vaccine.identifier});
      } else {
        hydrateFunction(vaccine, rows);
        resolve(vaccine);
      }
    });
  });

如果没有发生大量请求,这一切都很有效但是只要发生超过10个请求(例如使用ab -k -c 2 -n 10)我就会拒绝连接并且池的最大数量为连接1000。

我觉得我的回调和Promise混合可能是一个问题,但我目前无法将executeQueryWithParams函数实现为Promise。

编辑: 这是用于创建池的代码(在executeQueryWithParams函数中引用为this.pool)

const pool = mysql.createPool({
    connectionLimit : '1000',
    host                        : 'localhost',
    user                    : 'readOnlyUser',
    password                :   'hRND74SKUjuH4uLU',
    database                :   'Calendar',
  debug           : false
});

1 个答案:

答案 0 :(得分:1)

我将发布我自己的解决方案,如@abdulbarik所示。

以下列方式实现executeQueryWithParams允许用户使用带有Promise的mysql池,这已经在总共100000个连接上测试了500个并发连接,并且TOO_MUCH_CONNECTIONS错误没有问题,可以用作Promise如果你想连锁。

function executeQueryWithParams(queryToExecute, queryArgs) {
  return new Promise((resolve, reject) => {
    this.pool.query(queryToExecute, queryArgs, function(err, rows) {
      if (err) {
        reject({reason: 'Error executing query', err});
      } else {
        resolve(rows);
      }
    });
  });
}