AWS Lambda(node.js v18)+ Serverless Framework
Serverless frameworkでAWS Lambda node.v18を動かしたときのメモです。
LambdaをNode.jsのバージョン18で動かそうとすると、AWS SDK for JavaScript v3を使用する必要があります。LambdaでNode v16以前のコードを読み込むとaws-sdkがデフォルトでは読み込まれていないためエラーになります。このAWS SDK for JavaScript v3はv2から大幅に仕様が異なっていて正直しんどい...
そこで、よく使用するS3とDynamoDBの操作をまとめました。
Node.js v18の環境で、aws-sdkを読み込んだときの結果
2023-01-07T02:30:18.629Z undefined ERROR Uncaught Exception
{
"errorType": "Runtime.ImportModuleError",
"errorMessage": "Error: Cannot find module 'aws-sdk'\nRequire stack:\n- /var/task/src/functions/v0_monitoring_download/handler.js\n- /var/runtime/index.mjs",
"stack": [
"Runtime.ImportModuleError: Error: Cannot find module 'aws-sdk'",
"Require stack:",
"- /var/task/src/functions/v0_monitoring_download/handler.js",
"- /var/runtime/index.mjs",
" at _loadUserApp (file:///var/runtime/index.mjs:1000:17)",
" at async UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1035:21)",
" at async start (file:///var/runtime/index.mjs:1200:23)",
" at async file:///var/runtime/index.mjs:1206:1"
]
}
今回は、ローカルでの開発環境構築と、DynamoDBとS3を動かすまでを対応してみます。まずは、必要なライブラリをインストールします。なお、AWSのリソースに対してローカルからはSSO(Single Sign-On)を利用しているので、@aws-sdk/credential-providers
もインストールしています。
npm i -D @aws-sdk/credential-providers
npm i -D @aws-sdk/client-dynamodb
npm i -D @aws-sdk/lib-dynamodb
npm i -D @aws-sdk/client-s3
認証部分
AWS_SDK_LOAD_CONFIG=1のときはローカル動作させるためにprofileを指定しています。
それ以外はlambdaで動作させることを想定してcredentialsをundefinedにしています。
export const config = {
region: 'ap-northeast-1',
credentials: process.env.AWS_SDK_LOAD_CONFIG === '1' ? fromSSO({ profile: 'your-profile' }) : undefined,
}
S3
S3に保存しているのがJSON形式の文字列なので、このようにJSONオブジェクトにしました。v2からはコマンド体型以外にBodyのデータを文字列化するためのコマンドが違っています。res.Body.toString()
では文字列化出来ませんでした。
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
const client = new S3Client(config);
const command = new GetObjectCommand({
Bucket: S3_CLIENT_BUCKET,
Key: S3_KEY,
});
client.send(command).then((res) => res.Body.transformToString()).then((values) => resolve(JSON.parse(values))).catch((err) => {
console.log(err);
reject(err);
})
DynamoDB
v2からコマンド体型がは変わりましたが、使用するパラメータには差が無いようです。
エラーはerr.code
にエラーコードが入っていましたが、v3ではerr.name
にエラーコードが入っているようです。
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { QueryCommand, PutCommand, QueryCommandInput } from "@aws-sdk/lib-dynamodb";
const client = new DynamoDBClient(config);
const command = new QueryCommand({
TableName: DbName,
KeyConditionExpression: '#type = :type AND #timestamp < :from',
ExpressionAttributeNames: {
"#type": "type",
"#timestamp": "timestamp",
},
ExpressionAttributeValues: {
":type": PRIMARY_KEY,
":from": SECONDRY_KEY
}
});
client.send(command).then((values) => {
console.log(values);
}).catch((err)=>{
if (err.name === 'ProvisionedThroughputExceededException') {
// ProvisionedThroughputExceededExceptionの例外処理
} else {
// ProvisionedThroughputExceededException 以外の例外処理
}
});
vscodeの設定
Serverless frameworkを使用して、mock.jsonに記載したS3 Triggerのイベントをローカルで擬似的に発火してテストするためのvscodeの設定になります。
// IntelliSense を使用して利用可能な属性を学べます。
// 既存の属性の説明をホバーして表示します。
// 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "v0_monitorig_download",
"program": "${workspaceFolder}/node_modules/.bin/sls",
"cwd": "${workspaceFolder}",
"request": "launch",
"args": [
"invoke",
"local",
"-f",
"handler",
"--path",
"src/functions/handler/mock.json",
"--aws-profile",
"profile",
],
"skipFiles": [
"<node_internals>/**"
],
"type": "node"
},
]
}