話題の記事

初めてのJavaScript、初めてのAWS Lambda

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

佐々木です。開発経験も無くJavaScriptを触ったこともない僕ですが、どうしてもAWS lambdaを触ってみたかったので、四苦八苦しながらやってみました。

すでにバリバリ活用しているブログ記事がたくさん出ていますが、本記事は本当に何もわからない僕がよちよち歩きしている内容ですので、深いところは期待しないでください。そして識者のツッコミをお待ちしております。

AWS lambdaの基本的な使い方は以下の記事をご参照ください。

やってみる

MBAにnode.jsをインストールする

とりあえず簡単な構文チェックだけでも手元でやりたいので、MBAにbrewを使ってnode.jsをインストールします。

$ brew install node
$ node -v
v0.10.32

簡単なスクリプトを動かしてみます。

$ vi hello.js
console.log('Hello World');
$ node hello.js
Hello World

これでとりあえず構文チェックは出来ます。もっと良いデバッグ方法があれば是非教えてください。

外部モジュールを使ってみる

AWS lambdaではAWSマネージメントコンソール上で直接jsスクリプトを書く以外に、外部モジュールもまとめてzip化してアップロードすることができます。

AWS_Lambda

外部モジュールを使う場合には、lambdaスクリプトを作成するプロジェクトディレクトリを作ります。

$ mkdir myfunc
$ cd myfunc

外部モジュールをプロジェクトにインストールします。今回はasyncを使ってみました。

$ npm install async

そしてlambdaスクリプトを作成します。

$ vi index.js
var async = require('async');

exports.handler = function(event, context) {
  async.series([
    function (callback) {
      console.log("one");
      callback(null, "one");
    },
    function (callback) {
      console.log("two");
      callback(null, "two");
    },
    function (callback) {
      console.log("three");
      callback(null, "three");
    }
  ], function (err, results) {
    if (err) {
        throw err;
    }
    console.log('all done. ' + results);
  });
};

lambdaスクリプトと外部モジュールをZIP化します。この時プロジェクトディレクトリごとzip化(zip -r myfunc.zip ./myfunc/)すると、ファイルが見つからない(Can't find module)エラーになってしまいますので、以下のようにlambdaスクリプトと外部モジュールディレクトリを指定してzip化します。

$ zip -r myfunc.zip index.js node_modules

このZIPをAWS lambdaにアップロードして実行すると、以下のように動きます。

Logs
----
START RequestId: bf1f1533-75f5-11e4-a765-67c132e1225f
2014-11-27T05:24:52.586Z bf1f1533-75f5-11e4-a765-67c132e1225f one
2014-11-27T05:24:52.625Z bf1f1533-75f5-11e4-a765-67c132e1225f two
2014-11-27T05:24:52.625Z bf1f1533-75f5-11e4-a765-67c132e1225f three
2014-11-27T05:24:52.625Z bf1f1533-75f5-11e4-a765-67c132e1225f all done. one,two,three
Process exited before completing request

END RequestId: bf1f1533-75f5-11e4-a765-67c132e1225f
REPORT RequestId: bf1f1533-75f5-11e4-a765-67c132e1225f Duration: 220.41 ms Billed Duration: 300 ms  Memory Size: 128 MB Max Memory Used: 9 MB 

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

ちゃんと動きました!

AWS SDKを使ってみる

さて、ようやっとlambdaっぽい話になります。lambdaスクリプトからAWS SDKを使ってみました。やっているのは

  • S3 BucketにObjectがPUTされる。
  • 同じBucketに、ファイル名に"copy-"と付与して、コピーを置く。

という流れです。GETとPUTの間にサムネイル作成やリサイズなどの画像変換処理などを組み込むと、さらにlambdaっぽいですね。今度やってみます。

var async = require('async');
var AWS = require('aws-sdk');

var s3 = new AWS.S3();

exports.handler = function(event, context) {
  var Bucket = event.Records[0].s3.bucket.name;
  var srcKey = event.Records[0].s3.object.key;
  var dstKey = "copy-" + srcKey;

  if (srcKey.substr(0,5) ==  'copy-') {
    return;
  }

  async.waterfall([
    function download(callback) {
      console.log('download start:' + srcKey);
      s3.getObject({
        Bucket: Bucket,
        Key: srcKey
      }, function(err, data) {
           if (err) { callback(err); }
           try {
             callback(null, data);
           } catch (e) {
             callback(e);
           }
         }
      );
    },
    function upload(arg1, callback) {
      console.log('upload start:' + dstKey);
      console.log('data:' + arg1.Body);
      s3.putObject({
        Bucket: Bucket,
        Key: dstKey,
        Body: arg1.Body
      }, function(err, data) {
           if (err) { callback(err); }
           try {
             callback(null);
           } catch (e) {
             callback(e);
           }
         }
      );
    }
  ], function (err) {
    if (err) { console.log('Error:' + err); }
    console.log('all done. ');
  });
};

これをAWS lambdaにアップロードし、S3にファイルをPUTすると、自動的にファイルがコピーされます。

S3_Management_Console 2

わーい動いたよー!

まとめ

AWS SDKと外部モジュールの活用がlambdaのキモかなと思いました。それにしても、これまでRubyしかやってこなかったためJavaScriptについては全く知識がなかったのですが、まだ全然わかりません。ちゃんと基礎から勉強しようと思います。