当記事はアカウンティング・サース・ジャパン Advent Calendarの11日目です。
開発グループでマネージャーをしています。
普段コードはほとんど書いていないですが、AWS好きなのでAWSネタで行きます。
先日、Amazon Auroraのストアード・プロシージャーからLambda Functionの呼び出しができるようになったことが発表されました。
https://aws.amazon.com/jp/blogs/news/amazon-aurora-update-call-lambda-functions-from-stored-procedures-load-data-from-s3/
早速試してみましょう!
要件
- 会員テーブルにデータが登録されたら、営業責任者にお褒めの電話
- 会員テーブルからデータが削除されたら、営業責任者にお叱りの電話
構成概要
- Amazon AuroraにUsersテーブルを作成し、INSERTとDELETEのTriggerからストアード・プロシージャーをcallする
- ストアード・プロシージャーからLambdaをキック
- LamdaからTwilio APIをキック
まずはLambdaの設定
「Create a Lambda Function」を押して、「Blank Function」選択
設定は、「VPC」のところは「No VPC」を選択
※ VPCを選択すると、インターネットアクセスする為に一手間かかりますので、今回はこっち。
他の項目は適当に(「Lambda function code」は次項)。
Lambda function code
exports.handler = function(event, context) {
console.log(JSON.stringify(event, null, 2));
var message = new Buffer(event.message, 'base64').toString()
var queryString = require('querystring');
twiml = {
Twiml: '<Response>\n' +
'<Say voice="alice" language="ja-JP">' + message + '</Say>\n' +
'</Response>'
};
url = "http://twimlets.com/echo?" + queryString.stringify(twiml);
var exec = require('child_process').exec;
var cmd = 'curl -XPOST https://api.twilio.com/2010-04-01/Accounts/#####Twilio ACCOUNT SID#####/Calls ' +
'--data-urlencode "Url=' + url + '" ' +
'--data-urlencode "To=+81xxxxxxxxxx" ' +
'--data-urlencode "From=+81xxxxxxxxxx" ' +
'-u "#####Twilio ACCOUNT SID#####:#####Twilio AuthToken#####"';
exec(cmd, function(error, stdout, stderr) {
if (! error) {
console.log('standard out: ' + stdout);
console.log('standard error: ' + stderr);
context.done();
} else {
console.log('error code: ' + error.code);
console.log(error);
context.fail();
}
});
};
以下の値をセットする。
設定項目 | 値 |
---|---|
To | かける相手(≒上司)の電話番号の、頭一桁を除いた番号を設定する |
From | Twilioで取得した番号を設定 |
ACCOUNT SID | TwilioのACCOUNT SID |
AUTH TOKEN | TwilioのAUTH TOKEN |
Amazon Aurora用のRoleの作成
次にまずは、Auroraに設定するRoleを作成します。
- 名前:forAuroraToLambda
- アクセス許可タブのところで、「AWSLamdbaRole」をアタッチ
- 信頼関係タブの編集のところで、"rds.amazonaws.com"をServiceの所に追加
DBインスタンスの作成
設定項目 | 値 |
---|---|
エンジン | Amazon Aurora(当然w) |
パブリックアクセス可能 | はい |
Subnet | Publicで・・・ |
後は適当に。
クラスターにIAMロールを紐付け
- クラスターの画面の上部にある「IAMロールの管理」をクリックする
- そこで先程作成した「forAuroraToLambda」を選択し、完了
DB Cluster Parameter Groupの作成
つぎに「DB Cluster Parameter Group」を作成します。
- 新規で「DB Cluster Parameter Group」を「forLambda」で作成
- パラメータの編集で、「aws_default_lambda_role」の値に、先程作成したRoleのARN(↓のようなやつ)を設定
「arn:aws:iam::xxxxxxxxxx:role/forAuroraToLambda」 - インスタンスの編集画面で、「DB クラスターのパラメータグループ」の値を、「forLambda」に変更
- 再起動
Database、Tableの作成
//Database
create database test;
//Table
create table users (id int auto_increment primary key, name char(100));
ストアード・プロシージャーの作成
DROP PROCEDURE IF EXISTS lambda_test;
DELIMITER ;;
CREATE PROCEDURE lambda_test(IN message VARCHAR(255)) LANGUAGE SQL
BEGIN CALL mysql.lambda_async(
// ↓ここに先程作成したLambdaのARNを設定する
'arn:aws:lambda:ap-northeast-1:xxxxxxxxxx:function:helloTwilio',
CONCAT('{"message":"', to_base64(message), '"}')
);
END
;;
DELIMITER ;
トリガーの作成
// Insert用
DROP TRIGGER IF EXISTS insert_trigger;
DELIMITER ;;
CREATE TRIGGER insert_trigger
AFTER INSERT ON users
FOR EACH ROW
BEGIN
CALL lambda_test('いけてるやん');
END
;;
DELIMITER ;
// Delete用
DROP TRIGGER IF EXISTS delete_trigger;
DELIMITER ;;
CREATE TRIGGER delete_trigger
AFTER DELETE ON users
FOR EACH ROW
BEGIN
CALL lambda_test('あかんがな');
END
;;
DELIMITER ;
では、実際にやってみよう
直接UsersテーブルにレコードをInsertします。
// 会員追加
insert into users(name) values ('hoge');
お褒めの電話がかかりましたか?
// 会員退会処理
delete from users where id = nnn;
お叱りの電話がかかりましたか?
まとめ
Databaseのストアード・プロシージャーからLambdaを呼び出せることにより、様々な連携の実装コストが格段に下がるかもしれません。
ただ、2000年代前半のストアド地獄の二の舞いにならないよう、節度を持って使っていきましょう!
参考
http://dev.classmethod.jp/cloud/aws/invoke-lambda-from-aurora/
http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Aurora.Lambda.html
http://aws.typepad.com/aws_japan/2016/02/access-resources-in-a-vpc-from-your-lambda-functions.html