Firebase Extensions für die Migration zu Cloud Functions vorbereiten

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

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

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

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

Wenn Sie Fragen zur Migration von Firebase Extensions haben, erreichen Sie uns unter firebase-extensions-migrator-support-external@google.com. Wir senden auch E-Mails an diese Gruppe, 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 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 CLI die deklarierten Rollen einem verwalteten Laufzeitdienst konto zu und aktiviert die deklarierten APIs in Ihrem Namen.

  • Lebenszyklusereignisse für Cloud Functions Codebasen. Cloud Functions Codebasen unterstützen jetzt Lebenszyklusereignisse, die denen von Firebase Extensions ähneln. Deklarieren Sie die Einrichtung bei der Installation und Aktualisierung mit den Lebenszyklushooks afterFirstDeploy(...) und afterRedeploy(...). Diese ersetzen die lifecycleEvents, die Sie in extension.yaml deklarieren.

Erweiterung inventarisieren

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

Prüfen Sie die folgenden Elemente und notieren Sie Ihre Ergebnisse:

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

  • functions/, das Ihren Funktionscode, Ihre Abhängigkeiten, die Build-Konfiguration, Trigger und Funktionen für Aufgabenwarteschlangen enthält.

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

  • scripts/mit allen Dienstprogrammen für Import, Backfill, IAM, Reparatur oder Migration sowie allen anderen Tools, die Sie zusammen mit der Erweiterung ausliefern.

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

  • Nutzerkonfiguration in Cloud Functions Parameter konvertieren (Abschnitt 5)

  • Secrets in Cloud Functions Secrets konvertieren (Abschnitt 6)

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

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

  • Installations- und Aktualisierungshooks in afterFirstDeploy(...)- und afterRedeploy(...)-Deklarationen konvertieren (Abschnitt 8)

Beispiel: Stream Firestore to BigQuery

Das Lesen von „firestore-bigquery-export/extension.yaml“ und „functions/“ ergibt dieses Inventar:

In extension.yaml Anzahl / Wert Ziel
Parameter 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) + Funktionen für Aufgabenwarteschlangen (initBigQuerySync, setupBigQuerySync) Exportierte Paketfunktionen (Abschnitt 3)
lifecycleEvents onInstall → initBigQuerySync; onUpdate / onConfigure → setupBigQuerySync afterFirstDeploy / afterRedeploy (Abschnitt 9)
Skripts/ import/ (backfill), gen-schema-view/ Als Skripts beibehalten (hier nicht relevant)

Die Erweiterung deklariert keinen Typ: Secret-Parameter. Daher gibt es in Abschnitt 6 dieser Anleitung nichts zu migrieren. Der Ereignistrigger ist bereits 2. Generation. Nur die Funktionen für Aufgabenwarteschlangen sind noch 1. Generation (relevant in Abschnitt 3).

package.json aktualisieren

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

Mindestversionen des SDK. Deklarieren Sie „firebase-functions >= 7.3“ und „firebase-admin >= 14.2.0“ als Abhängigkeiten. Deklarieren Sie auch Ihre Version von „firebase-functions“ 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 Version des SDK verwendet, mit der Ihre Bibliothek geschrieben wurde.

Beispiel: Stream Firestore to BigQuery

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: Name mit Bereich, eine Exportzuordnung und firebase-functions wurde zu 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 zur 2. Generation aktualisieren

Wenn Ihre Erweiterung noch Funktionen der 1. Generation exportiert, konvertieren Sie jede Funktion in die entsprechende Funktion der 2. Generation. Importieren Sie aus den Modulen firebase-functions/... und übergeben Sie Laufzeiteinstellungen in den Funktionsoptionen.

Sie können den Aufwand für das Umschreiben mit der gepatchten Ereignisdestrukturierung der 2. Generation minimieren und müssen Ihre Funktionslogik nicht umschreiben, da das SDK der 2. Generation die Parameter der 1. Generation jetzt als Felder im Ereignisobjekt verfügbar macht. So können Sie destrukturierte/benannte Parameter verwenden und Ihre Geschäftslogik unverändert beibehalten.

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);
);

Im Cloud Functions Versions vergleich finden Sie eine umfassende Liste der Unterschiede zwischen Funktionen der 1. und 2. Generation.

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 konvertieren:

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, wenn ein Platzhalter erwartet wird, z. B. ein Funktions Triggerpfad.

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

Es ist wichtig, dass Sie die in Ihrem Code deklarierten Parameternamen nicht ändern überhaupt nicht. Bei der Migration von Erweiterungen wird der vorhandene Parameterwert des Endnutzers automatisch beibehalten, aber nur, wenn die Namen unverändert bleiben.

Beispiel:Stream Firestore to BigQuery 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 ihn und liest ihn 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 Erweiterungslaufzeit 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);

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

Beispiel: E-Mail aus Cloud Firestore auslösen

Vorher MAIL_COLLECTION und SMTP_PASSWORD werden in „config.ts“ als Umgebungsvariablen 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 Ein defineString und ein defineSecret; die CLI erkennt beide und liest sie 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 Aufrufe von Aufgabenwarteschlangen migrieren

Einige Erweiterungen stellen Aufgaben in die eigenen Aufgabenwarteschlangen ein, indem sie den Firebase Admin SDK in ihrem Funktionscode verwenden. Dies unterscheidet sich vom Empfangen einer gesendeten Aufgabe (behandelt in den Abschnitten Funktionen aktualisieren und Lebenszyklushooks konvertieren). Hier ist Ihr Code der Producer , der „queue.enqueue(...)“ aufruft.

In früheren Versionen des Admin SDK mussten Erweiterungen ihre eigene Erweiterungsinstanz-ID als zweiten Parameter übergeben, um eine Funktion für Aufgabenwarteschlangen in derselben Erweiterung anzusprechen. 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 sowohl in Erweiterungen als auch in eigenständigen Funktionen gefahrlos entfernen. Das Entfernen dieses Parameters sorgt für Portabilität und Vorwärtskompatibilität.

Alles andere am Aufruf zum Einreihen in die Warteschlange – der Ressourcenpfad für Standorte/region/Funktionen/name, die Aufgaben- Payload und Ihre Logik für Wiederholungsversuche – bleibt gleich.

Weitere Informationen zum Einreihen von Funktionen in die Warteschlange 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";
import { region } from "firebase-functions/params";

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

Wenn Ihr Aufruf zum Einreihen in die Warteschlange auf eine Codebasis mit Präfix abzielt, wird auch dem erkannten Funktionsnamen ein Präfix vorangestellt (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");

Mit der deklarativen Sicherheit erstellt oder aktualisiert die Firebase CLI ein verwaltetes Laufzeit-Dienstkonto für die Codebasis und weist ihm die Kombination aller deklarierten Rollen zu. Dokumentieren Sie für Ihre Nutzer, dass alle Funktionen in der Codebasis mit diesen Rollen ausgeführt werden, es sei denn, die endgültige API unterstützt ein engeres Modell.

Beispiel: Stream Firestore to BigQuery

Vorher In „extension.yaml“ deklariert; die Erweiterungslaufzeit hat die API aktiviert und die Rollen einem verwalteten Konto 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");

Lebenszyklushooks konvertieren

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 gesteuert, wenn diese Statusverfolgung nicht verwendet wird.

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

Für die 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 Codeaktualisierungen :

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

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

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

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

Beispiel: Stream Firestore to BigQuery

Vorher lifecycleEvents in extension.yaml, gesteuert von der Erweiterungslaufzeit:

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 Aufgabe stellt BigQuery bei der ersten Bereitstellung bereit:

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

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

Die Bereitstellung ist idempotent, sodass bei einer erneuten Ausführung Dataset, Tabelle und Ansichten abgeglichen werden. Nutzer können die Aufgabe mit „firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME“ manuell noch einmal ausführen.

Einrichtung für Ihre Nutzer dokumentieren

  • Erstellen Sie eine README-Datei für das Paket, in der 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 Lebenszyklushooks, die das Paket deklariert, und wie sie manuell noch einmal ausgeführt werden.

  • Abrechnungshinweise.

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

Beispiel: Stream Firestore to BigQuery

Die README-Datei des Pakets enthält eine konkrete Tabelle mit den Änderungen:

Bedenken Als Erweiterung Als @firebase/firestore-bigquery-export
Konfiguration Erweiterungsparameter Funktionsparameter über „.env“
IAM Von Erweiterungen gewährt requiresRole(...), bei der Bereitstellung angewendet
Bereitstellung Lebenszyklusaufgabe durch Erweiterungen Aufgabe „afterFirstDeploy“ / „afterRedeploy“
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 nach der Bereitstellung genauso verhält wie eine neue Installation Ihrer Erweiterung. Im letzten Schritt müssen Sie alle Probleme überprüfen und beheben, die versehentlich aufgetreten sind.

Achten Sie darauf, dass Sie firebase-tools >= 15.24.0 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 für das Testen Ihrer Erweiterung eingerichtet haben, verwenden Sie den folgenden Befehl:

firebase deploy --only functions

Nachdem Sie diesen Befehl eingegeben haben, füllen Sie den resultierenden Assistenten aus, in dem Sie nach Parameterwerten gefragt werden. Gehen Sie dabei genauso vor, wie Sie das Installationsformular in der Firebase Console für die Erweiterung ausgefüllt hätten.

Beispiel: Stream Firestore to BigQuery

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

  1. Erstellen Sie in der Cloud Firestore Console die Sammlung, die Sie als COLLECTION_PATH (Nutzer) 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 Console die Tabelle mit dem Roh-Änderungsprotokoll ab. Sie sollte eine einzelne Zeile enthalten, in der die Dokumenterstellung protokolliert wird:
SELECT * FROM `PROJECT_ID.analytics.users_raw_changelog`
  1. Fragen Sie die neueste Ansicht ab. Sie sollte das letzte Änderungsereignis für das einzige vorhandene Dokument zurückgeben: bigquery-mirror-test
SELECT * FROM `PROJECT_ID.analytics.users_raw_latest`
  1. Löschen Sie das bigquery-mirror-test Dokument in Cloud Firestore. Es wird aus der neuesten Ansicht entfernt und der Tabelle mit dem Roh-Änderungsprotokoll wird ein DELETE-Ereignis angehängt.

Sie können den vollständigen Verlauf eines einzelnen Dokuments mit folgendem Befehl prüfen:

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

Unterschiede beim Testen der Erweiterung :

  • Der Trigger wird als fsexportbigquery (optional mit Präfix für die Codebasis) bereitgestellt, nicht als ext-&lt;instanceId&gt;-fsexportbigquery. Suchen Sie in der Cloud Functions Console und in den Logs nach diesem Namen.
  • Ihr Code wird jetzt in der Firebase Local Emulator Suite als normale Funktionen ausgeführt. Sie können den Wert von Parametern, die im Emulator verwendet werden sollen, mit .env.local festlegen. Sie können Ihren Code auch mit dem firebase-functions-test SDK testen, wie unter Unit-Tests für Cloud Functions beschrieben.
  • Die Bereitstellung wird nicht mehr von der Erweiterungslaufzeit gesteuert. Wenn die Tabelle mit dem Änderungsprotokoll nach der Bereitstellung fehlt, führen Sie die Einrichtung manuell noch einmal aus: firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME. Die Aufgabe ist idempotent, sodass bei einer erneuten Ausführung Dataset, Tabelle und Ansichten abgeglichen werden.
  • Parameterwerte stammen aus .env und nicht aus dem Installationsformular. Daher sind erneute Ausführungen von firebase deploy nicht interaktiv, sobald .env vollständig ist.