AWS Lambda で SimpleDB のテーブルをCSVにエクスポートする

AWS Lambda で SimpleDB や DynamoDB のテーブルダンプを作成したい場合、60秒制限があるため、処理を分割する必要があります。以下の関数では、SimpleDB のクエリを発行してカーソルを次の Lambda の処理に受け渡すようにしています。

process.env.TZ="Asia/Tokyo";
var aws = require('aws-sdk');
var s3 = new aws.S3({apiVersion: '2006-03-01', region: 'ap-northeast-1'});
var sdb = new aws.SimpleDB({apiVersion: '2009-04-15', region: 'ap-northeast-1'});

var exportBucket = "";
var exportKey = "";
var exportSql = "";

function fetch(body, nextToken, callback) {
    var params = {
        SelectExpression: exportSql,
        ConsistentRead: true,
        NextToken: nextToken
    };
    sdb.select(params, function(err, data) {
       if (err) {
           callback(null);
       } else {
           var result = [];
           data.Items.forEach(function(item) {
               var record = [];
               item.Attributes.forEach(function(attr) {
                    // ダンプしたいデータを作成
                });
                result.push(record);
            });
            var csv = body;
            result.forEach(function(item) {
            csv += item.map(function(field) {
                return '"' + field.toString().replace(/\"/g, '""') + '"';
            }).toString("utf-8") + '\n';
            });
            save(csv, function() {
                callback(data.NextToken);
            });
       }
   });
}

function start(body, next, context) {
    fetch(body, next, function(nextToken) {
        if(nextToken) {
            chain(nextToken, function() {
                console.log("next chain to " + nextToken);
                context.succeed("next");
            });
        } else {
            console.log("chain end.");
            context.succeed("success");
        }
    });
}

function chain(nextToken, callback) {
  s3.putObject({
      Bucket: "bucket",
      Key: "1",
      Body: new Buffer(nextToken, 'binary')
  }, function(err, data) {
      if(callback) {
          callback();
      }
  });
}

function save(csv, callback) {
  s3.putObject({
      Bucket: exportBucket,
      Key: exportKey,
      Body: new Buffer(csv, 'utf-8'),
      ContentType: "application/text; charset=UTF-8"
  }, function(err, data) {
      if(callback) {
          callback();
      }
  });
}


exports.handler = function(event, context) {
    if(event.Records) {
        var bucket = event.Records[0].s3.bucket.name;
        var key = event.Records[0].s3.object.key;
        var params = {
            Bucket: bucket,
            Key: key
        };
        s3.getObject(params, function(err, data) {
            if (err) {
                context.done("error");
            } else {
                var next = data.Body.toString("utf-8");
                if(next == "0") {
                   next = null  
                } else {
                    var params = {
                        Bucket: exportBucket,
                        Key: exportKey
                    };
                    s3.getObject(params, function(err, data) {
                        var body = "";
                        if (err) {

                        } else {
                            body = data.Body.toString("utf-8");
                        }
                        start(body, next, context);
                    });
                }
            }
        });
    } else {
        start("", null, context);
    }
};