Node.js AWS Lambda 没有等待任何东西
Node.js AWS Lambda not waiting for anything
我已经尝试了所有建议的解决方案并查看了每个类似的问题,但没有解决我的问题。这个脚本在我的本地机器上工作得很好。 Lambda 的问题在于它完全跳过超时和等待。而我的本地机器实际上在等待。
我的索引文件如下所示:
import { getData } from './src/EC2Scripts/taskScripts/otherLogic.js';
async function handler(event) {
await getData();
const response = {
statusCode: 200,
body: JSON.stringify("Not waiting."),
};
return response;
}
export { handler };
这是其他逻辑 class:
import fetch from "node-fetch";
import { PoolConnection } from '../common/classes/PoolConnection.js';
async function getData() {
return new Promise(async (resolve, reject) => {
let pool = PoolConnection.getInstance();
let currentResponse = await fetch(
"dummyURL"
);
let currentData = await currentResponse.json();
pool.uploadCoins(currentData).then((result) => {
pool.endConnection().then((end) => { resolve() });
});
});
}
export { getData };
这是 PoolConnection class:
import pg from "pg";
import fetch from "node-fetch";
import { getCurrentDateTime } from "../dateTime.js";
class PoolConnection {
// DO NOT CALL THIS CONSTRUCTOR, CALL THE GETINSTANCE() METHOD
constructor() {
if (!PoolConnection.instance) {
PoolConnection.instance = this;
this.config = {
user: "user",
password: "password",
database: "postgres",
host: "host",
port: 5432,
max: 100,
connectionTimeoutMillis: 30000,
idleTimeoutMillis: 30000
};
this.pool = this.establishConnection(1).catch((error) => { });
}
}
static getInstance() {
if (PoolConnection.instance) {
return PoolConnection.instance;
}
PoolConnection.instance = new PoolConnection();
return PoolConnection.instance;
}
async connect() {
return new Promise((resolve, reject) => {
const poolPromise = new pg.Pool(this.config);
poolPromise.connect()
.then(pool => {
console.log(getCurrentDateTime() + " ----- Connection to article database successful.");
resolve(pool);
})
.catch(err => {
console.error(getCurrentDateTime() + " ----- ERROR CONNECTING TO ARTICLE DATABASE :: " + err);
reject(err);
});
});
}
async establishConnection(attempts) {
return new Promise((resolve, reject) => {
if (attempts > 5) {
console.log(getCurrentDateTime() + " ---- Connection unsuccessful to database, maximum number of attempts reached.");
reject("ERROR");
}
this.connect().then(pool => {
resolve(pool);
}).catch(err => {
console.error(getCurrentDateTime() + " RETRYING CONNECTION TO DATABASE ATTEMPT #" + attempts);
attempts++;
// try again in 3 seconds
setTimeout(() => { this.establishConnection(attempts) }, 3000);
});
})
}
// Connection has to be terminated gracefully or else script will hang.
async endConnection() {
return new Promise((resolve, reject) => {
this.pool.then(connection => connection.end(() => console.log(getCurrentDateTime() + " ---- Connection to database successfully terminated.")));
});
}
async uploadData(data) {
return new Promise((resolve, reject) => {
this.pool.then(async (poolInstance) => {
for(const entry of data) {
let getMoreData = await fetch (
"dummyUrl2" + entry
);
const result = poolInstance.query("INSERT INTO table(data) VALUES ()",
[entry['getMoreData']]);
}
resolve();
});
});
}
}
export { PoolConnection }
它试图在我做任何事情之前关闭连接。这是错误:
> START RequestId: 5aa4984b-d57f-4d69-84a3-005a6c590c0f Version: $LATEST
> 2022-05-03T14:48:11.625Z 5aa4984b-d57f-4d69-84a3-005a6c590c0f INFO 2022-5-3
> **** 14:48:11 ----- Connection to article database successful. 2022-05-03T14:48:12.946Z 5aa4984b-d57f-4d69-84a3-005a6c590c0f INFO 2022-5-3
> **** 14:48:12 ---- Connection to database successfully terminated. 2022-05-03T14:48:14.146Z 5aa4984b-d57f-4d69-84a3-005a6c590c0f ERROR Unhandled Promise Rejection
> {"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"Error:
> Client was closed and is not
> queryable","reason":{"errorType":"Error","errorMessage":"Client was
> closed and is not queryable","stack":["Error: Client was closed and is
> not queryable"," at
> /var/task/node_modules/pg/lib/client.js:570:27"," at
> processTicksAndRejections
> (internal/process/task_queues.js:77:11)"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection:
> Error: Client was closed and is not queryable"," at
> process.<anonymous> (/var/runtime/index.js:35:15)"," at
> process.emit (events.js:400:28)"," at processPromiseRejections
> (internal/process/promises.js:245:33)"," at
> processTicksAndRejections (internal/process/task_queues.js:96:32)"]}
> END RequestId: 5aa4984b-d57f-4d69-84a3-005a6c590c0f REPORT RequestId:
> 5aa4984b-d57f-4d69-84a3-005a6c590c0f Duration: 2985.31 ms Billed
> Duration: 2986 ms Memory Size: 128 MB Max Memory Used: 75 MB Init
> Duration: 267.75 ms
我已经尝试将所有内容转换为 return 一个新的 Promise,然后使用 .then(),但这实际上使程序 运行 不知何故变得更快。我试过使用 Promise.all().then()。我试过将 setTimeout() 移动到 index.js 中的处理程序中,但这也没有用。我试过在 pool.uploadData() 之后使用 then()。我也试过从方法处理程序中删除异步。
我现在没主意了。我已经重构并尝试以我见过的所有方式实现此代码,但没有任何效果。
没有错误或未捕获的异常,只是没有等待。
Lambda 使用的是 NodeJS 版本 14.x
编辑:添加池连接 class 并更新 classes 以更清楚地显示我尝试过的内容。
虽然 getData()
被标记为 async
,但它没有 return 任何明确的承诺,因此它 return 是一个 Promise<void>
立即解析(到undefined
)。
您需要 return 一个明确的 Promise
resolves/rejects 在您的业务逻辑 运行 之后,使 Lambda 实际上等待处理完成。
根据Node.js Lambda docs on async handlers:
If your code performs an asynchronous task, return a promise to make sure that it finishes running. When you resolve or reject the promise, Lambda sends the response or error to the invoker.
例如,此 returns 是一个 Promise
,它在 5 秒后解析,让 Lambda 在它 returns 响应之前等待:
async function getData() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), 5000)
});
}
async function handler(event) {
await getData();
const response = {
statusCode: 200,
body: JSON.stringify("Waiting 5 seconds..."),
};
return response;
}
export { handler };
START RequestId: 0ee7693e-8d6a-4c3f-b23e-119377e633e3 Version: $LATEST
END RequestId: 0ee7693e-8d6a-4c3f-b23e-119377e633e3
REPORT RequestId: 0ee7693e-8d6a-4c3f-b23e-119377e633e3 Duration: 5009.05 ms Billed Duration: 5010 ms Memory Size: 128 MB Max Memory Used: 56 MB Init Duration: 224.62 ms
我添加这个是因为我能够找出问题所在。在之前 answers/comments 的帮助下,我重新格式化了我的代码,因此如果其他人遇到类似问题,希望这会有所帮助。
index.js:
import { getData } from './src/EC2Scripts/taskScripts/otherLogic.js';
async function handler(event) {
await getData();
const response = {
statusCode: 200,
body: JSON.stringify("Now waiting."),
};
return response;
}
export { handler };
其他逻辑class:
import fetch from "node-fetch";
import { PoolConnection } from '../common/classes/PoolConnection.js';
async function getData() {
return new Promise(async (resolve, reject) => {
let pool = await PoolConnection.getInstance();
let currentResponse = await fetch(
"dummyURL"
);
let currentData = await currentResponse.json();
await pool.uploadData(currentData);
await pool.endConnection();
resolve();
});
}
export { getData };
池连接class:
import pg from "pg";
import fetch from "node-fetch";
import { getCurrentDateTime } from "../dateTime.js";
class PoolConnection {
// DO NOT CALL THIS CONSTRUCTOR, CALL THE GETINSTANCE() METHOD
constructor() {
if (!PoolConnection.instance) {
PoolConnection.instance = this;
this.config = {
user: "user",
password: "password",
database: "postgres",
host: "host",
port: 5432,
max: 100,
connectionTimeoutMillis: 30000,
idleTimeoutMillis: 30000
};
this.pool = new pg.Pool(this.config);
}
}
static async getInstance() {
return new Promise(async (resolve, reject) => {
if (PoolConnection.instance) {
return PoolConnection.instance;
}
PoolConnection.instance = new PoolConnection();
resolve(PoolConnection.instance);
});
}
// Connection has to be terminated gracefully or else script will hang.
async endConnection() {
return new Promise(async (resolve, reject) => {
await this.pool.end(() => console.log(getCurrentDateTime() + " ---- Connection to database successfully terminated."));
resolve();
});
}
async uploadData(data) {
return new Promise(async (resolve) => {
let promiseArray = [];
for (const entry of data) {
promiseArray.push(new Promise(async (resolve) => {
await this.pool.connect(async (error, client, release) => {
if (error) {
console.error(getCurrentDateTime() + " ----- Error getting client. Error :: ", error.stack);
}
await client.query("query", (error, result, release) => {
release();
if (error) {
console.error(getCurrentDateTime() + " ----- Error executing query :: ", error.stack);
}
resolve();
});
});
}));
}
await Promise.all(promiseArray);
resolve();
});
}
}
export { PoolConnection }
如果这不能解决您的问题,找到修复的两个最大帮助是 and 。
我已经尝试了所有建议的解决方案并查看了每个类似的问题,但没有解决我的问题。这个脚本在我的本地机器上工作得很好。 Lambda 的问题在于它完全跳过超时和等待。而我的本地机器实际上在等待。
我的索引文件如下所示:
import { getData } from './src/EC2Scripts/taskScripts/otherLogic.js';
async function handler(event) {
await getData();
const response = {
statusCode: 200,
body: JSON.stringify("Not waiting."),
};
return response;
}
export { handler };
这是其他逻辑 class:
import fetch from "node-fetch";
import { PoolConnection } from '../common/classes/PoolConnection.js';
async function getData() {
return new Promise(async (resolve, reject) => {
let pool = PoolConnection.getInstance();
let currentResponse = await fetch(
"dummyURL"
);
let currentData = await currentResponse.json();
pool.uploadCoins(currentData).then((result) => {
pool.endConnection().then((end) => { resolve() });
});
});
}
export { getData };
这是 PoolConnection class:
import pg from "pg";
import fetch from "node-fetch";
import { getCurrentDateTime } from "../dateTime.js";
class PoolConnection {
// DO NOT CALL THIS CONSTRUCTOR, CALL THE GETINSTANCE() METHOD
constructor() {
if (!PoolConnection.instance) {
PoolConnection.instance = this;
this.config = {
user: "user",
password: "password",
database: "postgres",
host: "host",
port: 5432,
max: 100,
connectionTimeoutMillis: 30000,
idleTimeoutMillis: 30000
};
this.pool = this.establishConnection(1).catch((error) => { });
}
}
static getInstance() {
if (PoolConnection.instance) {
return PoolConnection.instance;
}
PoolConnection.instance = new PoolConnection();
return PoolConnection.instance;
}
async connect() {
return new Promise((resolve, reject) => {
const poolPromise = new pg.Pool(this.config);
poolPromise.connect()
.then(pool => {
console.log(getCurrentDateTime() + " ----- Connection to article database successful.");
resolve(pool);
})
.catch(err => {
console.error(getCurrentDateTime() + " ----- ERROR CONNECTING TO ARTICLE DATABASE :: " + err);
reject(err);
});
});
}
async establishConnection(attempts) {
return new Promise((resolve, reject) => {
if (attempts > 5) {
console.log(getCurrentDateTime() + " ---- Connection unsuccessful to database, maximum number of attempts reached.");
reject("ERROR");
}
this.connect().then(pool => {
resolve(pool);
}).catch(err => {
console.error(getCurrentDateTime() + " RETRYING CONNECTION TO DATABASE ATTEMPT #" + attempts);
attempts++;
// try again in 3 seconds
setTimeout(() => { this.establishConnection(attempts) }, 3000);
});
})
}
// Connection has to be terminated gracefully or else script will hang.
async endConnection() {
return new Promise((resolve, reject) => {
this.pool.then(connection => connection.end(() => console.log(getCurrentDateTime() + " ---- Connection to database successfully terminated.")));
});
}
async uploadData(data) {
return new Promise((resolve, reject) => {
this.pool.then(async (poolInstance) => {
for(const entry of data) {
let getMoreData = await fetch (
"dummyUrl2" + entry
);
const result = poolInstance.query("INSERT INTO table(data) VALUES ()",
[entry['getMoreData']]);
}
resolve();
});
});
}
}
export { PoolConnection }
它试图在我做任何事情之前关闭连接。这是错误:
> START RequestId: 5aa4984b-d57f-4d69-84a3-005a6c590c0f Version: $LATEST
> 2022-05-03T14:48:11.625Z 5aa4984b-d57f-4d69-84a3-005a6c590c0f INFO 2022-5-3
> **** 14:48:11 ----- Connection to article database successful. 2022-05-03T14:48:12.946Z 5aa4984b-d57f-4d69-84a3-005a6c590c0f INFO 2022-5-3
> **** 14:48:12 ---- Connection to database successfully terminated. 2022-05-03T14:48:14.146Z 5aa4984b-d57f-4d69-84a3-005a6c590c0f ERROR Unhandled Promise Rejection
> {"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"Error:
> Client was closed and is not
> queryable","reason":{"errorType":"Error","errorMessage":"Client was
> closed and is not queryable","stack":["Error: Client was closed and is
> not queryable"," at
> /var/task/node_modules/pg/lib/client.js:570:27"," at
> processTicksAndRejections
> (internal/process/task_queues.js:77:11)"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection:
> Error: Client was closed and is not queryable"," at
> process.<anonymous> (/var/runtime/index.js:35:15)"," at
> process.emit (events.js:400:28)"," at processPromiseRejections
> (internal/process/promises.js:245:33)"," at
> processTicksAndRejections (internal/process/task_queues.js:96:32)"]}
> END RequestId: 5aa4984b-d57f-4d69-84a3-005a6c590c0f REPORT RequestId:
> 5aa4984b-d57f-4d69-84a3-005a6c590c0f Duration: 2985.31 ms Billed
> Duration: 2986 ms Memory Size: 128 MB Max Memory Used: 75 MB Init
> Duration: 267.75 ms
我已经尝试将所有内容转换为 return 一个新的 Promise,然后使用 .then(),但这实际上使程序 运行 不知何故变得更快。我试过使用 Promise.all().then()。我试过将 setTimeout() 移动到 index.js 中的处理程序中,但这也没有用。我试过在 pool.uploadData() 之后使用 then()。我也试过从方法处理程序中删除异步。
我现在没主意了。我已经重构并尝试以我见过的所有方式实现此代码,但没有任何效果。
没有错误或未捕获的异常,只是没有等待。
Lambda 使用的是 NodeJS 版本 14.x
编辑:添加池连接 class 并更新 classes 以更清楚地显示我尝试过的内容。
虽然 getData()
被标记为 async
,但它没有 return 任何明确的承诺,因此它 return 是一个 Promise<void>
立即解析(到undefined
)。
您需要 return 一个明确的 Promise
resolves/rejects 在您的业务逻辑 运行 之后,使 Lambda 实际上等待处理完成。
根据Node.js Lambda docs on async handlers:
If your code performs an asynchronous task, return a promise to make sure that it finishes running. When you resolve or reject the promise, Lambda sends the response or error to the invoker.
例如,此 returns 是一个 Promise
,它在 5 秒后解析,让 Lambda 在它 returns 响应之前等待:
async function getData() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), 5000)
});
}
async function handler(event) {
await getData();
const response = {
statusCode: 200,
body: JSON.stringify("Waiting 5 seconds..."),
};
return response;
}
export { handler };
START RequestId: 0ee7693e-8d6a-4c3f-b23e-119377e633e3 Version: $LATEST
END RequestId: 0ee7693e-8d6a-4c3f-b23e-119377e633e3
REPORT RequestId: 0ee7693e-8d6a-4c3f-b23e-119377e633e3 Duration: 5009.05 ms Billed Duration: 5010 ms Memory Size: 128 MB Max Memory Used: 56 MB Init Duration: 224.62 ms
我添加这个是因为我能够找出问题所在。在之前 answers/comments 的帮助下,我重新格式化了我的代码,因此如果其他人遇到类似问题,希望这会有所帮助。
index.js:
import { getData } from './src/EC2Scripts/taskScripts/otherLogic.js';
async function handler(event) {
await getData();
const response = {
statusCode: 200,
body: JSON.stringify("Now waiting."),
};
return response;
}
export { handler };
其他逻辑class:
import fetch from "node-fetch";
import { PoolConnection } from '../common/classes/PoolConnection.js';
async function getData() {
return new Promise(async (resolve, reject) => {
let pool = await PoolConnection.getInstance();
let currentResponse = await fetch(
"dummyURL"
);
let currentData = await currentResponse.json();
await pool.uploadData(currentData);
await pool.endConnection();
resolve();
});
}
export { getData };
池连接class:
import pg from "pg";
import fetch from "node-fetch";
import { getCurrentDateTime } from "../dateTime.js";
class PoolConnection {
// DO NOT CALL THIS CONSTRUCTOR, CALL THE GETINSTANCE() METHOD
constructor() {
if (!PoolConnection.instance) {
PoolConnection.instance = this;
this.config = {
user: "user",
password: "password",
database: "postgres",
host: "host",
port: 5432,
max: 100,
connectionTimeoutMillis: 30000,
idleTimeoutMillis: 30000
};
this.pool = new pg.Pool(this.config);
}
}
static async getInstance() {
return new Promise(async (resolve, reject) => {
if (PoolConnection.instance) {
return PoolConnection.instance;
}
PoolConnection.instance = new PoolConnection();
resolve(PoolConnection.instance);
});
}
// Connection has to be terminated gracefully or else script will hang.
async endConnection() {
return new Promise(async (resolve, reject) => {
await this.pool.end(() => console.log(getCurrentDateTime() + " ---- Connection to database successfully terminated."));
resolve();
});
}
async uploadData(data) {
return new Promise(async (resolve) => {
let promiseArray = [];
for (const entry of data) {
promiseArray.push(new Promise(async (resolve) => {
await this.pool.connect(async (error, client, release) => {
if (error) {
console.error(getCurrentDateTime() + " ----- Error getting client. Error :: ", error.stack);
}
await client.query("query", (error, result, release) => {
release();
if (error) {
console.error(getCurrentDateTime() + " ----- Error executing query :: ", error.stack);
}
resolve();
});
});
}));
}
await Promise.all(promiseArray);
resolve();
});
}
}
export { PoolConnection }
如果这不能解决您的问题,找到修复的两个最大帮助是