AWS LambdaのCustom RuntimeでElixirを動かし、DynamoDBのGET/PUTを試してみます。
環境
- Windows 10 Pro 64bit
- VSCode 1.38.1
- Docker Desktop for Windows 2.1.0.4
- Docker Engine 19.03.4
事前準備
こちらで作った環境をベースに作業を進めます。
参考資料
alertlogic社のサンプルコードをベースに都度試しながら進めます。
環境変数の読込
AWS Lambdaの環境変数に設定したキーに対する値をログに出力します。
-
lib/lambda_ex.ex
- 以下の通り変更を加え、
MIX_ENV=prod mix erllambda.release
を実行しリリース用モジュールをリビルド。出来上がったzipファイルをAWS Lambdaへ反映- ログへの環境変数の内容出力を追加
- 以下の通り変更を加え、
defmodule LambdaEx do
def handle(event, context) do
:erllambda.message("event: ~p", [event])
:erllambda.message("context: ~p", [context])
+ :erllambda.message("envName: ~p", [System.get_env("ENV_NAME")])
{:ok, response({:ok, [[{"result", "OK"}]]})}
end
defp items_to_json(items) do
items
|> Enum.map(&:maps.from_list/1)
|> :jiffy.encode
end
defp response({:ok, response}) do
%{
statusCode: "200",
body: items_to_json(response),
headers: %{
"Content-Type": "application/json"
}
}
end
defp response({:error, response}) do
%{
statusCode: "400",
body: response,
headers: %{
"Content-Type": "application/json"
}
}
end
end
DynamoDBからGET
-
テスト用のテーブルを作成
- テーブル名:
TEST_ITEMS
- プライマリキー:
code
(string) - 設定:デフォルト
- テーブル名:
-
テスト用のレコードを作成
-
lib/lambda_ex.ex
- 以下の通り変更を加え、モジュールリビルド&AWS Lambdaへ反映
- 環境変数からテーブル名取得を追加
- テーブルからの全件取得を追加
- テーブルから取得した値をレスポンスに追加
- 以下の通り変更を加え、モジュールリビルド&AWS Lambdaへ反映
defmodule LambdaEx do
def handle(event, context) do
:erllambda.message("event: ~p", [event])
:erllambda.message("context: ~p", [context])
+ # :erllambda.message("envName: ~p", [System.get_env("ENV_NAME")])
+ table_name = System.get_env("TABLE_NAME")
+ result = scan_all(table_name)
+ # {:ok, response({:ok, [[{"result", "OK"}]]})}
+ {:ok, response(result)}
end
+ defp scan_all(table_name) do
+ :erlcloud_ddb_util.scan_all(table_name)
+ end
defp items_to_json(items) do
items
|> Enum.map(&:maps.from_list/1)
|> :jiffy.encode
end
defp response({:ok, response}) do
%{
statusCode: "200",
body: items_to_json(response),
headers: %{
"Content-Type": "application/json"
}
}
end
defp response({:error, response}) do
%{
statusCode: "400",
body: response,
headers: %{
"Content-Type": "application/json"
}
}
end
end
DynamoDBへPUT
-
lib/lambda_ex.ex
- 以下の通り変更を加え、モジュールリビルド&AWS Lambdaへ反映
- AWS LambdaのeventパラメータをそのままDynamoDBへPUTする処理を追加
- 以下の通り変更を加え、モジュールリビルド&AWS Lambdaへ反映
defmodule LambdaEx do
def handle(event, context) do
:erllambda.message("event: ~p", [event])
:erllambda.message("context: ~p", [context])
# :erllambda.message("envName: ~p", [System.get_env("ENV_NAME")])
table_name = System.get_env("TABLE_NAME")
+ put_item(event, table_name)
result = scan_all(table_name)
# {:ok, response({:ok, [[{"result", "OK"}]]})}
{:ok, response(result)}
end
defp scan_all(table_name) do
:erlcloud_ddb_util.scan_all(table_name)
end
+ defp put_item(item, table_name) do
+ :erlcloud_ddb2.put_item(table_name, :maps.to_list(item))
+ end
defp items_to_json(items) do
items
|> Enum.map(&:maps.from_list/1)
|> :jiffy.encode
end
defp response({:ok, response}) do
%{
statusCode: "200",
body: items_to_json(response),
headers: %{
"Content-Type": "application/json"
}
}
end
defp response({:error, response}) do
%{
statusCode: "400",
body: response,
headers: %{
"Content-Type": "application/json"
}
}
end
end
所感
erlcloudを使うことで簡単にAWSのリソースへアクセスすることができました。また、Docker + VSCodeのリモートアクセス機能を使うことでビルド~反映が簡単になりました。あとはlocalstackである程度動作確認してから反映できればより良いと思います。