ClaudiaJS и pg-pool: как обернуть обещание

Я использую ClaudiaJS для развертывания бессерверного API (Lambda + API Gateway). В моем API я обращаюсь к RDS Postgres с помощью pg-pool.

Что я наделал:

В app.js

var ApiBuilder = require('claudia-api-builder'),
api = new ApiBuilder();
module.exports = api;

var Pool = require('pg-pool');

api.get("/list", function (request) {
   var dbconnect = {
     user: ‘xxxx’, //env var: PGUSER
     database: ‘xxxx’, //env var: PGDATABASE
     password: ‘xxx’, //env var: PGPASSWORD
     host: ‘xxxxxxxxxx.eu-west-1.rds.amazonaws.com', // Server hosting the postgres database
     port: 5432, //env var: PGPORT
     max: 1,
     min: 0,
     idleTimeoutMillis: 300000, 
     connectionTimeoutMillis: 1000
};

var pool = new Pool(dbconnect)
var sql = ‘Select …’

pool.query(sql, function (err, result) {

    console.log('Lambda :: execute query ');

    var resp = new Object();
    var jsonArr = []; // Populate the result
    console.log('Lambda :: result :: ' + JSON.stringify(result));
    return JSON.stringify(result)
});
}

В чем проблема: ничего не возвращает, и Cloudwatch тоже не показывает ошибок. Я погуглил, и люди сказали, что он не завернут в Promise. Мой вопрос в том, как обернуть pg-pool в Promise в этом случае.

Любое предложение приветствуется. Спасибо

****Обновлять****

Я пытался использовать обещание в пуле

pool.connect().then(client => {
  client.query(sql).then(res => {
    client.release()
    console.log('Result:', res.rows[0])
    return JSON.stringify(res.rows[0]);
  })
  .catch(e => {
    client.release()
    console.error('query error', e.message, e.stack)
  })
})

Я получил ошибку от CloudWatch:

UnhandledPromiseRejectionWarning: отклонение необработанного обещания (идентификатор отказа: 1): ошибка: соединение прервано из-за тайм-аута соединения


person Phong Vu    schedule 27.09.2017    source источник
comment
Как выглядит ваша лямбда handler? Можете ли вы опубликовать, как вы вызываете этот код из своего обработчика?   -  person Noel Llevares    schedule 28.09.2017
comment
Зачем заключать Pool в обещание, если есть pg-prom, которая уже выполняет все это? ;)   -  person vitaly-t    schedule 28.09.2017


Ответы (3)


Похоже, вы можете получить обещание от pool.query:

pg-pool поддерживает полностью основанный на обещаниях API для привлечения клиентов

https://github.com/brianc/node-pg-pool#acquire-clients-with-a-promise

Затем вы можете связать обещание вернуть свой JSON:

return pool.query(sql).then(function (result) {

    console.log('Lambda :: execute query ');

    var resp = new Object();
    var jsonArr = []; // Populate the result
    console.log('Lambda :: result :: ' + JSON.stringify(result));
    return JSON.stringify(result)
}, function(error){
    //handle error here
    console.error(error);
});
person gaheinrichs    schedule 27.09.2017
comment
Привет, спасибо за быстрый ответ. Я попробовал ваше предложение и получил сообщение об ошибке: UnhandledPromiseRejectionWarning: отклонение необработанного обещания (идентификатор отказа: 1): Ошибка: соединение прервано из-за тайм-аута соединения - person Phong Vu; 27.09.2017
comment
Привет, @PeterPham, без проблем. Я обновил свой ответ на отказ от обещания. - person gaheinrichs; 27.09.2017
comment
да, больше нет предупреждения об отклонении обещания, но все же ошибка: соединение прервано из-за тайм-аута соединения. Кажется, пул не может установить соединение. Любая идея? Этот пул нормально работал в AWS Elastic BeanTalk - person Phong Vu; 28.09.2017
comment
похоже, вы не можете подключиться ... Я чувствую, что это другой вопрос. Пожалуйста, попробуйте поискать в Google эту конкретную ошибку, я не знаю особенностей вашего соединения. - person gaheinrichs; 28.09.2017

Вам нужно вернуть обещание. Так:

return pool.connect().then(client => { // Return a promise
  return client.query(sql).then(res => { // Return promise again, if you omit this it will break promise chain
    client.release()
    console.log('Result:', res.rows[0])
    return JSON.stringify(res.rows[0]);
  })
  .catch(e => {
    client.release()
    console.error('query error', e.message, e.stack)
    throw e // Throw an error so Claudia can catch it
  })
})
person Slobodan Stojanovic    schedule 02.10.2017
comment
Фактически, ваш ответ очень близок к решению, которое я нашел. :) - person Phong Vu; 04.10.2017
comment
Нарушение цепочки обещаний - одна из самых распространенных ошибок, которые возникают при работе с Claudia API Builder и Claudia Bot Builder. Нам нужно будет как можно скорее написать об этом статью :) Этот код - всего лишь пример, возможно, он должен быть немного другим. - person Slobodan Stojanovic; 06.10.2017

Спасибо за ваши ответы. Поигравшись с кодом и погуглив на выходных, я нашел способ справиться с этим, я оставляю решение здесь для других, если таковые имеются.

var ApiBuilder = require('claudia-api-builder');
var pgp = require('pg-promise')();

api = new ApiBuilder();
module.exports = api;

api.get('/list', function (request) {

   var dbconnect = {
      user: ‘xxx’, //env var: PGUSER
      database: ‘xxx’, //env var: PGDATABASE
      password: ‘xxx’, //env var: PGPASSWORD
      host: ‘xxxx.rds.amazonaws.com', // Server hosting the postgres database
      port: 5432, //env var: PGPORT
   };

   var db = pgp(dbconnect);

   var sql = "SELECT * from table ...“;

   return db.any(sql).then(function (data) {

      pgp.end();

      console.log('Lambda :: params :: ' + JSON.stringtify(data));

      var resp = {
         name: data[0].name,
         serial_number: data[0].serial
      };

     return resp;
  })
   .catch(function (error) {
      console.log("Lambda :: Error: " + error);
      pgp.end();
  });
});

Меня устраивает. В любом случае, если у кого-то есть идея получше, поделитесь ею и здесь.

person Phong Vu    schedule 04.10.2017