AWS Lambda の関数の中に DynamoDB のアクセスを記述するようにします。
ここでは、以下を実現します。
- Lambda 関数から、DynamoDBをアクセスします。
- Cognito認証とLambdaで協調しアクセス制限をします。
- mynote-sample-lambda.zip
- 実行方法は、サンプルコードの実行方法を参照してください。
MyNote - Lambda を使用した DynamoDB アプリケーション
設定項目 | 設定値 |
---|---|
AWS サービス | Amazon DynamoDB |
アクション | BatchGetItem BatchWriteItem DeleteItem GetItem PutItem Query UpdateItem UpdateTable |
Amazon リソースネーム | DynamoDB のテーブルのARN |
console.log('Loading mynote_lambda function'); var AWS = require("aws-sdk"); var m_dynamodbDoc = null; var table = "Notes"; var regin = "<リージョン名>"; exports.handler = function(event, context) { switch (event.func) { case 'getNoteList': execGetNoteList(event, context); break; case 'updateNote': execUpdateNote(event, context); break; case 'addNote': execUpdateNote(event, context); break; case 'clearAll': execClearAll(event, context); break; case 'deleteNote': execDeleteNote(event, context); break; default: console.log('unknown event.func=' + event.func); break; } }; function execGetNoteList(event, context) { openDb(); getNoteList(context.identity.cognitoIdentityId, function(isSuccess, data) { if (isSuccess) { context.succeed({"operation" : "new", "notes" : data}); } else { context.fail("failed getNoteList: " + data); } }); } function execUpdateNote(event, context) { openDb(); updateNote(context.identity.cognitoIdentityId, event.param, function(isSuccess, data) { if (isSuccess) { context.succeed({"operation" : "add", "note" : data}); } else { context.fail("failed updateNote: " + data); } }); } function execClearAll(event, context) { openDb(); clearAll(context.identity.cognitoIdentityId, function(isSuccess, data) { if (isSuccess) { context.succeed({"operation" : "new", "notes" : []}); } else { context.fail("failed clearAll: " + data); } }); } function execDeleteNote(event, context) { openDb(); deleteNote(context.identity.cognitoIdentityId, event.param.date_time, function(isSuccess, data) { if (isSuccess) { context.succeed({"operation" : "delete", "note" : data}); } else { context.fail("failed deleteNote: " + data); } }); } function openDb() { if (m_dynamodbDoc === null) { console.log('start open dynamoDB'); AWS.config.update({ region: region, endpoint: "https://dynamodb." + region + ".amazonaws.com" }); m_dynamodbDoc = new AWS.DynamoDB.DocumentClient(); console.log('end open dynamoDB'); } } function getNoteList(userId, callback) { console.log("userId", userId); var params = { "TableName" : table, "KeyConditionExpression": "user_id = :userId", "ExpressionAttributeValues": { ":userId": userId } }; console.log("query param ", JSON.stringify(params)); m_dynamodbDoc.query(params, function(err, data) { var notes = []; if (err) { var errStr = "Unable to query. Error:" + JSON.stringify(err, null, 2); console.log(errStr); callback(false, errStr); } else { console.log("Query succeeded."); var itemSize = data.Items.length; if (itemSize === 0) { callback(true, notes); } else { data.Items.forEach(function(item) { console.log(" -", JSON.stringify(item)); var note = { "user_id" : item.user_id, "date_time" : item.date_time, "text_type" : item.text_type, "text" : item.text }; notes.push(note); }); callback(true, notes); } } }); } function updateNote(userId, item, callback) { var params = { "TableName" : table, "Item" : { "user_id" : userId, "date_time" : item.date_time, "text_type" : item.text_type, "text" : item.text } }; console.log("Adding a new item...", JSON.stringify(params)); m_dynamodbDoc.put(params, function(err, data) { if (err) { console.error("Unable to add item. Error JSON:", JSON.stringify(err, null, 2)); callback(false, JSON.stringify(err)); } else { console.log("Added item:", JSON.stringify(data, null, 2)); callback(true, params.Item); } }); } function deleteNote(userId, dateTime, callback) { var data = { user_id: userId, date_time: dateTime }; var dataList= []; dataList.push(data); deleteItems(dataList, function(isSuccess, deletedItems) { if (isSuccess) { callback(isSuccess, deletedItems[0]); } else { callback(isSuccess, deletedItems); } }); } function clearAll(userId, callback) { var params = { "TableName" : table, "KeyConditionExpression": "user_id = :userId", "ExpressionAttributeValues": { ":userId": userId } }; console.log("query param ", JSON.stringify(params)); m_dynamodbDoc.query(params, function(err, data) { var notes = []; if (err) { var errStr = "Unable to query. Error: " + JSON.stringify(err, null, 2); console.log(errStr); callback(false, errStr); } else { console.log("Query succeeded."); deleteItems(data.Items, callback); } }); } function deleteItems(items, callback) { params = { "RequestItems": { } }; var deletedItems = []; params.RequestItems[table] = []; console.log("test ", JSON.stringify(params)); items.forEach(function(item) { console.log(" -", JSON.stringify(item)); var request = { "DeleteRequest" : { "Key": { "user_id": item.user_id, "date_time" : item.date_time } } }; params.RequestItems[table].push(request); deletedItems.push({ "user_id": item.user_id, "date_time" : item.date_time }); }); console.log("delete req:", JSON.stringify(params)); m_dynamodbDoc.batchWrite(params, function(err, data) { if (err) { var errStr = "Unable to batchWriteItem. Error: " + JSON.stringify(err, null, 2); console.log(errStr); callback(false, errStr); } else { console.log("batchWriteItem succeeded."); callback(true, deletedItems); } }); }
{ func: "要求機能", param: 要求パラメータ }ユーザーIdは、Cognito認証して、Lambda Function の invoke をすると、Lambda の context.identity.cognitoIdentity で取得することができるので、パラメータとはしません。
機能 | func | param |
---|---|---|
Noteリストの取得 | 'getNoteList' | {} |
Noteの追加 | 'addNote' |
{ date_time : 日時, text : テキスト } |
Noteの更新 | 'updateNote' |
{ date_time : 日時, text : テキスト } |
Noteの削除 | 'deleteNote' |
{ date_time : 日時 } |
全Noteの削除 | 'clearAll' | {} |
設定項目 | 設定値 |
---|---|
AWS サービス | AWS Lambda |
アクション | Invoke Function |
Amazon リソースネーム | DynamoDB のテーブルのARN |
cognito.js で、認証してユーザーが使用する role ARN に先ほど作成した、ロールを指定するようにします。
function Cognito() { var m_roleArn = role の ARN; var m_identityPoolId = cognito のプールID;この指定によって、cognitoに認証したユーザーが、MyNodeFunc の Lambda function にアクセスできるようになります。
Lmbdaアクセスは、dbControllerLambda.js で行います。
Cognitoを使用したアプリケーション作成のときのように、index.html のdbContoller を入れ替えるだけで、Lambdaを使ったアクセスができるようになります。
function initApp() { … g_dbControllerLambda = new DbControllerLambda(); g_dbControllerLambda.init(); g_doc.setDbController(g_dbControllerLambda);
function invoke(payLoad, callback) { console.log('AWS.config='); console.log(AWS.config); var lambda = new AWS.Lambda(); var params = { FunctionName : 'MyNoteFunc', InvocationType : 'RequestResponse', Payload : JSON.stringify(payLoad) }; lambda.invoke(params, function(err, data) { if (err) { console.log('error:' + err); callback(false, err); } else { if (data.FunctionError) { console.log('function error:' + data); callback(false, data.Payload); } } else { console.log(data); callback(true, JSON.parse(data.Payload)); } } }); } this.getNoteList = function(userId, callback) { var payload = { func : 'getNoteList', param : {} }; invoke(payload, function(isSuccess, data) { if (isSuccess) { callback(true, data.operation, data.notes); } else { callback(false, data, null); } }); };その他の機能は、dbControllerLambda.js の実装を参照してください。
c:\projects>cd mynote c:\projects\mynote>npm install
var g_region = '<リージョン名>';
var m_roleArn = '<Role ARN>'; var m_identityPoolId = '<cognito identity pool id>';
var region = "<リージョン名>";