从AWS Lambda将数据保存到Postgres

时间:2018-08-03 16:18:00

标签: node.js postgresql amazon-web-services typescript aws-lambda

我正在构建一个lambda函数,该函数应将游戏反馈(例如性能等级)保存到AWS RDS中的Postgres数据库中。

我正在使用NodeJS打字稿,该函数虽然可以正常工作,但是以一种奇怪的方式进行。

我做了一个API网关,所以我可以将数据发布到lambda的URL上进行处理并保存,事实是,当我发布数据时,该函数似乎会对其进行处理,直到达到连接的客户端的最大限制为止,而且似乎丢失了其他客户的数据。

另一个问题是,每当我发布数据时,我都会收到一个响应,指出存在内部服务器错误,并且标头显示“ X-Cache→Error from cloudfront”。对于GET请求,我发现它是给我此响应的,因为响应的格式不正确,但是在这种情况下,我固定了响应格式,但仍然遇到此问题...

有时我会收到超时响应。

我函数的代码:

import { APIGatewayEvent, Callback, Context, Handler } from "aws-lambda";
import { QueryConfig, Client, Pool, PoolConfig } from "pg";

export const insert: Handler = async (
  event: APIGatewayEvent,
  context: Context,
  cb: Callback
) => {
  // context.callbackWaitsForEmptyEventLoop = false;

  const config: PoolConfig = {
    user: process.env.PG_USER,
    host: process.env.PG_HOST,
    database: process.env.PG_DB,
    password: process.env.PG_PASS,
    port: parseInt(process.env.PG_PORT),
    idleTimeoutMillis: 0,
    max: 10000
  };

  const pool = new Pool(config);

  let postdata = event.body || event;

  console.log("POST DATA:", postdata);

  if (typeof postdata == "string") {
    postdata = JSON.parse(postdata);
  }

  let query: QueryConfig = <QueryConfig>{
    name: "get_all_questions",
    text:
      "INSERT INTO gamefeedback (gameid, userid, presenterstars, gamestars) VALUES ($1, $2, $3, $4);",
    values: [
      parseInt(postdata["game_id"]),
      postdata["user_id"],
      parseInt(postdata["presenter_stars"]),
      parseInt(postdata["game_stars"])
    ]
  };
  console.log("Before Connect");

  let con = await pool.connect();

  let res = await con.query(query);

  console.log("res.rowCount:", res.rowCount);

  if (res.rowCount != 1) {
    cb(new Error("Error saving the feedback."), {
      statusCode: 400,
      body: JSON.stringify({
        message: "Error saving data!"
      })
    });
  }

  cb(null, {
    statusCode: 200,
    body: JSON.stringify({
      message: "Saved successfully!"
    })
  });
  console.log("The End");
};

比CloudWatch错误日志中连接的最大客户端数看起来像这样:

2018-08-03T15:56:04.326Z    b6307573-9735-11e8-a541-950f760c0aa5    (node:1) UnhandledPromiseRejectionWarning: error: sorry, too many clients already
at u.parseE (/var/task/webpack:/node_modules/pg/lib/connection.js:553:1)
at u.parseMessage (/var/task/webpack:/node_modules/pg/lib/connection.js:378:1)
at Socket.<anonymous> (/var/task/webpack:/node_modules/pg/lib/connection.js:119:1)
at emitOne (events.js:116:13)
at Socket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:250:11)
at Socket.Readable.push (_stream_readable.js:208:10)
at TCP.onread (net.js:607:20)

你们中的任何一个可以帮助我解决这个奇怪的问题吗?

谢谢

1 个答案:

答案 0 :(得分:0)

有一件事,您需要在处理程序上方放置一个池,就像这样:

const config: PoolConfig = {
  user: process.env.PG_USER,
  ...
};

const pool = new Pool(config);

export const insert: Handler = async (
  event: APIGatewayEvent,
  context: Context,
  cb: Callback
) => {

..etc

使用它的方式是在每次调用时创建一个池。如果您在处理程序外部创建池,则Lambda可以在调用之间共享池。