はじめに
なんらかのクライアントからS3にデータを格納したい場合に、例えばデータのチェックをしたり、なんらかの簡単な処理を保存前にかけたいというケースってよくあると思います。
その際にクライアントから送られてくるデータをLambdaで一旦受けて、チェックなり処理を施してからS3に保存するという選択があると思います。
その中でLambdaからS3にデータを保存する場合に、躓きやすい点があります。
下記のコードには問題点があります(Sample1)
なおLambdaFunctionとS3は同一リージョンにあるとします。
var aws = require('aws-sdk');
var s3 = new aws.S3({ apiVersion: '2006-03-01' });
exports.handler = function(event, context) {
// クライアントからデータが渡ってきて、所望の処理を施されてから
// inputedValueに詰められる
var params = {Bucket: 'myBucket', Key: 'myKey', Body: inputedValue};
s3.putObject(params, function(err, data) {
// ログを吐き出すなどS3へのデータ格納の後処理
});
}
上記のコードを実行するとS3にデータは格納されるのですが、実行結果を見てみると下記の通りエラーが発生しています。リクエストが完了する前にプロセスが終了しているというエラーメッセージです。
{
"errorMessage": "Process exited before completing request"
}
LambdaFunctionではリクエストが完了したことを明示的に教えてあげる必要があります。context
の持っているいくつかのメソッドを呼び出すことでリクエストの完了を通知することができ、上記のようなエラーが出なくなります。
下記コードにも問題があります(Sample2)
var aws = require('aws-sdk');
var s3 = new aws.S3({ apiVersion: '2006-03-01' });
exports.handler = function(event, context) {
// クライアントからデータが渡ってきて、所望の処理を施されてから
// inputedValueに詰められる
var params = {Bucket: 'myBucket', Key: 'myKey', Body: inputedValue};
s3.putObject(params, function(err, data) {
// ログを吐き出すなどS3へのデータ格納の後処理
});
context.done();// ここに追加しました
}
上記コードを実行するとエラーが発生しなくなりました。
context.done()
を呼び出すことで明示的にLambdaにリクエストが完了したことを教えてあげているためです。
しかし、S3を見てみると肝心のデータが格納されていません。
これはs3.putObject...
によるデータの格納完了を待たずにcontext.done()
が呼び出されてしまっていることが原因です。
LambdaFunctionを実行するコンテナがcontext.done()
が呼び出されたことによって終了されてしまうのです。
ということで
var aws = require('aws-sdk');
var s3 = new aws.S3({ apiVersion: '2006-03-01' });
exports.handler = function(event, context) {
// クライアントからデータが渡ってきて、所望の処理を施されてから
// inputedValueに詰められる
var params = {Bucket: 'myBucket', Key: 'myKey', Body: inputedValue};
s3.putObject(params, function(err, data) {
// ログを吐き出すなどS3へのデータ格納の後処理
context.done();// ここに移動しました
});
}
ということで、context.done()
はputObjectのコールバック内で呼び出すようにしましょう。
これでputObjectが完了してからcontex.done()が呼び出されるようになるため、前述の「S3にデータが格納される前に処理が終わってしまう」「明示的にリクエスト完了を伝えていないのでエラーが発生する」という問題が解消されました