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

Serverless+TypeORM+AWS Lambda数据库初始化时机问题求助

问题描述

我正在开发一个基于TypeScript、Serverless、TypeORM和AWS Lambda的项目,数据库初始化代码写在data-source.ts中:

export const AppDataSource = new DataSource({
  type: "postgres",
  host: "localhost",
  port: 5432,
  username: "use",
  password: "pass",
  database: "dbname",
  synchronize: false,
  logging: true,
  entities: [CarEntity],
  subscribers: [],
  migrations: [],
})

// * (see below)This code is in the initDB() function that I call in the create function.
AppDataSource.initialize()
  .then(async () => {
    console.log("DB Initialized")
  })
  .catch((error) => console.log("Error: ", error))

目前遇到的问题是:数据库还未完成初始化,handler函数就已执行,导致报错信息为"errorMessage": "No metadata for \"CarEntity\" was found."。若在create handler中取消注释await initDB()代码,即可正常创建并保存Car实体到数据库。

项目的serverless.yml配置如下:

service: aws-node-typescript # NOTE: update this with your service name
frameworkVersion: '3'
provider:
  name: aws
  runtime: nodejs18.x
functions:
   create:
    handler: src/handler.create
    events:
      - http:
          path: ''
          method: 'post'
   update:
    handler: src/handler.update
    events:
      - http:
          path: ''
          method: 'put'
   get:
    handler: src/handler.get
    events:
      - http:
          path: ''
          method: 'get'
plugins:
  - serverless-esbuild

想请教:数据库的正确初始化位置应该在哪里?


解决方案

在AWS Lambda环境下,TypeORM的数据源初始化必须确保在handler执行前完成异步初始化,不能依赖顶层的AppDataSource.initialize()(因为Lambda冷启动时,顶层代码的异步操作不会等待完成就会执行handler)。

正确的实现步骤:

  1. 封装带单例判断的初始化函数
    修改data-source.ts,把初始化逻辑改成可等待的异步函数,同时判断数据源是否已初始化,避免重复操作:
// data-source.ts
import { DataSource } from "typeorm"
import { CarEntity } from "./entities/CarEntity"

export const AppDataSource = new DataSource({
  type: "postgres",
  host: "localhost",
  port: 5432,
  username: "use",
  password: "pass",
  database: "dbname",
  synchronize: false,
  logging: true,
  entities: [CarEntity],
  subscribers: [],
  migrations: [],
})

export async function initDB() {
  if (!AppDataSource.isInitialized) {
    await AppDataSource.initialize()
    console.log("DB Initialized")
  }
}
  1. 在每个Lambda handler开头执行初始化
    所有需要操作数据库的handler,都要在业务逻辑前await initDB():
// src/handler.ts
import { initDB } from './data-source'
import { AppDataSource } from './data-source'
import { CarEntity } from './entities/CarEntity'

export const create = async (event: any) => {
  // 先确保数据库初始化完成
  await initDB()
  
  const carRepository = AppDataSource.getRepository(CarEntity)
  // 执行创建Car实体的业务逻辑...
}

export const update = async (event: any) => {
  await initDB()
  // 执行更新逻辑...
}

export const get = async (event: any) => {
  await initDB()
  // 执行查询逻辑...
}
  1. 关键原因说明
    Lambda的执行机制是:冷启动时加载代码并执行顶层逻辑,但顶层的异步操作(比如.then()链式调用)不会阻塞handler的执行,导致handler运行时数据源还未完成初始化,触发"No metadata"错误。而在handler内使用await可以强制等待初始化完成后再执行业务代码,同时isInitialized判断能在热启动时复用已初始化的数据源,提升请求处理效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 22:33:27