超爆速　LambdaでDenoを動かしてみる

私はLambdaが大好きだ。
もう全てLambdaで動かせばいいんじゃないかな？（少なくともAPIはAPIGateway + Lambdaで十分だと思ってる。）

それはさておき

そんなLambdaでDenoを爆速で動かす方法をまとめてみた。

# 前提条件

 - aws cliが使用できる
 - 実行環境はmac

# 1.Layerの登録

## deno-lambda-layer.zipをダウンロード

```sh
$ curl -OL https://github.com/hayd/deno-lambda/releases/download/1.11.0/deno-lambda-layer.zip
```

※ <a href="https://github.com/hayd/deno-lambda/releases">公式サイト</a>より最新のアーカイブファイルをダウンロードすることを推奨

## deno-lambda-layerを登録

```sh
$ aws lambda publish-layer-version \
  --layer-name deno-lambda-layer \
  --zip-file fileb://deno-lambda-layer.zip
```

```実行結果.json
{
    "Content": {
        "Location": "xxx",
        "CodeSha256": "xxx",
        "CodeSize": 31586895
    },
    "LayerArn": "arn:aws:lambda:ap-northeast-1:xxx:layer:deno-lambda-layer",
    "LayerVersionArn": "arn:aws:lambda:ap-northeast-1:xxx:layer:deno-lambda-layer:1",
    "Description": "",
    "CreatedDate": "9999-99-99T99:99:99.999+0000",
    "Version": 1
}
```

LayerVersionArnを使用するので控えること。

# 2.実行Roleの作成

role作成済みの場合はSKIP

## 定義ファイル作成

```sh
$ vim role.json
```

```role.json
{
    "Version": "2012-10-17",
    "Statement":[
        {
            "Effect": "Allow",
            "Principal":{
                "Service":"lambda.amazonaws.com"
            },
            "Action":"sts:AssumeRole"
        }
    ]
}
```

## role作成

```sh
$ aws iam create-role \
  --role-name deno-function-exec-role \
  --assume-role-policy-document file://role.json
```

```実行結果.json
{
    "Role": {
        "Path": "/",
        "RoleName": "deno-function-exec-role",
        "RoleId": "xxxx",
        "Arn": "arn:aws:iam::xxxx:role/deno-function-exec-role",
        "CreateDate": "9999-99-99T99:99:99.999+0000",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "lambda.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
    }
}
```

Arnを使用するので控えること。

# 3.LambdaDeploy

## Create index.ts

```sh
$ vim index.ts
```

```index.ts
import { Context, Event } from "https://deno.land/x/lambda/mod.ts";

export function handler(event: Event, context: Context) {
  const message:String = `Hey deno ${Deno.version.deno}.`
  console.log(message)
  return {
    statusCode: 200,
    body: message
  }
}
```

## Deploy

```sh
$ zip index.zip index.ts
$ aws lambda create-function \
  --function-name DenoFunction \
  --runtime provided.al2 \
  --handler index.handler \
  --zip-file fileb://index.zip \
  --role arn:aws:iam::xxxx:role/deno-function-exec-role \
  --region ap-northeast-1
```

--roleに2.実行ロールで作成で控えたArnを定義して実行

```実行結果.
割愛。
エラーが発生していなければOK。
```

## Layerの登録

```sh
$ aws lambda update-function-configuration \
  --function-name DenoFunction \
  --layers \
    "arn:aws:lambda:ap-northeast-1:xxx:layer:deno-lambda-layer:1"
```

--layersに1.Layerの登録で控えたLayerVersionArn定義して実行

```実行結果.
割愛。
エラーが発生していなければOK。
```

## 動作確認

```sh
$ aws lambda invoke  \
  --function-name DenoFunction \
  --log-type Tail \
  outputfile.txt \
  --query 'LogResult' | tr -d '"' | base64 -D
```

```実行結果.
START RequestId: xxxx Version: $LATEST
Hey deno 1.11.0.d: xxxx
END RequestId: xxxx
REPORT RequestId: xxxx	Duration: 76.08 ms	Billed Duration: 1804 ms	Memory Size: 128 MB	Max Memory Used: 76 MB	Init Duration: 1727.22 ms
```
ちゃんと動いた、
これで完了。

# 番外編

やっぱりDenoらしいコードでも試してみたいよね。

メインロジックを分離する想定で、

```index.ts
import { Context, Event } from "https://deno.land/x/lambda/mod.ts";
import { execute } from "./usecase.ts";

export function handler(event: Event, context: Context) {
  const message:String = execute()
  console.log(message)
  return {
    statusCode: 200,
    body: message
  }
}
```

```usecase.ts
export function execute(): String {
  return 'My son is an angel'
}
```

ほいで更新

```sh
$ zip index.zip *.ts
$ aws lambda update-function-code \
  --function-name DenoFunction \
  --zip-file fileb://index.zip
```

最後に実行

```sh
aws lambda invoke  \
  --function-name DenoFunction \
  --log-type Tail \
  outputfile.txt \
  --query 'LogResult' | tr -d '"' | base64 -D
```

```実行結果.
START RequestId: xxxx Version: $LATEST
My son is an angel xxxx
END RequestId: xxxx
REPORT RequestId: xxxx	Duration: 74.14 ms	Billed Duration: 1360 ms	Memory Size: 128 MB	Max Memory Used: 76 MB	Init Duration: 1285.37 ms
```

できた。

# まとめ

・TypeScriptの記法で実装できたり、node_modules管理が無くなったり、awaitの使い勝手が良くなったりと利便性が高いので真面目に導入するのもアリかと。
次はもうちょっと実務に耐えれる設計や、CI/CDの導入など考慮してみたい。


・Denoのアイコンってチンアナゴ？
![20190204030029.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300430/1a342f63-d515-0a3b-9172-bd6c446d788d.png)