You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

共享PostgreSQL连接的AWS Node.js 2.x Lambda第二个无返回值求助

Node.js TypeScript Lambda 无返回值问题排查与解决

项目结构

project-root/
│
├── src/
│   ├── lambda1/
│   │   ├── index.ts
│   │   ├── Service.ts
│   │   ├── package.json
│   │   └── tsconfig.json
│   │
│   ├── lambda2/
│   │   ├── index.ts
│   │   ├── Service.ts  // 注:原描述中为Service.json,推测应为Service.ts
│   │   ├── package.json
│   │   └── tsconfig.json
│   │
│   └── shared/
│       ├── dbconnect.ts
│       ├── constants.ts
│
├── tsconfig.json
├── package.json

问题现象

部署两个Lambda后,第一个Lambda可正常返回数据,但第二个Lambda既无返回值也不抛出错误,日志如下:

INIT_START Runtime Version: nodejs:20.v15 Runtime Version ARN: arn:aws:lambda:us-east-2::runtime:0856f5d760b75612d4aa6b5feda50bafc1ce3ba07c036cbd0abc585dc28fb870
START RequestId: 85af3fa6-2044-4664-9d67-9890be0a088a Version: $LATEST
2024-02-16T10:59:14.484Z 85af3fa6-2044-4664-9d67-9890be0a088a INFO Inside GetLegalDashBoardData
2024-02-16T10:59:14.523Z 85af3fa6-2044-4664-9d67-9890be0a088a INFO Inside Service connectionString
2024-02-16T10:59:14.524Z 85af3fa6-2044-4664-9d67-9890be0a088a INFO Inside ConnectToDatabase
2024-02-16T10:59:14.726Z 85af3fa6-2044-4664-9d67-9890be0a088a INFO Inside ConnectToDatabase before return
2024-02-16T10:59:14.726Z 85af3fa6-2044-4664-9d67-9890be0a088a INFO After ConnectToDatabase
END RequestId: 85af3fa6-2044-4664-9d67-9890be0a088a
REPORT RequestId: 85af3fa6-2044-4664-9d67-9890be0a088a Duration: 525.35 ms Billed Duration: 526 ms Memory Size: 128 MB Max Memory Used: 76 MB Init Duration: 191.40 ms

关键代码分析

dbconnect.ts 原代码

import { IDatabase, IMain } from 'pg-promise';
import pgpromise from 'pg-promise';

async function ConnectToDatabase(user: string, password: string, host: string, port: number, database: string): Promise<IDatabase<any>> {
try {
    console.log("Inside ConnectToDatabase");
    const pgp = pgpromise();
    const connectionOptions = {
        host: host,
        port: port,
        database: database,
        user: user,
        password: password,
    };

    const dbClient = pgp(connectionOptions)
    console.log("Inside ConnectToDatabase before return");
    return dbClient;
} catch (error) {
    console.error('Error connecting to the database:', error);
    throw error;
}
}

export async function ExecuteFunction(query: string, connectionParams: any) {
try {
    const dbCreds = JSON.parse(connectionParams);
    const plsqlQuery: any = JSON.parse(query)
    const dbInstance = await ConnectToDatabase(dbCreds.user, dbCreds.password, dbCreds.host, dbCreds.port, dbCreds.database);
    console.log(`After ConnectToDatabase`)
    const result = dbInstance.func(plsqlQuery.funcName, plsqlQuery.params);
    return result;
} catch (error) {
    console.error('ExecuteFunction Error in Fetching Records From the database:', error);
    throw error;
}
}

Service.ts 原代码

import { config } from '../../../shared/config/whub_config';
import { ExecuteFunction } from '../../../shared/data_access/whub_data_service';
export async function GetLegalDashBoardData() {
    console.log("Inside GetLegalDashBoardData")
    try {

        const dbCred: any = GetHubDBCredentials();
        const query: any = {
            funcName: `${config.WHUB_LEGAL_SCHEMA}.${config.LEGAL_GET_DASHBOARD_DATA}`,
            params:"test"
        }
        console.log(`Inside Service connectionString`)
        const result = await ExecuteFunction(JSON.stringify(query),JSON.stringify(dbCred));
         return result;
    } catch (error) {
        console.error('Error executing query', error);
        console.log('Error executing query', JSON.stringify(error));
    }
}

问题根源

  1. 未等待数据库函数执行:ExecuteFunction中调用dbInstance.func()时未添加await,该方法返回Promise,但代码直接返回未解析的Promise,导致Lambda在数据库查询完成前就因事件循环为空而终止,无返回结果。
  2. 不必要的异步包装:ConnectToDatabase函数被标记为async,但内部没有异步操作(pg-promise实例化是同步的,连接是懒加载),多余的async会导致返回Promise,但实际不需要。
  3. 重复创建pgp实例:每次调用ConnectToDatabase都新建pgp实例,可能导致资源泄漏或连接问题。

修复方案

1. 修改dbconnect.ts,添加await并优化实例创建

import { IDatabase } from 'pg-promise';
import pgpromise from 'pg-promise';

// 全局单例pgp实例,避免重复创建
const pgp = pgpromise();

// 移除不必要的async,同步返回数据库实例
function ConnectToDatabase(user: string, password: string, host: string, port: number, database: string): IDatabase<any> {
    try {
        console.log("Inside ConnectToDatabase");
        const connectionOptions = {
            host,
            port,
            database,
            user,
            password,
        };

        const dbClient = pgp(connectionOptions);
        console.log("Inside ConnectToDatabase before return");
        return dbClient;
    } catch (error) {
        console.error('Error connecting to the database:', error);
        throw error;
    }
}

export async function ExecuteFunction(query: string, connectionParams: string) {
    try {
        const dbCreds = JSON.parse(connectionParams);
        const plsqlQuery = JSON.parse(query) as { funcName: string; params: any };
        const dbInstance = ConnectToDatabase(dbCreds.user, dbCreds.password, dbCreds.host, dbCreds.port, dbCreds.database);
        console.log(`After ConnectToDatabase`);
        
        // 关键:await数据库函数执行,确保等待查询完成
        const result = await dbInstance.func(plsqlQuery.funcName, plsqlQuery.params);
        return result;
    } catch (error) {
        console.error('ExecuteFunction Error in Fetching Records From the database:', error);
        throw error;
    }
}

2. 确保Lambda Handler正确等待结果

检查lambda2的index.ts,确保handler正确await GetLegalDashBoardData并返回结果:

import { GetLegalDashBoardData } from './Service';

export const handler = async () => {
    try {
        const data = await GetLegalDashBoardData();
        return {
            statusCode: 200,
            body: JSON.stringify(data)
        };
    } catch (error) {
        console.error('Handler failed:', error);
        return {
            statusCode: 500,
            body: JSON.stringify({ message: 'Failed to retrieve dashboard data' })
        };
    }
};

3. 补充异常处理(可选)

在GetLegalDashBoardData中,若catch块未抛出错误,会返回undefined,建议在catch中重新抛出错误或返回明确错误对象,确保Handler能捕获并处理:

export async function GetLegalDashBoardData() {
    console.log("Inside GetLegalDashBoardData")
    try {
        const dbCred: any = GetHubDBCredentials();
        const query: any = {
            funcName: `${config.WHUB_LEGAL_SCHEMA}.${config.LEGAL_GET_DASHBOARD_DATA}`,
            params:"test"
        }
        console.log(`Inside Service connectionString`)
        const result = await ExecuteFunction(JSON.stringify(query),JSON.stringify(dbCred));
         return result;
    } catch (error) {
        console.error('Error executing query', error);
        // 重新抛出错误,让Handler处理
        throw error;
    }
}

额外检查项

  • 确认第二个Lambda的VPC、安全组配置与第一个一致,确保能访问数据库
  • 检查数据库函数${config.WHUB_LEGAL_SCHEMA}.${config.LEGAL_GET_DASHBOARD_DATA}是否存在且权限正确
  • 验证GetHubDBCredentials返回的数据库凭证是否正确

内容的提问来源于stack exchange,提问作者balajivaishnav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 19:44:55