AWS Lambdaでハマッたのは内緒です

Lambdaをやらねばやらねばと1ヶ月以上放置していたがいよいよ使うタイミングとなり、実際に始めてみたらハマッてしまった点についてまとめ。

# V8のバージョンは？

現在のところ 3.14.5.10 の模様、なんでV8のバージョンが気になったのかというと・・。

1. Promiseを書いててエラー
2. あれ？Node.jsってPromise書けないんだっけ？
3. 最近のV8 EngineはPromiseサポートしてるっていう話を聞く
4. え、じゃあ、Lambdaで採用してるNode.jsのV8はいくつなのよ？

ということで調べて納得。
bluebirdという素敵なPromiseモジュールで幸せになった。
promisifyAll() yeaaaaaaaaah!

# contextとevent

ハンドラにわたってくるcontextとeventってなんなのか見てみる。
contextはIDしか入ってないみたいだった。
doneメソッドを呼んでるところを見ると終了時とかにメッセージ渡して死亡宣言に使えばよいのだと推測できる。

eventはそのままLambda起動時のトリガーとなった情報が詰まっていたが、これRecordsが配列になってて複数のイベントで1つのinvokeを構成することって想定されてるのかな？状況が想像出来ないんですけど。
あ。ソースがKinesisとかならありえるな。うんうん。

# 使えるJava実行環境は JRE7 なのかな？

child_processからjavaを起してzip4jを使うコードを実行したところ、見慣れる警告が表示された。
どうも、Lambdaから起動できるJava環境はJRE7ぽいので、バージョン間のクロスコンパイルオプションを忘れずに。

```
$ javac -source 1.7 -target 1.7 hogehoge.java
```

# Java実行環境で環境変数が足りなかった

```
File directory = new File(targetDir);
File[] fileList = directory.listFiles();
ArrayList<File> arrayList = new ArrayList<File>();
for (int i = 0 ; i < fileList.length ; i++) {
    if (fileList[i].isFile()) {
        if (! fileList[i].getName().equals(excludeFile)) {
            arrayList.add(fileList[i]);
            System.out.println(fileList[i].getName());
        }
    }
}
```

上記のようなJavaコードからLambdaの/tmpを走査する仕組みで日本語ファイル名が尽く認識されず困り果てた。

```
var child = require('child_process').spawn('java', ["-cp", "/var/task:/var/task/*", "Hogehoge"],{env :{"LANG":"ja_JP.UTF-8"}});
```

node.jsからJavaを呼び出す時に環境変数(LANG)を追加する必要があった。
これにたどり着くまで1.5日くらい掛かってしまった。

# ログが見にくいなぁ

Lambdaのロググループに書き込まれる順序がよくわからない・・・。これは新しいIDなのか？とりあえず検証中はずっと消しては読み、消しては読みを繰り返して頑張った。GUIからだけでいいからソート機能は無いものだろうか...

# タイムアウトがある

ファイルをS3にアップしたあとパスワード付きZIPにする処理をしてみたけどもメモリーはプログラム側でなんとか節約も出来そうだが、ファイル数が多かったり巨大だと許容実行時間内に処理が終わるかどうかはかなり微妙かもしれない(最大は60秒の模様)

```
var Promise = require('bluebird');

exports.handler = function (event, context) {
    var timeout = function (t) {
        return new Promise(function (resolve, reject) {
            setTimeout(function() {
                resolve();
            },1000*t);
        });
    };
    timeout(10).then(function () {
        console.log('success timeout');
    });
};
```

通常の使い方ではこんな事は考えなくてもよいのかもしれないが、上記のような10秒間動いたあとメッセージを表示するだけのnode.jsコードで実際に試してみた結果は以下の通り。さらにPromiseなのは愛嬌です。

```
2015-02-14T02:30:00.993Z	58f41a02-b3f1-11e4-b1c1-b9fe804855d2	success timeout
Process exited before completing request

END RequestId: 58f41a02-b3f1-11e4-b1c1-b9fe804855d2
REPORT RequestId: 58f41a02-b3f1-11e4-b1c1-b9fe804855d2	Duration: 10322.41 ms	Billed Duration: 10400 ms 	Memory Size: 128 MB	Max Memory Used: 11 MB	

Message
-------
Process exited before completing request::
```

11秒の実行時間では成功したが、10秒の実行時間ではその時点で実行が停止している模様

```
Task timed out after 10.00 seconds

END RequestId: 845204bc-b3f3-11e4-8b4e-211955af3fd6
REPORT RequestId: 845204bc-b3f3-11e4-8b4e-211955af3fd6	Duration: 10000.59 ms	Billed Duration: 10000 ms 	Memory Size: 128 MB	Max Memory Used: 11 MB	

Message
-------
Task timed out after 10.00 seconds::
```

後処理も含め最大60秒以下に実行時間を収めていかないとならない。

# 実行結果の取り扱い

現状ではあまり芳しくない状況
LambdaからS3へJSONを投げてそのS3Putをトリガーにして、処理結果を受け渡す事も出来なくはないだろうけ...こんな使い方は恐らく真っ当じゃない。

# 現在までのまとめ

今回は無理やりLambdaだけで頑張ってみたが、あまりこの仕組みにこだわり過ぎないようにしたほうがいい。EC2側でやるべきことを無理にLambdaに引き込んでもよい結果は得られそうにない。だがこれからも検証は続けていく予定です。