バックグラウンド関数

Google Cloud Pub/Sub トピックのメッセージ、Google Cloud Storage バケットの変更、Firebase イベントなどのイベントによって Cloud Functions の関数を間接的に呼び出す場合は、バックグラウンド関数を使用します。

バックグラウンド関数を再試行する方法については、バックグラウンド関数の再試行をご覧ください。

使用例

以下の例は、Pub/Sub と Cloud Storage からイベントを処理する方法を示しています。異なるソースからのイベントを処理する方法については、Cloud Functions の呼び出しをご覧ください。

Pub/Sub の例

この例では、Pub/Sub イベントで Cloud ファンクションをトリガーします。Pub/Sub トピックにメッセージが公開されるたびに関数が呼び出され、メッセージから派生したデータを含む挨拶がログに書き込まれます。

Node.js

/**
 * Background Cloud Function to be triggered by Pub/Sub.
 * This function is exported by index.js, and executed when
 * the trigger topic receives a message.
 *
 * @param {object} message The Pub/Sub message.
 * @param {object} context The event metadata.
 */
exports.helloPubSub = (message, context) => {
  const name = message.data
    ? Buffer.from(message.data, 'base64').toString()
    : 'World';

  console.log(`Hello, ${name}!`);
};

Python

def hello_pubsub(event, context):
    """Background Cloud Function to be triggered by Pub/Sub.
    Args:
         event (dict):  The dictionary with data specific to this type of
         event. The `data` field contains the PubsubMessage message. The
         `attributes` field will contain custom attributes if there are any.
         context (google.cloud.functions.Context): The Cloud Functions event
         metadata. The `event_id` field contains the Pub/Sub message ID. The
         `timestamp` field contains the publish time.
    """
    import base64

    print("""This Function was triggered by messageId {} published at {}
    """.format(context.event_id, context.timestamp))

    if 'data' in event:
        name = base64.b64decode(event['data']).decode('utf-8')
    else:
        name = 'World'
    print('Hello {}!'.format(name))

Go


// Package helloworld provides a set of Cloud Functions samples.
package helloworld

import (
	"context"
	"log"
)

// PubSubMessage is the payload of a Pub/Sub event.
type PubSubMessage struct {
	Data []byte `json:"data"`
}

// HelloPubSub consumes a Pub/Sub message.
func HelloPubSub(ctx context.Context, m PubSubMessage) error {
	name := string(m.Data) // Automatically decoded from base64.
	if name == "" {
		name = "World"
	}
	log.Printf("Hello, %s!", name)
	return nil
}

Java


import com.google.cloud.functions.BackgroundFunction;
import com.google.cloud.functions.Context;
import functions.eventpojos.PubSubMessage;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.logging.Level;
import java.util.logging.Logger;

public class HelloPubSub implements BackgroundFunction<PubSubMessage> {
  private static final Logger logger = Logger.getLogger(HelloPubSub.class.getName());

  @Override
  public void accept(PubSubMessage message, Context context) {
    String name = "world";
    if (message != null && message.getData() != null) {
      name = new String(
          Base64.getDecoder().decode(message.getData().getBytes(StandardCharsets.UTF_8)),
          StandardCharsets.UTF_8);
    }
    logger.info(String.format("Hello %s!", name));
    return;
  }
}

C#

using CloudNative.CloudEvents;
using Google.Cloud.Functions.Framework;
using Google.Events.Protobuf.Cloud.PubSub.V1;
using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;

namespace HelloPubSub
{
    public class Function : ICloudEventFunction<MessagePublishedData>
    {
        private readonly ILogger _logger;

        public Function(ILogger<Function> logger) =>
            _logger = logger;

        public Task HandleAsync(CloudEvent cloudEvent, MessagePublishedData data, CancellationToken cancellationToken)
        {
            string nameFromMessage = data.Message?.TextData;
            string name = string.IsNullOrEmpty(nameFromMessage) ? "world" : nameFromMessage;
            _logger.LogInformation("Hello {name}", name);
            return Task.CompletedTask;
        }
    }
}

Pub/Sub イベントでトリガーされる Cloud Functions をデプロイする方法については、Pub/Sub トリガーPub/Sub チュートリアルをご覧ください。

Cloud Storage の例

この例では、Cloud Storage イベントで Cloud ファンクションをトリガーします。 オブジェクトが Cloud Storage バケットに作成されるたびに関数が呼び出され、変更に関するメッセージがログに記録されます。

Node.js

/**
 * Generic background Cloud Function to be triggered by Cloud Storage.
 *
 * @param {object} file The Cloud Storage file metadata.
 * @param {object} context The event metadata.
 */
exports.helloGCS = (file, context) => {
  console.log(`  Event: ${context.eventId}`);
  console.log(`  Event Type: ${context.eventType}`);
  console.log(`  Bucket: ${file.bucket}`);
  console.log(`  File: ${file.name}`);
  console.log(`  Metageneration: ${file.metageneration}`);
  console.log(`  Created: ${file.timeCreated}`);
  console.log(`  Updated: ${file.updated}`);
};

Python

def hello_gcs(event, context):
    """Background Cloud Function to be triggered by Cloud Storage.
       This generic function logs relevant data when a file is changed.

    Args:
        event (dict):  The dictionary with data specific to this type of event.
                       The `data` field contains a description of the event in
                       the Cloud Storage `object` format described here:
                       https://cloud.google.com/storage/docs/json_api/v1/objects#resource
        context (google.cloud.functions.Context): Metadata of triggering event.
    Returns:
        None; the output is written to Stackdriver Logging
    """

    print('Event ID: {}'.format(context.event_id))
    print('Event type: {}'.format(context.event_type))
    print('Bucket: {}'.format(event['bucket']))
    print('File: {}'.format(event['name']))
    print('Metageneration: {}'.format(event['metageneration']))
    print('Created: {}'.format(event['timeCreated']))
    print('Updated: {}'.format(event['updated']))

Go


// Package helloworld provides a set of Cloud Functions samples.
package helloworld

import (
	"context"
	"fmt"
	"log"
	"time"

	"cloud.google.com/go/functions/metadata"
)

// GCSEvent is the payload of a GCS event.
type GCSEvent struct {
	Kind                    string                 `json:"kind"`
	ID                      string                 `json:"id"`
	SelfLink                string                 `json:"selfLink"`
	Name                    string                 `json:"name"`
	Bucket                  string                 `json:"bucket"`
	Generation              string                 `json:"generation"`
	Metageneration          string                 `json:"metageneration"`
	ContentType             string                 `json:"contentType"`
	TimeCreated             time.Time              `json:"timeCreated"`
	Updated                 time.Time              `json:"updated"`
	TemporaryHold           bool                   `json:"temporaryHold"`
	EventBasedHold          bool                   `json:"eventBasedHold"`
	RetentionExpirationTime time.Time              `json:"retentionExpirationTime"`
	StorageClass            string                 `json:"storageClass"`
	TimeStorageClassUpdated time.Time              `json:"timeStorageClassUpdated"`
	Size                    string                 `json:"size"`
	MD5Hash                 string                 `json:"md5Hash"`
	MediaLink               string                 `json:"mediaLink"`
	ContentEncoding         string                 `json:"contentEncoding"`
	ContentDisposition      string                 `json:"contentDisposition"`
	CacheControl            string                 `json:"cacheControl"`
	Metadata                map[string]interface{} `json:"metadata"`
	CRC32C                  string                 `json:"crc32c"`
	ComponentCount          int                    `json:"componentCount"`
	Etag                    string                 `json:"etag"`
	CustomerEncryption      struct {
		EncryptionAlgorithm string `json:"encryptionAlgorithm"`
		KeySha256           string `json:"keySha256"`
	}
	KMSKeyName    string `json:"kmsKeyName"`
	ResourceState string `json:"resourceState"`
}

// HelloGCS consumes a GCS event.
func HelloGCS(ctx context.Context, e GCSEvent) error {
	meta, err := metadata.FromContext(ctx)
	if err != nil {
		return fmt.Errorf("metadata.FromContext: %v", err)
	}
	log.Printf("Event ID: %v\n", meta.EventID)
	log.Printf("Event type: %v\n", meta.EventType)
	log.Printf("Bucket: %v\n", e.Bucket)
	log.Printf("File: %v\n", e.Name)
	log.Printf("Metageneration: %v\n", e.Metageneration)
	log.Printf("Created: %v\n", e.TimeCreated)
	log.Printf("Updated: %v\n", e.Updated)
	return nil
}

Java

import com.google.cloud.functions.BackgroundFunction;
import com.google.cloud.functions.Context;
import functions.eventpojos.GcsEvent;
import java.util.logging.Logger;

public class HelloGcs implements BackgroundFunction<GcsEvent> {
  private static final Logger logger = Logger.getLogger(HelloGcs.class.getName());

  @Override
  public void accept(GcsEvent event, Context context) {
    logger.info("Event: " + context.eventId());
    logger.info("Event Type: " + context.eventType());
    logger.info("Bucket: " + event.getBucket());
    logger.info("File: " + event.getName());
    logger.info("Metageneration: " + event.getMetageneration());
    logger.info("Created: " + event.getTimeCreated());
    logger.info("Updated: " + event.getUpdated());
  }
}

C#

using CloudNative.CloudEvents;
using Google.Cloud.Functions.Framework;
using Google.Events.Protobuf.Cloud.Storage.V1;
using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;

namespace HelloGcs
{
    public class Function : ICloudEventFunction<StorageObjectData>
    {
        private readonly ILogger _logger;

        public Function(ILogger<Function> logger) =>
            _logger = logger;

        public Task HandleAsync(CloudEvent cloudEvent, StorageObjectData data, CancellationToken cancellationToken)
        {
            _logger.LogInformation("Event: {event}", cloudEvent.Id);
            _logger.LogInformation("Event Type: {type}", cloudEvent.Type);
            _logger.LogInformation("Bucket: {bucket}", data.Bucket);
            _logger.LogInformation("File: {file}", data.Name);
            _logger.LogInformation("Metageneration: {metageneration}", data.Metageneration);
            _logger.LogInformation("Created: {created:s}", data.TimeCreated?.ToDateTimeOffset());
            _logger.LogInformation("Updated: {updated:s}", data.Updated?.ToDateTimeOffset());
            return Task.CompletedTask;
        }
    }
}

Cloud Storage イベントでトリガーされる Cloud Functions をデプロイする方法については、Cloud Storage トリガーCloud Storage チュートリアルをご覧ください。

関数のパラメータ

バックグラウンド関数には、関数の実行をトリガーしたイベントの関連データを含む引数が渡されます。バックグラウンド関数のパラメータは次のとおりです。

Node.js

Node.js ランタイムでは、関数に引数 (data, context, callback) が渡されます。

プロパティ 説明
data イベントのデータ オブジェクト。タイプはイベントによって異なります。 オブジェクト
context イベントのコンテキスト オブジェクト。 オブジェクト
context.eventId イベントの一意の ID。例: "70172329041928" 文字列
context.timestamp このイベントが作成された日時。例: "2018-04-09T07:56:12.975Z" 文字列(ISO 8601)
context.eventType イベントのタイプ。例: "google.pubsub.topic.publish" 文字列
context.resource イベントを発行したリソース。 オブジェクト
callback

関数の実行完了を通知するコールバック。errback 規則に従います。最初の引数がエラーとして解釈されます。


callback();                    // Success
callback(null, 'Success!');    // Success
callback(1);                   // Error
callback(new Error('Failed')); // Error
関数

Python

Python ランタイムでは、関数に引数 (data, context) が渡されます。

プロパティ 説明
data イベントのデータを含む辞書。形式はイベントによって異なります。 Cloud Storage オブジェクトまたは PubsubMessage
context イベントのコンテキスト オブジェクト。 コンテキスト
context.event_id イベントの一意の ID。例: "70172329041928" 文字列
context.timestamp このイベントが作成された日時。例: "2018-04-09T07:56:12.975Z" 文字列(ISO 8601)
context.event_type イベントのタイプ。例: "google.pubsub.topic.publish" 文字列
context.resource イベントを発行したリソース。 文字列

Go

Go ランタイムでは、関数に引数 (ctx, Event) が渡されます。

プロパティ 説明
ctx イベントに関するメタデータを保持する context.Context 値。メタデータは、cloud.google.com/go/functions/metadata パッケージで取得できます。 context.Context
Event

定義する型の struct。イベントのペイロードが json.Unmarshal() でマーシャリング解除されます。イベントのペイロードは、関数が登録されたトリガーによって異なります。

コードに指定する struct 定義は、イベントタイプの構造に対応している必要があります。各イベントの構造は、対応するイベントのトリガーページに記載されています。

struct では、ペイロードに含まれるすべてのフィールドを定義する必要はないことに注意してください。関数で特定のフィールドしか使用しない場合には、そのフィールドだけを struct で定義します。また、JSON タグを使用してフィールドの名前を変更することもできます(JSON フィールド名にアンダースコアが含まれている場合など)。

ユーザー定義の struct

Java

Java ランタイムでは、関数にパラメータ (event, context) が渡されます。バックグラウンド関数には、BackgroundFunction<T>RawBackgroundFunction の 2 種類があります。

プロパティ 説明
event イベントのペイロード。ペイロードの内容は、関数が登録されたトリガーによって異なります。

BackgroundFunction<T> の場合、このパラメータの型は T(ユーザー定義クラス)です。イベントの JSON ペイロードは、Gson.fromJson を使用してシリアル化解除され、このクラスのインスタンスになります。

RawBackgroundFunction の場合、このパラメータの型は String であり、イベントの JSON ペイロードです。
ユーザー定義または String
context イベントに関するメタデータを保持する読み取り専用の Context オブジェクト。 Context

C#

.NET Core 3.1 ランタイムには、2 種類の CloudEvent 関数があります。1 つは ICloudEvent<T>、もう 1 つは ICloudEvent(型なしの CloudEvent 関数)です。

ICloudEvent<T> を実装すると、関数にパラメータ (cloudEvent, data, cancellationToken) が渡されます。ICloudEvent を実装すると、関数にパラメータ (cloudEvent, cancellationToken) が渡されます。

プロパティ 説明
cloudEvent 関数をトリガーした CloudEvent。イベントに関するメタデータと元データのメタデータが格納されます。
data イベントから抽出された T 型のデータ。T は関数のタイプ引数です。このパラメータは、型なしの CloudEvent 関数で使用されません。
cancellationToken 中止されたリクエストを監視するキャンセル トークン。

イベントデータは、関数が登録されたトリガーによって異なります(たとえば Pub/Sub または Cloud Storage など)。直接トリガーされる関数の場合(gcloud functions call コマンドでトリガーする場合など)、直接送信されたメッセージがイベントデータに含まれます。

バックグラウンド関数の終了

関数がバックグラウンド タスク(スレッド、Future、Promise、コールバック、システム プロセスなど)を作成する場合、関数から制御が戻る前に、これらのタスクを終了するか、他の方法で解決する必要があります。特定の実行から制御が戻る前に終了しなかったタスクは、正常に完了しない場合があります。また、予測できない動作を引き起こす場合もあります。

Node.js ランタイムを使用すると、関数に進行中のタスクへの参照を提供させ、Cloud Functions 自体にタスクを待機させることができます。これは、次のいずれかの方法で行うことができます。

  • 関数が完了すると解決される Promise を返す。
  • 完了時にコールバック関数で callback 引数を呼び出す。

次のステップ