【GCP】Cloud Taskへのキュー登録メモ（＋Cloud Functionsをコールする）

自分用のメモ。

# Cloud Taskの作成

まずCloud Taskの画面から「PUSHキューの作成」を押してCloud Taskそのものを作成する。ちなみに作成後に名前は変えられないみたい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392942/6e92300f-c140-48b9-4c30-7e986cd0aa9b.png)

詳細設定がいろいろ指定できるがよくわからんので全部初期設定のままとする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392942/a6c3b494-bd5a-e7b6-d447-175a363957dd.png)

と思ったんだが「最大試行回数」はデフォの100からもう少し下げてもいいかもしれない。ちょっとミスってタスク登録してしまってコール先のCloud Functionsがエラーになり、それが無邪気に100回繰り返されてログが結構えらいことになった。。まあコール先の都合に合わせて各自適宜調整してください。

# Cloud Taskにキューの登録

コード書かないとだめらしい。基本は以下に載っている。以下GitHubのものを「サンプルコード」と記述して本記事内で参照・抜粋していく。
https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/HEAD/cloud-tasks/tutorial-gcf/app/createTask.js
https://cloud.google.com/tasks/docs/tutorial-gcf?hl=ja

## credential指定

サンプルコードだとデフォルトのクレデンシャルを使って処理しようとするため、任意のクレデンシャルを利用する場合(特定のプロジェクト向けにタスクを発行したいとか)は `CloudTasksClient` の引数に [Authenticaion Option](https://github.com/googleapis/gax-nodejs/blob/main/client-libraries.md#authentication-options) の指定が必要。
以下のような感じ。`credentials.client_email`、`credentials.private_key`はいずれもService AccountのJSONファイルに同名フィールドがあるので、それそのままコピって貼り付ければよい。

```javascript
    const options = {
        credentials: {
            client_email: '<member>@<project-id>.iam.gserviceaccount.com',
            private_key: '...'
        },
        projectId: 'hogehoge'
    };
  const {v2beta3} = require('@google-cloud/tasks');
  const client = new v2beta3.CloudTasksClient(options);
```

Authentication Optionの解説Doc見ると他にもいろいろ指定できるみたいだが、少なくとも私の場合は上のフィールドを適切に埋めただけでなんとかなりました。

参考：
https://stackoverflow.com/questions/60394894/cloudtasks-createtask-fails-lacks-iam-permission-cloudtasks-tasks-create-ev

## Service AccountのPermission

いかにも意味ありげな「Cloud Taskサービスエージェント」「Cloud Tasksタスク実行者」とかいうロールがあるのでこれを付けておく。単にタスクの作成をするだけならどっちかだけでいいかもしれない。よくわからん。私は両方付けちゃいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392942/240b0784-074e-48de-c8b7-e037904336d7.png)

## 未来日時のスケジュール

サンプルコードに大体書いてあるのだが、例えば10分後とかにするなら以下の要領で発行可能

```javascript
    let date = new Date();
    const currentTimeInMillis = date.getTime();
    const after10MinutesTimeInMilllis = currentTimeInMillis + (10 * 60 * 1000);
    date.setTime(after10MinutesTimeInMilllis);
    // あとはサンプルコードに従えば勝手に10分後がETAとなって登録される
```

以下のような感じになる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392942/ae925d84-59d7-4afd-6a50-51317553b99a.png)

ちなみにタスクの登録時点から最大30日先までしか予約できないらしい。

```javascript
const MAX_SCHEDULE_LIMIT = 30 * 60 * 60 * 24; // Represents 30 days in seconds.
```

# 【補足】Cloud FunctionsをコールするTaskの場合

サンプルコードだとくっつけるペイロードが結局どういう名前のパラメータになるのかがよくわからなかった(以下サンプルコードより抜粋)

```javascript
    ...
    payload = 'Hello, World!', // The task HTTP request body
    ...
```

単純に以下のようにすればいいらしい。(オブジェクトとして定義するだけ)

```javascript
    ...
    payload = {test: 'test'},
    ...
```

この`payload`変数はサンプルコードにおいて以下の内容で加工されてTaskとして登録される。

```javascript
    ...
  // Convert message to buffer.
  const convertedPayload = JSON.stringify(payload);
  const body = Buffer.from(convertedPayload).toString('base64');
    ...
```

で、ここで指定されたリクエストパラメータを、Cloud Functions側で `req.body.test`みたいな感じで取り出す。