Déclencheurs Firebase Realtime Database

Avec Cloud Functions, vous pouvez gérer les événements dans Firebase Realtime Database dans le même projet Cloud que la fonction. Cloud Functions vous permet d'exécuter des opérations de base de données avec des droits d'administrateur complets et garantit que chaque modification de la base de données est traitée individuellement. Vous pouvez apporter des modifications à Firebase Realtime Database via le SDK Admin Firebase.

Dans un cycle de vie typique, une fonction Firebase Realtime Database effectue les opérations suivantes :

  1. Attend les modifications apportées à un emplacement de base de données particulier.

  2. Se déclenche lorsqu'un événement se produit et exécute ses tâches.

  3. Reçoit un objet de données qui contient un instantané des données stockées dans le document spécifié.

Types d'événement

Cloud Functions vous permet de gérer les événements de base de données à deux niveaux de spécificité. Vous pouvez écouter uniquement les événements de création, de mise à jour ou de suppression ou bien écouter toute modification apportée à un chemin d'accès. Cloud Functions prend en charge les types d'événements suivants pour Realtime Database :

Type d'événement Déclencheur
providers/google.firebase.database/eventTypes/ref.write Déclenché lors de tout événement de mutation : à la création, la mise à jour ou la suppression de données dans Realtime Database.
providers/google.firebase.database/eventTypes/ref.create (par défaut) Déclenché lors de la création de données dans Realtime Database.
providers/google.firebase.database/eventTypes/ref.update Déclenché lors de la mise à jour de données dans Realtime Database.
providers/google.firebase.database/eventTypes/ref.delete Déclenché lors de la suppression de données dans Realtime Database.

Spécifier le chemin d'accès et l'instance de la base de données

Pour contrôler le moment et le lieu du déclenchement de votre fonction, vous devez spécifier un chemin d'accès et éventuellement une instance de base de données.

Chemin

Les spécifications de chemin d'accès correspondent à toutes les écritures qui touchent un chemin d'accès, y compris les écritures se trouvant en dessous. Si le chemin d'accès de votre fonction est défini sur /foo/bar, il correspond aux événements de ces deux emplacements :

 /foo/bar
 /foo/bar/baz/really/deep/path

Dans les deux cas, Firebase interprète que l'événement se produit à /foo/bar, et les données d'événement incluent les anciennes et les nouvelles données se trouvant à /foo/bar. Si les données d'événement risquent d'être volumineuses, envisagez d'utiliser plusieurs fonctions sur des chemins d'accès plus profonds au lieu d'utiliser une seule fonction près de la racine de votre base de données. Pour des performances optimales, demandez uniquement des données au niveau le plus profond possible.

Vous pouvez spécifier un composant de chemin d'accès en tant que caractère générique en l'entourant d'accolades. foo/{bar} correspond à n'importe quel enfant de /foo. Les valeurs de ces composants à caractère génériques sont disponibles dans l'objet event.params de votre fonction. Dans cet exemple, la valeur est disponible sous le nom event.params.bar.

Les chemins d'accès contenant des caractères génériques peuvent correspondre à plusieurs événements d'une seule écriture. Une insertion de :

{
  "foo": {
    "hello": "world",
    "firebase": "functions"
  }
}

correspond au chemin d'accès /foo/{bar} deux fois : une fois avec "hello": "world" et une autre fois avec "firebase": "functions".

Instance

Si vous ne spécifiez pas d'instance dans Cloud Console, la fonction est déployée sur l'instance de base de données par défaut de votre projet.

Avec l'outil de ligne de commande gcloud, l'instance doit être spécifiée dans le cadre de la chaîne --trigger-resource. Généralement, le nom de l'instance par défaut est le même que votre ID de projet.

Par exemple, si vous déployez une fonction dans un projet ayant l'ID my-project-id, vous utiliserez ce qui suit dans votre chaîne --trigger-resource :

--trigger-resource projects/_/instances/my-project-id/refs/PATH

Structure de l'événement

Lors de la gestion d'un événement Realtime Database, l'objet data contient deux propriétés qui sont fournies au format JSON :

  • data est un instantané des données pris avant l'événement ayant déclenché la fonction.

  • delta est un instantané des données pris après l'événement ayant déclenché la fonction.

Exemple de code

Node.js

/**
 * Triggered by a change to a Firebase RTDB reference.
 *
 * @param {!Object} event The Cloud Functions event.
 * @param {!Object} context The Cloud Functions event context.
                            (Required to access RTDB path parameters.)
 */
exports.helloRTDB = (event, context) => {
  const triggerResource = event.resource;

  const pathParams = context.params;
  if (pathParams) {
    console.log('Path parameters:');
    Object.keys(pathParams).forEach(key => {
      console.log(`  ${key}: ${pathParams[key]}`);
    });
  }

  console.log(`Function triggered by change to: ${triggerResource}`);
  console.log(`Admin?: ${!!event.auth.admin}`);
  console.log('Delta:');
  console.log(JSON.stringify(event.delta, null, 2));
};

Python

import json
def hello_rtdb(data, context):
    """ Triggered by a change to a Firebase RTDB reference.
    Args:
        data (dict): The event payload.
        context (google.cloud.functions.Context): Metadata for the event.
    """
    trigger_resource = context.resource

    if 'params' in data:
        print('Path parameters:')
        for param, value in data['params'].items():
            print(f'  {param}: {value}')

    print('Function triggered by change to: %s' % trigger_resource)
    print('Admin?: %s' % data.get("admin", False))
    print('Delta:')
    print(json.dumps(data["delta"]))

Go


// Package p contains a Cloud Function triggered by a Firebase Realtime Database
// event.
package p

import (
	"context"
	"fmt"
	"log"

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

// RTDBEvent is the payload of a RTDB event.
type RTDBEvent struct {
	Data  interface{} `json:"data"`
	Delta interface{} `json:"delta"`
}

// HelloRTDB handles changes to a Firebase RTDB.
func HelloRTDB(ctx context.Context, e RTDBEvent) error {
	meta, err := metadata.FromContext(ctx)
	if err != nil {
		return fmt.Errorf("metadata.FromContext: %v", err)
	}
	log.Printf("Function triggered by change to: %v", meta.Resource)
	log.Printf("%+v", e)
	return nil
}

Java

import com.google.cloud.functions.Context;
import com.google.cloud.functions.RawBackgroundFunction;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import java.util.logging.Logger;

public class FirebaseRtdb implements RawBackgroundFunction {
  private static final Logger logger = Logger.getLogger(FirebaseRtdb.class.getName());

  // Use GSON (https://github.com/google/gson) to parse JSON content.
  private static final Gson gson = new Gson();

  @Override
  public void accept(String json, Context context) {
    logger.info("Function triggered by change to: " + context.resource());

    JsonObject body = gson.fromJson(json, JsonObject.class);

    boolean isAdmin = false;
    if (body != null && body.has("auth")) {
      JsonObject authObj = body.getAsJsonObject("auth");
      isAdmin = authObj.has("admin") && authObj.get("admin").getAsBoolean();
    }

    logger.info("Admin?: " + isAdmin);

    if (body != null && body.has("delta")) {
      logger.info("Delta:");
      logger.info(body.get("delta").toString());
    }
  }
}

C#

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

namespace FirebaseRtdb
{
    public class Function : ICloudEventFunction<ReferenceEventData>
    {
        private readonly ILogger _logger;

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

        public Task HandleAsync(CloudEvent cloudEvent, ReferenceEventData data, CancellationToken cancellationToken)
        {
            _logger.LogInformation("Function triggered by change to {subject}", cloudEvent.Subject);
            _logger.LogInformation("Delta: {delta}", data.Delta);

            // In this example, we don't need to perform any asynchronous operations, so the
            // method doesn't need to be declared async.
            return Task.CompletedTask;
        }
    }
}

Ruby

require "functions_framework"

# Triggered by a change to a Firebase RTDB document.
FunctionsFramework.cloud_event "hello_rtdb" do |event|
  # Event-triggered Ruby functions receive a CloudEvents::Event::V1 object.
  # See https://cloudevents.github.io/sdk-ruby/latest/CloudEvents/Event/V1.html
  # The Firebase event payload can be obtained from the `data` field.
  payload = event.data

  if payload.key? "params"
    logger.info "Path parameters:"
    payload["params"].each do |param, value|
      logger.info "  #{param}: #{value}"
    end
  end

  logger.info "Function triggered by change to: #{event.source}"
  logger.info "Admin?: #{payload.fetch 'admin', false}"
  logger.info "Delta: #{payload['delta']}"
end

Déployer votre fonction

La commande gcloud suivante déploie une fonction qui est déclenchée par les événements create sur le chemin d'accès /messages/{pushId}/original :

gcloud functions deploy YOUR_FUNCTION_NAME \
  --trigger-event providers/google.firebase.database/eventTypes/ref.create \
  --trigger-resource projects/_/instances/DATABASE_INSTANCE/refs/messages/{pushId}/original \
  --runtime RUNTIME
Argument Description
--trigger-event NAME Nom du type d'événement que la fonction souhaite recevoir. Dans ce cas, il s'agit de l'un des éléments suivants : écrire, créer, mettre à jour ou supprimer.
--trigger-resource NAME Chemin d'accès complet de la base de données sur lequel la fonction écoutera. Il doit respecter le format suivant : projects/_/instances/DATABASE_INSTANCE/refs/PATH.
--runtime RUNTIME Nom de l'environnement d'exécution que vous utilisez. Pour obtenir une liste complète, consultez la documentation de référence sur gcloud.