Fügen Sie Benutzer-Hooks zu einer Erweiterung hinzu

Sie können Benutzern, die Ihre Erweiterung installieren, die Möglichkeit geben, ihre eigene benutzerdefinierte Logik in die Ausführung Ihrer Erweiterung einzufügen. Es gibt zwei Möglichkeiten, dies zu erreichen:

  • Eventarc-Ereignisse : Um Benutzern die Möglichkeit zu geben, asynchron auf Ereignisse zu reagieren, können Sie sie auf Eventarc veröffentlichen. Benutzer können Event-Handler-Funktionen bereitstellen, die beispielsweise Benachrichtigungen senden, nachdem Aufgaben mit langer Laufzeit abgeschlossen sind, oder sie können ihre eigenen Nachbearbeitungsfunktionen definieren.

  • Synchrone Hooks : Um Benutzern die Möglichkeit zu geben, Ihrer Erweiterung Blockierungslogik hinzuzufügen, können Sie an vordefinierten Punkten im Betrieb der Erweiterung synchrone Hooks hinzufügen. An diesen Punkten führen Sie eine Benutzer-Provider-Funktion aus und fahren erst fort, nachdem sie abgeschlossen ist. Vorverarbeitungsaufgaben fallen häufig in diese Kategorie.

Eine Erweiterung kann eine oder beide Methoden verwenden.

Eventarc-Veranstaltungen

So veröffentlichen Sie Ereignisse aus einer Erweiterung:

  1. Deklarieren Sie die Ereignistypen, die Sie in der Datei extension.yaml veröffentlichen möchten:

    events:
      - type: publisher-id.extension-name.version.event-name
        description: event-description
      - type: publisher-id.extension-name.version.another-event-name
        description: another-event-description
    

    Die type besteht aus mehreren durch Punkte getrennten Feldern. Die Felder Herausgeber-ID , Erweiterungsname und Ereignisname sind erforderlich. Das Versionsfeld wird empfohlen. Wählen Sie für jeden von Ihnen veröffentlichten Veranstaltungstyp einen eindeutigen und beschreibenden Veranstaltungsnamen.

    Beispielsweise deklariert die Erweiterung storage-resize-images einen einzelnen Ereignistyp:

    events:
      - type: firebase.extensions.storage-resize-images.v1.complete
        description: |
          Occurs when image resizing completes. The event will contain further
          details about specific formats and sizes.
    

    Benutzer können bei der Installation der Erweiterung auswählen, welche Ereignisse sie abonnieren möchten.

  2. Importieren Sie in Ihren Erweiterungsfunktionen die Eventarc-API aus dem Admin SDK und initialisieren Sie einen Ereigniskanal mithilfe der Installationseinstellungen des Benutzers. Diese Einstellungen werden mithilfe der folgenden Umgebungsvariablen verfügbar gemacht:

    • EVENTARC_CHANNEL : der vollständig qualifizierte Name des Eventarc-Kanals, in dem der Benutzer Ereignisse veröffentlicht hat.
    • EXT_SELECTED_EVENTS : eine durch Kommas getrennte Liste von Ereignistypen, die der Benutzer zur Veröffentlichung ausgewählt hat. Wenn Sie einen Kanal mit diesem Wert initialisieren, filtert das Admin SDK automatisch Ereignisse heraus, die der Benutzer nicht ausgewählt hat.
    • EVENTARC_CLOUD_EVENT_SOURCE : die Cloud-Ereignisquellenkennung. Das Admin SDK übergibt diesen Wert automatisch im source veröffentlichter Ereignisse. Normalerweise müssen Sie diese Variable nicht explizit verwenden.

    Wenn Ereignisse bei der Installation nicht aktiviert wurden, sind diese Variablen undefiniert. Sie können diese Tatsache nur dann nutzen, um einen Ereigniskanal zu initialisieren, wenn Ereignisse aktiviert sind:

    import * as admin from "firebase-admin";
    import {getEventarc} from 'firebase-admin/eventarc';
    
    admin.initializeApp();
    
    // Set eventChannel to a newly-initialized channel, or `undefined` if events
    // aren't enabled.
    const eventChannel =
      process.env.EVENTARC_CHANNEL &&
      getEventarc().channel(process.env.EVENTARC_CHANNEL, {
        allowedEventTypes: process.env.EXT_SELECTED_EVENTS,
      });
    
  3. Veröffentlichen Sie Ereignisse im Kanal an den Stellen in Ihrer Erweiterung, die Sie Benutzern zugänglich machen möchten. Zum Beispiel:

    // If events are enabled, publish a `complete` event to the configured
    // channel.
    eventChannel && eventChannel.publish({
        type: 'firebase.extensions.storage-resize-images.v1.complete',
        subject: filename,  // the name of the original file
        data: {
          // ...
        }
    });
    
  4. Dokumentieren Sie die von Ihnen veröffentlichten Ereignisse entweder in der PREINSTALL- oder POSTINSTALL-Datei.

    Dokumentieren Sie für jedes Ereignis Folgendes:

    • Sein beabsichtigter Zweck
    • Der Punkt in der Logik Ihrer Erweiterung, an dem sie ausgeführt wird
    • Die darin enthaltenen Ausgabedaten
    • Die Bedingungen für seine Ausführung

    Warnen Sie Benutzer außerdem davor, in ihren Ereignishandlern Aktionen auszuführen, die möglicherweise dieselbe Erweiterung auslösen, was zu einer Endlosschleife führen könnte.

Wenn Sie Ereignisse aus einer Erweiterung veröffentlichen, können Benutzer Ereignishandler bereitstellen, um mit benutzerdefinierter Logik zu reagieren.

Im folgenden Beispiel wird beispielsweise das Originalbild gelöscht, nachdem dessen Größe geändert wurde. Beachten Sie, dass dieser Beispielhandler die subject Eigenschaft des Ereignisses verwendet, in diesem Fall den ursprünglichen Dateinamen des Bildes.

exports.onimageresized = onCustomEventPublished(
    "firebase.extensions.storage-resize-images.v1.complete",
    (event) => {
      logger.info("Received image resize completed event", event);
      // For example, delete the original.
      return admin.storage()
          .bucket("my-project.appspot.com")
          .file(event.subject)
          .delete();
    });

Weitere Informationen finden Sie unter Benutzerdefinierte Ereignisauslöser .

Beispiel

Die offizielle Erweiterung „Resize Images“ bietet einen asynchronen Hook, indem sie nach der Größenänderung eines Bildes auf Eventarc veröffentlicht .

Synchronhaken

Wenn Sie Benutzern einen Hook bereitstellen möchten, der erfolgreich abgeschlossen werden muss, damit eine Ihrer Erweiterungsfunktionen funktioniert, verwenden Sie synchrone Hooks .

Ein synchroner Hook ruft eine benutzerdefinierte HTTPS-aufrufbare Cloud-Funktion auf und wartet auf den Abschluss (möglicherweise mit einem zurückgegebenen Wert), bevor er fortfährt. Ein Fehler in der vom Benutzer bereitgestellten Funktion führt zu einem Fehler in der Erweiterungsfunktion.

So machen Sie einen synchronen Hook verfügbar:

  1. Fügen Sie Ihrer Erweiterung einen Parameter hinzu, der es Benutzern ermöglicht, die Erweiterung mit der URL zu ihrer benutzerdefinierten Cloud-Funktion zu konfigurieren. Zum Beispiel:

    - param: PREPROCESSING_FUNCTION
      label: Pre-processing function URL
      description: >
        An HTTPS callable function that will be called to transform the input data
        before it is processed by this function.
      type: string
      example: https://us-west1-my-project-id.cloudfunctions.net/preprocessData
      required: false
    
  2. Rufen Sie an der Stelle in Ihrer Erweiterung, an der Sie den Hook verfügbar machen möchten, die Funktion über ihre URL auf. Zum Beispiel:

    const functions = require('firebase-functions');
    const fetch = require('node-fetch');
    
    const preprocessFunctionURL = process.env.PREPROCESSING_FUNCTION;
    
    exports.yourFunctionName = functions.firestore.document("collection/{doc_id}")
        .onWrite((change, context) => {
          // PREPROCESSING_FUNCTION hook begins here.
          // If a preprocessing function is defined, call it before continuing.
          if (preprocessFunctionURL) {
            try {
              await fetch(preprocessFunctionURL); // Could also be a POST request if you want to send data.
            } catch (e) {
              // Preprocessing failure causes the function to fail.
              functions.logger.error("Preprocessor error:", e);
              return;
            }
          }
          // End of PREPROCESSING_FUNCTION hook.
    
          // Main function logic follows.
          // ...
        });
    
  3. Dokumentieren Sie alle Hooks, die Sie in der PREINSTALL- oder POSTINSTALL-Datei zur Verfügung stellen.

    Dokumentieren Sie für jeden Hook Folgendes:

    • Sein beabsichtigter Zweck
    • Der Punkt in der Logik Ihrer Erweiterung, an dem sie ausgeführt wird
    • Seine erwarteten Ein- und Ausgänge
    • Die Bedingungen (oder Optionen) für seine Ausführung

    Warnen Sie Benutzer außerdem davor, in der Hook-Funktion Aktionen auszuführen, die möglicherweise dieselbe Erweiterung auslösen, was zu einer Endlosschleife führen könnte.

Beispiel

Die Algolia Search-Erweiterung bietet einen synchronen Hook zum Aufrufen einer vom Benutzer bereitgestellten Transformationsfunktion vor dem Schreiben in Algolia.