AWS Lambda NodeJS导入返回空模块,但仅在AWS中
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AWS Lambda NodeJS导入返回空模块,但仅在AWS中相关的知识,希望对你有一定的参考价值。
更新
尝试调用我的Lambda函数时出现以下错误
{
"errorType": "TypeError",
"errorMessage": "e is not a function",
"trace": [
"TypeError: e is not a function",
" at Runtime.handler (/var/task/serverless_sdk/index.js:9:88355)",
" at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
]
}
我已将其追溯到对数据库的引用(请参阅schema.js的最后几行,应将数据库导入schema.js的顶部
const { DB } = require('./db.js')
实际上,当我在本地计算机上尝试相同的代码时,没有问题。
这与如何冻结Lambda函数(LF)以便在AWS中重复使用有一些巧妙的方法吗?我应该在哪里初始化LF中的数据库连接?
我尝试将db.js合并到schema.js中(不导入),但仍然出现相同的错误。我已经检查了无服务器加载的zip文件,看起来不错(node_modules和我的)。
这很难调试。因此,朝这个方向的任何提示都会有所帮助。
server.js
const { ApolloServer } = require('apollo-server')
const { ApolloServer: ApolloServerLambda } = require('apollo-server-lambda')
const { typeDefs, resolvers, connect } = require('./schema.js')
// The ApolloServer constructor requires two parameters: your schema
// definition and your set of resolvers.
async function setup(where) {
if (where == 'local') {
const server = new ApolloServer({ typeDefs, resolvers })
let { url } = await server.listen()
console.log(`Server ready at ${url}`)
} else {
const server = new ApolloServerLambda({
typeDefs,
resolvers,
playground: true,
introspection: true,
cors: {
origin: '*',
credentials: true,
},
context: ({ event, context }) => (
{
headers: event.headers,
functionName: context.functionName,
event,
context
})
})
exports.graphqlHandler = server.createHandler()
}
}
let location = (process.env.USERNAME == 'ysg4206') ? 'local' : 'aws'
connect(location, setup)
schema.js
const { gql } = require('apollo-server')
const { GraphQLDateTime } = require('graphql-iso-date')
const { DB } = require('./db.js')
exports.typeDefs = gql`
scalar DateTime
type User {
id: Int
"English First Name"
firstName: String
lastName: String
addressNumber: Int
streetName: String
city: String
email: String
createdAt: DateTime
updatedAt: DateTime
}
type Query {
users: [User]
findUser(firstName: String): User
hello(reply: String): String
}
type Mutation {
addUser(user: UserType): User!
}
type Subscription {
newUser: User!
}
`
exports.resolvers = {
Query: {
users: () => DB.findAll(),
findUser: async (_, { firstName }) => {
let who = await DB.findFirst(firstName)
return who
},
hello: (_, { reply }, context, info) => {
console.log(`hello with reply ${reply}`)
console.log(`context : ${JSON.stringify(context)}`)
console.log(`info : ${JSON.stringify(info)}`)
return reply
}
},
Mutation: {
addUser: async (_, args) => {
let who = await DB.addUser(args.user)
return who
}
}
}
exports.connect = async (where, setup) => {
console.log(`DB: ${DB}') // BUG DB is returning null
await DB.dbSetup(where) //BUG these lines cause Lambda to fail
await DB.populate() //BUG these lines cause Lambda to fail
let users = await DB.findAll() //BUG these lines cause Lambda to fail
console.log(users) //BUG these lines cause Lambda to fail
await setup(where)
}
db.js
const { Sequelize } = require('sequelize')
const { userData } = require('./userData')
const localHost = {
db: 'm3_db',
host: 'localhost',
pass: 'xxxx'
}
const awsHost = {
db: 'mapollodb3_db',
host: 'apollodb.cxeokcheapqj.us-east-2.rds.amazonaws.com',
pass: 'xxxx'
}
class DB {
async dbSetup(where) {
let host = (where == "local") ? localHost : awsHost
this.db = new Sequelize(host.db, 'postgres', host.pass, {
host: host.host,
dialect: 'postgres',
logging: false,
pool: {
max: 5,
min: 0,
idle: 20000,
handleDisconnects: true
},
dialectOptions: {
requestTimeout: 100000
},
define: {
freezeTableName: true
}
})
this.User = this.db.define('users', {
firstName: Sequelize.STRING,
lastName: Sequelize.STRING,
addressNumber: Sequelize.INTEGER,
streetName: Sequelize.STRING,
city: Sequelize.STRING,
email: Sequelize.STRING,
})
try {
await this.db.authenticate()
console.log('Connected to DB')
} catch (err) {
console.error('Unable to connect to DB', err)
}
}
async select(id) {
let who = await this.User.findAll({ where: { id: id } })
return who.get({ plain: true })
}
async findFirst(name) {
let me = await this.User.findAll({ where: { firstName: name } })
return me[0].get({ plain: true })
}
async addUser(user) {
let me = await this.User.create(user)
return me.get({ plain: true })
}
async populate() {
await this.db.sync({ force: true })
try {
await this.User.bulkCreate(userData, { validate: true })
console.log('users created');
} catch (err) {
console.error('failed to create users')
console.error(err)
} finally {
}
}
async findAll() {
let users = await this.User.findAll({ raw: true })
return users
}
async close() {
this.db.close()
}
}
exports.DB = new DB()
serverless.yml
service: apollo-lambda
provider:
name: aws
stage: dev
region: us-east-2
runtime: nodejs10.x
# cfnRole: arn:aws:iam::237632220688:role/lambda-role
functions:
graphql:
# this is formatted as <FILENAME>.<HANDLER>
handler: server.graphqlHandler
vpc:
securityGroupIds:
- sg-a1e6f4c3
subnetIds:
- subnet-4a2a7830
- subnet-1469d358
- subnet-53b45038
events:
- http:
path: graphql
method: post
cors: true
- http:
path: graphql
method: get
cors: true
拉链的文件夹结构
当AWS Lambda导入文件时,导出尚不可用。这就是为什么它抱怨您的处理程序不是函数(因为当时它实际上是undefined
,正在被导入)。
以下是一些建议的解决方案:
1。仅使用apollo-server-lambda
并使用serverless-offline
进行本地开发。这样,您的处理程序代码便与Lambda中的代码完全相同。
serverless-offline
2。在Lambda中使用const { ApolloServer: ApolloServerLambda } = require("apollo-server-lambda");
const { typeDefs, resolvers, connect } = require("./schema.js");
const server = new ApolloServerLambda({
typeDefs,
resolvers,
playground: true,
introspection: true,
cors: {
origin: "*",
credentials: true
},
context: ({ event, context }) => ({
headers: event.headers,
functionName: context.functionName,
event,
context
})
});
exports.graphqlHandler = server.createHandler();
,但在另一个文件(例如local.js)中使用apollo-server-lambda
。。然后,只需使用apollo-server
进行本地开发。不需要该node local.js
最后检查您所做的。
发现了问题。有点尴尬。但如果其他人需要它,我会发布它。
我正在尝试连接到数据库,作为lambda应用程序初始化的一部分。希望在发生冷启动或热启动时,带有DB的变量已经保存了连接。
这是反模式。
对于阿波罗,每个请求都必须重新连接到数据库。在GraphQL的解析器中,必须重新连接到数据库,然后关闭它,以便AWS可以看到没有打开的连接,然后关闭Lambda函数。
以上是关于AWS Lambda NodeJS导入返回空模块,但仅在AWS中的主要内容,如果未能解决你的问题,请参考以下文章
在 AWS Lambda 上使用 nodejs“ref”模块时出现“无效的 ELF 标头”
aws lambda 无法导入模块“lambda_function”:没有名为“requests”的模块
从 aws-lambda 导入 pysftp 时如何修复导入错误“没有名为 '_cffi_backend' 的模块”
AWS Lambda Python 3.7:无法导入模块'lambda_function':缺少必需的依赖项['numpy']