Cloud Storageのイベントトリガー第2世代Cloud FunctionsをHTTPトリガーに変えてみた

イベントトリガーからHTTPトリガーに変えました。
2023.07.31

(追記:タイトルを変更しました。また、稼働時間に言及している箇所を修正しました。
元タイトル:Cloud Storageのイベントトリガーで9分動く第2世代Cloud FunctionsをHTTPトリガーに変えて60分動かせるようにしてみた
変更理由:HTTPトリガーに変えた後60分動かすには別途Pub/Subの設定やコードの追加項目が必要になるため)

クラスメソッド株式会社データアナリティクス事業本部所属のニューシロです。
Cloud StorageのイベントトリガーCloud Functionsを、HTTPトリガーに変えてみました。以下のブログを参考にさせていただきました。

やりたいことは同じですが、違う点として今回はトリガー元がCloud Storageなので、その辺りの設定を説明していきたいと思います。

きっかけ

第2世代Cloud Functionsは、第1世代に比べてタイムアウトまでの時間が伸びています。
第1世代の9分に対し、第2世代はイベントトリガーは9分、HTTPトリガーは60分まで伸びています。

Cloud Storageにオブジェクトが作成されたことをトリガーにしてCloud Functionsを起動して処理を行う際、処理時間がかかる関数だと9分で足りないこともあるかもしれません。
せっかくHTTPトリガーが60分まで伸びているので、こちらを使って処理時間を伸ばせるようにしてみたいと思い、今回検証しました。

追記:実際に長時間稼働させてみたところ、別途Pub/Subの設定やコードの追加項目が必要になることがわかったため、今回はあくまでHTTPトリガーCloud Functionsを呼び出すところまでの紹介とさせていただきます。

やりたいこと

下記のような流れを実装します。

  • まずCloud Storageにオブジェクトが作成された際、Pub/Subトピックへ通知します。
  • 次にPub/SubサブスクリプションがメッセージをCloud Functionsへ通知します。
  • 最後にCloud Functionsが、バケットの名前、オブジェクトの名前を受け取って起動したら成功です。

(参考)ちなみにイベントトリガーだと

比較対象として、イベントトリガーでの設定を簡単に説明します。
まずはtest-eventtriggerという関数をデプロイします。ADD TRIGGERを押してCloud Storage triggerを選択します。

イベントはgoogle.cloud.storage.object.v1.finalizedを選び、あらかじめ作成しておいたtest-eventtrigger-bucketという名前のバケットにトリガーを設定します。

トリガーを保存し、サービスアカウントはデフォルトのままデプロイします。コードは以下です。

main.py

import functions_framework


@functions_framework.cloud_event
def test_eventtrigger(cloud_event):
    data = cloud_event.data

    bucket = data["bucket"]
    name = data["name"]

    print(f"Bucket: {bucket}")
    print(f"File: {name}")

requirements.txt

functions-framework==3.*

ちなみに、タイムアウトは540秒が最大値です。それ以上を設定しようとするとダメと言われます。

デプロイ後、test-eventtrigger-bucketという名前のバケットにtest.txtというサンプルファイルをアップロードします。

結果 ↓

このように、対象のCloud Storageのバケット名、作成されたオブジェクト名を取得することができます。
実際に業務に用いるコードでは、これらの取得したバケット名、オブジェクト名を利用して対象のオブジェクトを処理していくことになると思います。

本題

Cloud Functionsのデプロイ

では本題です。HTTPトリガーで動くCloud Functionsをデプロイします。 目標は、先ほどと同じように、作成されたオブジェクト名バケット名を取得することです。
先述の通り、この2つさえ受け取れていれば処理対象のオブジェクトが定まり、処理を開始することができるからです。

コンソール画面で作成します。サービスアカウントはデフォルトのものを使用しています。
認証については割愛しますが、誰でも叩けるとまずいので認証ありが良いと思います。

HTTPトリガーですのでタイムアウトは3600秒まで設定可能です。

以下のコードを利用します。

main.py

import functions_framework


@functions_framework.http
def test_httptrigger(request):
    request_json = request.get_json()
    bucket = request_json['message']['attributes']['bucketId']
    name = request_json['message']['attributes']['objectId']

    print(f"Bucket: {bucket}")
    print(f"File: {name}")

    return "OK"

requirements.txt

functions-framework==3.*

強調してある3行で、後に設定するPub/Subサブスクリプションからのメッセージをjson形式で受け取り、その中にあるオブジェクト名、バケット名を受け取ることができます。

Pub/Subトピックを作成する

次にPub/Subトピックを作成します。以下のドキュメントを元に進めます。

あらかじめ作成しておいたtest-httptrigger-bucketに対し、オブジェクトが作成された際の通知を設定します。 これはコンソール画面ではできないので、以下のコマンドをCloud Shellで入力します。

gcloud storage buckets notifications create gs://test-httptrigger-bucket \
--topic=test-httptrigger-topic \
--event-types=OBJECT_FINALIZE

以下のコマンドから通知構成が設定できているか確認します。

gcloud storage buckets notifications list gs://test-httptrigger-bucket

結果 ↓

---
Bucket URL: gs://test-httptrigger-bucket/
Notification Configuration:
  etag: '1'
  event_types:
  - OBJECT_FINALIZE
  id: '1'
  kind: storage#notification
  payload_format: JSON_API_V1
  selfLink: https://www.googleapis.com/storage/v1/b/test-httptrigger-bucket/notificationConfigs/1
  topic: //pubsub.googleapis.com/projects/new-shiro/topics/test-httptrigger-topic

ちゃんと作成できていることがわかります。

Pub/Subサブスクリプションを作成する

作成したPub/Subトピックに対するサブスクリプションを作成し、 push先が今回のCloud Functionsになるよう設定します。
まずPub/Subのコンソール画面で、サブスクリプションを作成をクリックします。
IDをtest-httptrigger-sub、トピックをtest-httptrigger-topicに設定し、pushを選んでエンドポイントを先ほど作成したCloud FunctionsのHTTPSエンドポイントに設定します。サービスアカウントはデフォルトです。

これで準備OKです!!

できてるかテストする

検証します。バケットtest-httptrigger-bucketにオブジェクトtest.txtを作成します。

Cloud Functionstest-httptriggerのログを見てみると、、

オブジェクト名、バケット名を受け取ることができています!
これでイベントトリガーと同様に、このオブジェクトを対象にした処理が実行できます。そして、タイムアウトは60分に設定できています。

最後に

ここまでやったのは良いのですが、実際に運用する場面はまだなさそうなので、いずれ使ってみたいです。  

引用・参照まとめ