Acionadores do Firebase Realtime Database

Com o Cloud Functions, é possível processar eventos no Firebase Realtime Database sem necessidade de atualizar o código do cliente. O Cloud Functions permite executar operações de banco de dados com todos os privilégios administrativos e garante o processamento individual de cada alteração feita no banco de dados. É possível fazer alterações no Firebase Realtime Database por meio do SDK Admin do Firebase.

Em um ciclo de vida comum, uma função do Firebase Realtime Database faz o seguinte:

  1. Aguarda alterações feitas em um local de banco de dados específico.

  2. É acionada quando um evento ocorre e realiza as tarefas dele.

  3. Recebe um objeto de dados que contém um snapshot dos dados armazenados no documento especificado.

Tipos de evento

O Functions permite processar eventos de banco de dados em dois níveis de especificidade. É possível detectar especificamente apenas eventos de criação, atualização ou exclusão ou detectar qualquer alteração de qualquer tipo em um caminho. O Cloud Functions dá suporte aos seguintes tipos de evento para o Realtime Database:

Tipo de evento Acionador
providers/google.firebase.database/eventTypes/ref.write Acionado em qualquer evento de mutação: quando os dados são criados, atualizados ou excluídos no Realtime Database.
providers/google.firebase.database/eventTypes/ref.create Acionado quando novos dados são criados no Realtime Database.
providers/google.firebase.database/eventTypes/ref.update Acionado quando os dados são atualizados no Realtime Database.
providers/google.firebase.database/eventTypes/ref.delete Acionado quando os dados são excluídos do Realtime Database.

Como especificar o caminho e a instância do banco de dados

Para controlar quando e onde a função será acionada, você precisa especificar um caminho e, como opção, uma instância de banco de dados.

Caminho

As especificações de caminho correspondem a todas as gravações realizadas em um caminho, inclusive as que acontecem em qualquer lugar abaixo dele. Se você definir o caminho para sua função como /foo/bar, ele corresponderá aos eventos nestes dois locais:

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

Em ambos os casos, o Firebase interpreta que o evento ocorre em /foo/bar, e os dados do evento incluem os dados antigos e novos em /foo/bar. Se os dados do evento forem grandes, considere usar várias funções em caminhos mais profundos, em vez de uma única função próxima da raiz do banco de dados. Para ter o melhor desempenho, solicite apenas dados no nível mais profundo possível.

Para especificar um componente do caminho como caractere curinga, basta colocá-lo entre chaves. foo/{bar} corresponde a qualquer filho de /foo. Os valores desses componentes de caminho curinga estão disponíveis no objeto event.params da sua função. Neste exemplo, o valor está disponível como event.params.bar.

Os caminhos com caracteres curinga podem corresponder a vários eventos de uma única gravação. Uma inserção de:

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

corresponde ao caminho /foo/{bar} duas vezes: uma vez com "hello": "world" e novamente com "firebase": "functions".

Instância

Ao usar o Console do Cloud, se você não especificar uma instância, a função será implantada na instância de banco de dados padrão de seu projeto.

Ao usar a ferramenta de linha de comando gcloud, a instância deve ser especificada como parte da string --trigger-resource. Normalmente, o nome da instância padrão é o mesmo do código do projeto.

Por exemplo, se você estiver implementando uma função em um projeto com o ID my-project-id, use o seguinte na string --trigger-resource:

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

Estrutura do evento

Ao manipular um evento do Realtime Database, o objeto data contém duas propriedades que são fornecidas no formato de objeto JSON:

  • data: um instantâneo dos dados registrados antes do evento que acionaram a função.

  • delta: um snapshot dos dados obtidos após o evento que acionou a função.

Exemplo de código

Node.js 8+

/**
 * Triggered by a change to a Firebase RTDB reference.
 *
 * @param {object} data The event payload.
 * @param {object} context The event metadata.
 */
exports.helloRTDB = (data, context) => {
  const triggerResource = context.resource;

  const pathParams = data.params;
  if (pathParams) {
    console.log(`Parameters:`);
    Object.entries(pathParams).forEach(([param, value]) => {
      console.log(`  ${param}: ${value}`);
    });
  }

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

Node.js 6 (obsoleto)

/**
 * Triggered by a change to a Firebase RTDB reference.
 *
 * @param {!Object} event The Cloud Functions event.
 */
exports.helloRTDB = event => {
  const triggerResource = event.resource;

  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
}

Como implantar a função

O comando gcloud a seguir implanta uma função que será acionada por eventos create no caminho /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
Argumento Descrição
--trigger-event NAME O nome do tipo de evento que a função quer receber. Neste caso, ele será um dos seguintes: escrever, criar, atualizar ou excluir.
--trigger-resource NAME O caminho completo do banco de dados em que a função vai detectar. Ele precisa estar de acordo com o seguinte formato: projects/_/instances/DATABASE_INSTANCE/refs/PATH
--runtime RUNTIME O nome do ambiente de execução que você está usando. Para uma lista completa, consulte a referência do gcloud.