Firebase Extensions für die Migration zu Cloud Functions vorbereiten

In dieser Anleitung erfahren Sie, wie Sie Ihre Erweiterungen von der eingestellten Umgebung Firebase Extensions zu einer Funktion migrieren, die Ihre Nutzer in ihrem eigenen Cloud Functions für die Firebase-Codebasis (2. Generation) installieren und bereitstellen.

Dies ist der empfohlene Migrationspfad. Firebase führt eine Liste von Erweiterungen mit offiziellen npm-Entsprechungen. In diesem Leitfaden erfahren Sie, wie Sie Ihre eigene erstellen.

In dieser Anleitung wird die Erweiterung Firestore in BigQuery streamen (firestore-bigquery-export) als Beispiel verwendet. Jeder Abschnitt endet mit einem Beispiel, das zeigt, wie die Erweiterung vor der Migration aussah und wie sie nach der Migration als @firebase/firestore-bigquery-export-Paket aussieht.

Registrieren, um weitere Informationen und Hilfe bei der Migration von Erweiterungen zu erhalten

Wenn Sie Fragen zur Migration von Firebase Extensions haben, können Sie uns unter firebase-extensions-migrator-support-external@google.com erreichen. Wir senden dieser Gruppe auch eine E-Mail, wenn wir die Anleitung mit weiteren Informationen zum Verpacken, Testen und Verteilen Ihrer Funktionen der 2. Generation aktualisieren.

Wenn Sie dieser Gruppe beitreten möchten, senden Sie eine Nachricht an firebase-extensions-migrator-support-external+subscribe@google.com. Sie erhalten dann eine E-Mail mit einer Beitrittsanfrage. Sie müssen auf diese E‑Mail antworten und dürfen nicht auf die Schaltfläche „Dieser Gruppe beitreten“ klicken.

Hinweis

Für diese Migration verwenden Sie die folgenden Funktionen von Cloud Functions:

  • Parametrisierte Konfiguration: Jeder Parameter, den Sie in extension.yaml deklarieren, wird zu einem definierten Parameter in Ihrem Paketcode.

  • Deklarative IAM-Rollen und erforderliche APIs Jede Rolle, die Sie in extension.yaml deklarieren, wird zu einem requiresRole(...)-Aufruf und jede API zu einem requiresAPI(...)-Aufruf in Ihrem Funktionscode. Bei der Bereitstellung weist die Firebase-Befehlszeile dem Dienstkonto einer verwalteten Laufzeitumgebung die deklarierten Rollen zu und aktiviert die deklarierten APIs in Ihrem Namen.

  • Lebenszyklusereignisse für Cloud Functions-Codebases: Cloud Functions Codebases unterstützen jetzt Lebenszyklusereignisse analog zu Firebase Extensions. Deklarieren Sie die Einrichtung bei der Installation und beim Update mit den Lebenszyklus-Hooks afterFirstDeploy(...) und afterRedeploy(...). Diese ersetzen die lifecycleEvents, die Sie in extension.yaml deklarieren.

Erweiterung inventarisieren

Erstellen Sie zuerst ein Inventar Ihrer Erweiterung. Das ist eine vollständige Liste aller Elemente, die in der Erweiterung deklariert, ausgeliefert und dokumentiert werden. So hat jedes Verhalten ein definiertes Ziel in der Funktion der 2. Generation und nichts geht bei der Migration verloren.

Prüfen Sie die folgenden Punkte und notieren Sie sich, was Sie finden:

  • extension.yaml, in der Sie Ihre Parameter, Funktionen, Ereignisse, IAM-Rollen, erforderlichen APIs, Secrets und Lebenszyklus-Hooks deklarieren.

  • functions/, die Ihren Funktionscode, Ihre Abhängigkeiten, Ihre Build-Konfiguration, Ihre Trigger und Ihre Aufgabenwarteschlangenfunktionen enthält.

  • README.md, PREINSTALL.md und POSTINSTALL.md mit Einrichtungsanleitungen, Warnungen und Abrechnungshinweisen.

  • scripts/, das alle Import-, Backfill-, IAM-, Reparatur- oder Migrationsdienstprogramme sowie alle anderen Tools enthält, die Sie zusammen mit der Erweiterung bereitstellen.

Entscheiden Sie dann für jedes Element in extension.yaml, wo es im npm-Paket platziert werden soll:

  • Nutzerkonfiguration in Cloud Functions-Parameter umwandeln (Abschnitt 5).

  • Secrets in Cloud Functions-Secrets umwandeln (Abschnitt 6).

  • IAM-Rollen in requiresRole(...)-Deklarationen umwandeln (Abschnitt 8).

  • Erforderliche Google-APIs in requiresAPI(...)-Deklarationen konvertieren (Abschnitt 8).

  • Installations- und Update-Hooks in afterFirstDeploy(...)- und afterRedeploy(...)-Deklarationen umwandeln (Abschnitt 8).

Beispiel:Firestore-Daten in BigQuery streamen

Beim Lesen von „firestore-bigquery-export/extension.yaml“ und „functions/“ wird Folgendes ermittelt:

In extension.yaml Anzahl / Wert Wohin gelangen sie?
params 25 (COLLECTION_PATH, DATASET_ID, TABLE_ID, DATASET_LOCATION, VIEW_TYPE, …) Cloud Functions-Parameter (Abschnitt 5)
APIs bigquery.googleapis.com requiresAPI(...) (Abschnitt 7)
Rollen bigquery.dataEditor, datastore.user, bigquery.user requiresRole(...) (Abschnitt 7)
Ressourcen 1 Ereignistrigger (fsexportbigquery) + Aufgabenwarteschlangen-Funktionen (initBigQuerySync, setupBigQuerySync) Exportierte Paketfunktionen (Abschnitt 3)
lifecycleEvents onInstall → initBigQuerySync; onUpdate / onConfigure → setupBigQuerySync afterFirstDeploy / afterRedeploy (Abschnitt 9)
scripts/ import/ (Backfill), gen-schema-view/ Als Skripts beibehalten (nicht relevant für diesen Artikel)

In der Erweiterung wird kein Typ deklariert: secret params. Daher gibt es in Abschnitt 6 dieses Leitfadens nichts zu migrieren. Der Ereignistrigger gehört bereits zur 2. Generation. Nur die Task-Queue-Funktionen gehören noch zur 1. Generation (relevant in Abschnitt 3).

package.json aktualisieren

Aktualisieren Sie die package.json-Datei Ihrer Erweiterung. Wenn Sie eine Erweiterung migrieren, kann dies das Stammverzeichnis package.json sein. Wenn Sie viele Erweiterungen in einem Repository migrieren, geben Sie jeder Erweiterung ein eigenes Paket.

Mindestens erforderliche SDK-Versionen. Deklarieren Sie „firebase-functions“ >= 7.3 und „firebase-admin“ >= 14.2.0 als Abhängigkeiten. Deklarieren Sie Ihre Version von firebase-functions auch als Peer-Abhängigkeit.

{
  "name": "<package-name>",
  "version": "1.0.0",
  "main": "lib/index.js",
  "types": "lib/index.d.ts",
  "exports": {
    ".": {
      "types": "./lib/index.d.ts",
      "default": "./lib/index.js"
    }
  },
  "engines": {
    "node": ">=22"
  },
  "peerDependencies": {
    "firebase-functions": "^7.3.0"
  },
  "dependencies": {
    "firebase-functions": "^7.3.0",
    "firebase-admin": "^14.2.0"
  }
}

Deklarieren Sie „firebase-functions“ zusätzlich zu Ihrer normalen Abhängigkeit als Peer-Abhängigkeit, damit das Cloud Functions-Projekt Ihrer Nutzer dieselbe SDK-Version hat, mit der Ihre Bibliothek geschrieben wurde.

Beispiel:Firestore-Daten in BigQuery streamen

Vorher Die Datei „functions/package.json“ der Erweiterung ist privat, enthält die Erweiterungs-ID und deklariert „firebase-functions“ als direkte Abhängigkeit:

{
  "name": "firestore-bigquery-export",
  "main": "lib/index.js",
  "private": true,
  "dependencies": {
    "@firebaseextensions/firestore-bigquery-change-tracker": "^2.0.4",
    "firebase-admin": "^14.2.0",
    "firebase-functions": "^6.3.2"
  }
}

Nachher Ein veröffentlichbares Paket: Bereichsname, eine Exportzuordnung und firebase-functions wurde nach peerDependencies verschoben:

{
  "name": "@firebase/firestore-bigquery-export",
  "version": "0.1.0",
  "main": "lib/index.js",
  "types": "lib/index.d.ts",
  "exports": {
    ".":     { "types": "./lib/index.d.ts", "default": "./lib/index.js" },  },
  "engines": { "node": ">=22" },
  "peerDependencies": { "firebase-functions": "^7.3.0" },
  "dependencies": {
      "@firebaseextensions/firestore-bigquery-change-tracker": "^2.0.4",
      "firebase-admin": "^14.2.0",
      "firebase-functions": "^7.3.0"
    }
}

Funktionen von der 1. Generation auf die 2. Generation upgraden

Wenn in Ihrer Erweiterung weiterhin Funktionen der 1. Generation exportiert werden, konvertieren Sie jede Funktion in ihr Äquivalent der 2. Generation. Importieren Sie die firebase-functions/...-Module und übergeben Sie Laufzeiteinstellungen in den Funktionsoptionen.

Mit der gepatchten Ereignis-Destrukturierung der 2. Generation können Sie den Aufwand für das Umschreiben minimieren und die Logik Ihrer Funktion beibehalten, da das SDK der 2. Generation die V1-Parameter jetzt als Felder im Ereignisobjekt verfügbar macht. So können Sie destrukturierte/benannte Parameter verwenden und Ihre Geschäftslogik unverändert lassen.

Vorher 1. Generation:

import * as functions from "firebase-functions/v1";

export const sync = functions.firestore
  .document("{collectionId}/{documentId}")
  .onWrite(async (change, context) => {
    await handleWrite(change.before, change.after, context.params);
  });

Nachher 2. Generation:

import { onDocumentWritten } from "firebase-functions/firestore";

export const syncV2 = onDocumentWritten(
  { document: "{collectionId}/{documentId}" },
  async ({change,context}) =>
    await handleWrite(change.before, change.after, context.params);
);

Eine umfassende Liste der Unterschiede zwischen Funktionen der 1. und 2. Generation finden Sie im Cloud Functions-Versionsvergleich.

Erweiterungsparameter und Secrets konvertieren

Parameter konvertieren

Jeder Parameter, den Sie in extension.yaml deklarieren, wird zu einem Cloud Functions-Parameter.

Direkte Umgebungsvariablen lesen:

const collectionPath = process.env.COLLECTION_PATH;

in Cloud Functions-Parameter:

import { defineString } from "firebase-functions/params";
import { onDocumentWritten} from "firebase-functions/firestore";

const collectionPath = defineString("COLLECTION_PATH");

// Pass the param directly when used as a placeholder (e.g. trigger path)
export const sync = onDocumentWritten(
  { document: collectionPath },
  async (event) => {
    // Call .value() to read the string inside a handler
    const path = collectionPath.value();
    await handleWrite(path, event);
  }
);

Verwenden Sie collectionPath.value(), um den String in einem Handler zu lesen. Verwenden Sie collectionPath direkt dort, wo ein Platzhalter erwartet wird, z. B. in einem Funktionsauslöserpfad.

Die Firebase-Befehlszeile erkennt Ihre Parameter und liest ihre Werte aus .env, .env.projectId oder fordert Ihre Nutzer während der Bereitstellung auf, sie einzugeben. Behalten Sie die Parameternamen bei, damit Werte aus einer vorhandenen Installation übernommen werden.

Es ist wichtig, dass Sie die in Ihrem Code deklarierten Parameternamen nicht ändern. Bei der Erweiterungsmigration wird der vorhandene Parameterwert des Endnutzers automatisch beibehalten, aber nur, wenn die Namen unverändert sind.

Beispiel: Firestore-Daten in BigQuery streamen Vorher Ein in extension.yaml deklarierter Parameter, der in config.ts als Umgebungsvariable gelesen wird:

# extension.yaml
-   param: COLLECTION_PATH
  label: Collection path
  type: string
  required: true
// functions/src/config.ts
collectionPath: process.env.COLLECTION_PATH,

Nachher Ein defineString; die CLI erkennt es und liest aus .env:

// src/config.ts
import { defineString } from "firebase-functions/params";

collectionPath: defineString("COLLECTION_PATH", {
  label: "Collection path",
  // We now support "nonEmpty: true" to ensure a value other than the empty string
  // is entered, analagous to "required: true" in extensions.yaml
  input: { text: { nonEmpty: true} }
}),

Der Parametername ist unverändert, sodass eine vorhandene .env-Datei weiterhin funktioniert.

Secrets konvertieren

In extension.yaml deklarieren Sie Secrets mit type: secret. Die Extensions-Laufzeit speichert und bindet sie, sodass Ihr Erweiterungscode process.env.PARAM_NAME direkt lesen kann. In einer typischen Cloud Functions-Codebasis deklarieren und binden Sie jedes Secret explizit:

import { defineSecret } from "firebase-functions/params";
import { onRequest } from "firebase-functions/https";

const apiKey = defineSecret("API_KEY");
export const fn = onRequest({ secrets: [apiKey] }, handler);

Nachdem Ihre Erweiterung zu einem npm-Paket/Kit migriert wurde, werden geheime Verweise in der .env-Datei des Endnutzers verwaltet. Es ist wichtig, dass Sie die in Ihrem Code deklarierten Namen der Secrets nicht ändern. Während der Migration werden die Geheimnisse der Endnutzer entsprechend migriert.

Beispiel:E-Mail über Trigger von Cloud Firestore senden

Vorher MAIL_COLLECTION und SMTP_PASSWORD werden als Rohumgebungsvariablen in config.ts gelesen:

# extension.yaml
-   param: MAIL_COLLECTION
  label: Email documents collection
  type: string
  default: mail
  required: true

-   param: SMTP_PASSWORD
  label: SMTP password
  type: secret
// functions/src/config.ts
mailCollection: process.env.MAIL_COLLECTION,
smtpPassword: process.env.SMTP_PASSWORD,

Nachher Eine defineString- und eine defineSecret-Datei. Die CLI erkennt beide und liest aus .env.

import { defineString, defineSecret } from "firebase-functions/params";
import { onDocumentWritten } from "firebase-functions/firestore";

const mailCollection = defineString("MAIL_COLLECTION",{ label: "Email documents collection",
 default: "mail"
});

const smtpPassword = defineSecret("SMTP_PASSWORD", { label: "SMTP password" });

export const processQueue = onDocumentWritten(
  { document: `${mailCollection}/{documentId}`, secrets: [smtpPassword] },
  async (event) => {
    const collection = mailCollection.value();
    const password = smtpPassword.value();
    // ...
  }
);

Interne Aufgabenwarteschlangenaufrufe migrieren

Einige Erweiterungen stellen Aufgaben in ihren eigenen Aufgabenwarteschlangen in ihrem Funktionscode mithilfe von Firebase Admin SDK in die Warteschlange. Das ist etwas anderes als das Empfangen einer zugewiesenen Aufgabe (siehe die Abschnitte Funktionen aktualisieren und Lifecycle-Hooks konvertieren). Hier ist Ihr Code der Producer, der queue.enqueue(...) aufruft.

In früheren Versionen von Admin SDK mussten Erweiterungen ihre eigene Erweiterungsinstanz-ID als zweiten Parameter übergeben, um eine Task Queue-Funktion in derselben Erweiterung aufzurufen. Ab `firebase-admin` 14.2.0 ist dies weder erforderlich noch empfehlenswert. Die Task Queue API zielt jetzt standardmäßig auf Aufgabenwarteschlangen im selben Kontext (z.B. Erweiterung) ab. Sie können diesen Parameter in Ihrem Code sowohl als Erweiterung als auch als eigenständige Funktion entfernen. Durch das Entfernen dieses Parameters wird die Portabilität und Vorwärtskompatibilität sichergestellt.

Alles andere am Enqueue-Aufruf – der Ressourcenpfad „locations/region/functions/name“, die Aufgaben-Payload und Ihre Wiederholungslogik – bleibt gleich.

Weitere Informationen zum Einreihen von Funktionen mit Cloud Tasks finden Sie unter /docs/functions/task-functions.

Vorher Erweiterung der 1. Generation

import { getFunctions } from "firebase-admin/functions";

const queue = getFunctions().taskQueue(
  `locations/${config.location}/functions/syncBigQuery`,
  process.env.EXT_INSTANCE_ID, // extension instance ID, injected by the runtime
);
await queue.enqueue(taskData);

Nachher Erweiterung der 2. Generation

import { getFunctions } from "firebase-admin/functions";

const queue = getFunctions().taskQueue(
  `locations/${process.env.FUNCTION_REGION}/functions/syncBigQuery`);
await queue.enqueue(taskData);

Wenn Ihr Enqueue-Aufruf auf eine mit einem Präfix versehene Codebasis abzielt, hat der ermittelte Funktionsname ebenfalls ein Präfix (z. B. orders-syncBigQuery).

Erforderliche APIs und IAM-Rollen deklarieren

Verschieben Sie die IAM- und API-Anforderungen Ihrer Erweiterung aus „extension.yaml“ in den Code:

import { requiresAPI, requiresRole } from "firebase-functions"

requiresAPI("bigquery.googleapis.com", "Needed to write changelog rows");
requiresRole("roles/bigquery.dataEditor");
requiresRole("roles/bigquery.user");

Bei der deklarativen Sicherheit wird mit der Firebase-Befehlszeile ein verwaltetes Laufzeit-Dienstkonto für die Codebasis erstellt oder aktualisiert und ihm die Vereinigung aller deklarierten Rollen zugewiesen. Dokumentieren Sie für Ihre Nutzer, dass alle Funktionen im Code mit diesen Rollen ausgeführt werden, sofern die endgültige API kein eingeschränkteres Modell unterstützt.

Beispiel:Firestore-Daten in BigQuery streamen

Vorher In „extension.yaml“ deklariert; die Extensions-Laufzeit hat die API aktiviert und einem verwalteten Konto die Rollen zugewiesen:

apis:
  -   apiName: bigquery.googleapis.com
roles:
  -   role: bigquery.dataEditor
  -   role: datastore.user
  -   role: bigquery.user

Nachher Im Code mit „requiresAPI“ und „requiresRole“ deklariert:

import { requiresAPI, requiresRole } from "firebase-functions/";
requiresAPI("bigquery.googleapis.com",
  "Needed to write changelog rows and views");
requiresRole("roles/biguqery.dataEditor");
requiresRole("roles/datastore.user");
requiresRole("roles/bigquery.user");

Convert-Lebenszyklus-Hooks

Wenn Ihre Erweiterung getExtensions().runtime() aufruft, z. B. setProcessingState oder setFatalError, löschen Sie diese Aufrufe, da sie einen Fehler auslösen, wenn sie von einer normal bereitgestellten Funktion der 2. Generation aufgerufen werden. Der Lebenszyklusstatus wird jetzt von afterFirstDeploy und afterRedeploy bestimmt, wobei die Statusverfolgung nicht verwendet wird.

Firebase Extensions kann die Einrichtung ausführen, wenn ein Nutzer eine Erweiterung installiert, aktualisiert oder neu konfiguriert. Deklarieren Sie im npm-Paket entsprechende Lebenszyklusaktionen im Code.

Einmalige Einrichtung:

import { afterFirstDeploy } from "firebase-functions/lifecycle";
import { onTaskDispatched } from "firebase-functions/tasks";

export const runInitialSetup = onTaskDispatched(async (request) => {
  await initializeResources(request.data);
});

afterFirstDeploy({
  task: {
    function: "runInitialSetup",
    body: {}
  }
});

Für Konfigurations- oder Code-Updates:

import { afterRedeploy } from "firebase-functions/lifecycle";

afterRedeploy({
  task: {
    function: "runInitialSetup",
    body: { reconcile: true }
  }
});

Machen Sie Ihre Lebenszyklusaktionen idempotent. Wenn die Ausführung fehlschlägt, müssen Ihre Nutzer sie möglicherweise manuell noch einmal ausführen:

firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME
firebase functions:lifecycle:run afterRedeploy CODEBASE_NAME

Beispiel:Firestore-Daten in BigQuery streamen

Vorher lifecycleEvents in extension.yaml, aufgrund der Extensions-Laufzeit:

lifecycleEvents:
  onInstall:
    function: initBigQuerySync
    processingMessage: Configuring BigQuery Sync.
  onUpdate:
    function: setupBigQuerySync
    processingMessage: Configuring BigQuery Sync
  onConfigure:
    function: setupBigQuerySync
    processingMessage: Configuring BigQuery Sync

Nachher Im Code deklariert; die Aufgaben stellen bei der ersten Bereitstellung BigQuery bereit:

import { afterFirstDeploy, afterRedeploy } from "firebase-functions/lifecycle";

afterFirstDeploy({ task: { function: "initBigQuerySync" } });
afterRedeploy({ task: { function: "setupBigQuerySync" } });

Die Bereitstellung ist idempotent. Bei einer erneuten Ausführung werden Dataset, Tabelle und Ansichten abgeglichen. Nutzer können den Vorgang mit firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME manuell wiederholen.

Dokumenteinrichtung für Ihre Nutzer

  • Schreiben Sie ein Paket README, in dem mindestens Folgendes erklärt wird:

  • Die .env-Werte, die für das Paket erforderlich sind.

  • Die Secrets, die für das Paket erforderlich sind, und wie vorhandene Secret-Werte migriert werden.

  • Die IAM-Rollen, die das Paket mit requiresRole(...) deklariert.

  • Die Google-APIs, die das Paket aktiviert oder erfordert.

  • Die vom Paket deklarierten Lebenszyklus-Hooks und wie sie manuell noch einmal ausgeführt werden.

  • Abrechnungshinweise.

  • Was hat sich im Vergleich zur ursprünglichen Erweiterung geändert?

Beispiel:Firestore-Daten in BigQuery streamen

Die Paket-README enthält eine konkrete Tabelle mit den Änderungen:

Bedenken Als Erweiterung Als @firebase/firestore-bigquery-export
Konfiguration Erweiterungsparameter Funktionsparameter über .env
IAM Durch Erweiterungen gewährt requiresRole(...), angewendet bei der Bereitstellung
Wird bereitgestellt Lebenszyklusaufgabe nach Erweiterungen afterFirstDeploy-Aufgabe / afterRedeploy-Aufgabe
Funktionsnamen ext-instanceId-fsexportbigquery fsexportbigquery (optional mit Präfix)

Funktion der 2. Generation testen

Sie sollten jetzt eine Funktion der 2. Generation haben, die sich bei der Bereitstellung identisch mit einer Neuinstallation Ihrer Erweiterung verhält. Im letzten Schritt werden alle Probleme behoben, die versehentlich eingeführt wurden.

Achten Sie darauf, dass Sie firebase-tools >= 15.25.1 verwenden, und stellen Sie Ihre konvertierte Funktion der 2. Generation in einem Testprojekt mit den entsprechenden Ressourcen bereit, um ihr Verhalten zu testen. Wenn Sie bereits ein Testprojekt zum Testen Ihrer Erweiterung eingerichtet haben, verwenden Sie den folgenden Befehl:

firebase deploy --only functions

Füllen Sie nach der Eingabe dieses Befehls den resultierenden Assistenten aus, in dem Sie nach Parameterwerten gefragt werden. Gehen Sie dabei genauso vor wie beim Ausfüllen des Installationsformulars für die Erweiterung in der Firebase-Konsole.

Beispiel:Firestore-Daten in BigQuery streamen

Wir prüfen die Synchronisierung von Cloud Firestore zu BigQuery von Anfang bis Ende:

  1. Erstellen Sie in der Cloud Firestore-Konsole die Sammlung, die Sie als COLLECTION_PATH (users) festgelegt haben, falls sie noch nicht vorhanden ist.
  2. Erstellen Sie ein Dokument mit dem Namen „bigquery-mirror-test“, das beliebige Felder mit beliebigen Werten enthält.
  3. Fragen Sie in der BigQuery-Konsole die Rohdaten-Changelog-Tabelle ab. Sie sollte eine einzelne Zeile mit der Protokollierung der Dokumenterstellung enthalten:
SELECT * FROM `PROJECT_ID.analytics.users_raw_changelog`
  1. Fragen Sie die letzte Ansicht ab. Dadurch sollte das letzte Änderungsereignis für das einzige vorhandene Dokument zurückgegeben werden: bigquery-mirror-test
SELECT * FROM `PROJECT_ID.analytics.users_raw_latest`
  1. Löschen Sie das Dokument bigquery-mirror-test in Cloud Firestore. Sie verschwindet aus der neuesten Ansicht und der Rohdaten-Changelog-Tabelle wird ein DELETE-Ereignis angehängt.

Mit dem folgenden Befehl können Sie den vollständigen Verlauf eines einzelnen Dokuments aufrufen:

SELECT *
   FROM `PROJECT_ID.analytics.users_raw_changelog`
   WHERE document_name = "bigquery-mirror-test"
   ORDER BY timestamp ASC

Unterschiede zum Testen der Erweiterung:

  • Der Trigger wird als fsexportbigquery (optional mit dem Präfix des Code-Repositorys) und nicht als ext-&lt;instanceId&gt;-fsexportbigquery bereitgestellt. Suchen Sie im Dashboard Cloud Functions und in den Logs nach diesem Namen.
  • Ihr Code wird jetzt wie gewohnt in den Firebase Local Emulator Suite-Funktionen ausgeführt. Mit .env.local können Sie den Wert von Parametern festlegen, die im Emulator verwendet werden sollen. Sie können Ihren Code auch mit dem firebase-functions-test SDK testen, wie unter Unittests für Cloud Functions beschrieben.
  • Die Bereitstellung wird nicht mehr von der Extensions-Laufzeit gesteuert. Wenn die Changelog-Tabelle nach der Bereitstellung fehlt, führen Sie die Einrichtungsaufgabe manuell noch einmal aus: firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME. Der Task ist idempotent. Wenn Sie ihn also noch einmal ausführen, werden Dataset, Tabelle und Ansichten abgeglichen.
  • Parameterwerte stammen aus .env und nicht aus dem Installationsformular. Daher sind Wiederholungen von firebase deploy nicht interaktiv, sobald .env abgeschlossen ist.