Dodawanie do rozszerzenia elementów, które zaciągają użytkowników

Możesz umożliwić użytkownikom, którzy zainstalują Twoje rozszerzenie, wstawianie własnej logiki niestandardowej podczas jego działania. Można to zrobić na 2 sposoby:

  • Zdarzenia Eventarc: aby umożliwić użytkownikom asynchroniczne reagowanie na zdarzenia, możesz publikować je w Eventarc. Użytkownicy mogą stosować funkcje przetwarzania zdarzeń, które na przykład wysyłają powiadomienia po zakończeniu długotrwałych zadań. Mogą też definiować własne funkcje przetwarzania w drugim etapie.

  • Synchroniczne hooki: aby umożliwić użytkownikom dodanie logiki blokującej do rozszerzenia, możesz dodać synchroniczne punkty zaczepienia w zdefiniowanych wstępnie punktach działania rozszerzenia. W tych miejscach uruchamiasz funkcję dostawcy danych użytkownika i kontynuujesz dopiero po jej zakończeniu. Do tej kategorii często należą zadania wstępnego przetwarzania.

Rozszerzenie może korzystać z jednej z tych metod lub z obu tych metod.

Zdarzenia Eventarc

Aby opublikować zdarzenia z rozszerzenia:

  1. Zadeklaruj typy zdarzeń, które chcesz publikować w pliku extension.yaml:

    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
    

    Identyfikator type składa się z kilku pól rozdzielanych kropkami. Pola identyfikator wydawcy, nazwa rozszerzenia i nazwa zdarzenia są wymagane. Pole wersji jest zalecane. Wybierz unikalną i opisową nazwę zdarzenia dla każdego publikowanego typu zdarzenia.

    Na przykład rozszerzenie storage-resize-images deklaruje 1 typ zdarzenia:

    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.
    

    Po zainstalowaniu rozszerzenia użytkownicy będą mogli wybrać, na które wydarzenia chcą się zapisać.

  2. W funkcjach rozszerzenia zaimportuj interfejs Eventarc API z Admin SDKi inicjuj kanał zdarzeń, używając ustawień instalacji użytkownika. Te ustawienia są ujawniane przy użyciu następujących zmiennych środowiskowych:

    • EVENTARC_CHANNEL: pełna nazwa kanału Eventarc, w którym użytkownik postanowił opublikować zdarzenia.
    • EXT_SELECTED_EVENTS: lista oddzielonych przecinkami typów wydarzeń, które użytkownik chce opublikować. Gdy inicjujesz kanał za pomocą tej wartości, pakiet Admin SDK automatycznie odfiltrowuje zdarzenia, których użytkownik nie wybrał.
    • EVENTARC_CLOUD_EVENT_SOURCE: identyfikator źródła zdarzeń Cloud. Pakiet Admin SDK automatycznie przekazuje tę wartość w polu source opublikowanych zdarzeń. Zwykle nie trzeba jej bezpośrednio używać.

    Jeśli podczas instalacji zdarzenia nie zostały włączone, te zmienne będą nieokreślone. Możesz skorzystać z tej informacji, aby zainicjować kanał zdarzeń tylko wtedy, gdy zdarzenia są włączone:

    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. Publikuj na kanale zdarzenia w miejscach rozszerzenia, które chcesz udostępnić użytkownikom. Przykład:

    // 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. Udokumentuj publikowane zdarzenia w pliku PREINSTALL lub POSTINSTALL.

    W przypadku każdego wydarzenia udokumentuj te informacje:

    • Zamierzone zastosowanie
    • Punkt w logice rozszerzenia, w którym jest ono wykonywane
    • Dane wyjściowe, które zawiera.
    • warunki jego wykonania.

    Dodatkowo ostrzegaj użytkowników, aby nie wykonywali żadnych działań w obsługach zdarzeń, które mogłyby wywołać to samo rozszerzenie, powodując nieskończoną pętlę.

Gdy opublikujesz zdarzenia z poziomu rozszerzenia, użytkownicy będą mogli stosować ich obsługi, aby reagować na nie za pomocą logiki niestandardowej.

Na przykład w tym przykładzie oryginalny obraz jest usuwany po zmianie jego rozmiaru. Zwróć uwagę, że ten przykładowy moduł obsługi korzysta z właściwości subject zdarzenia, która w tym przypadku jest oryginalną nazwą pliku obrazu.

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

Więcej informacji znajdziesz w sekcji Wyzwalacze zdarzeń niestandardowych.

Przykład

Oficjalne rozszerzenie do zmiany rozmiaru obrazu zapewnia asynchroniczny element wywoławczy, który publikuje w Eventarc po zmianie rozmiaru obrazu.

Elementy synchroniczne

Jeśli chcesz udostępnić użytkownikom element wywołania, który musi zostać wykonany prawidłowo, aby jedna z funkcji rozszerzenia mogła działać, użyj elementów wywołania synchronicznego.

Zaczep synchroniczny wywołuje zdefiniowaną przez użytkownika funkcję uruchamianą przez HTTPS w usłudze Cloud Function i czeka na jej zakończenie (być może z wartością zwracaną) przed kontynuacją. Błąd w funkcji dostarczonej przez użytkownika powoduje błąd w funkcji rozszerzenia.

Aby ujawnić element synchroniczny:

  1. Dodaj do rozszerzenia parametr, który pozwoli użytkownikom skonfigurować rozszerzenie z adresem URL ich niestandardowej funkcji w Cloud Functions. Przykład:

    - 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. W miejscu w rozszerzeniu, w którym chcesz ujawnić element wywołania, wywołaj funkcję za pomocą jej adresu URL. Przykład:

    const functions = require('firebase-functions/v1');
    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. Zapisz wszystkie dostępne punkty wywołania w pliku PREINSTALL lub POSTINSTALL.

    W przypadku każdego elementu zaczepu opisz te informacje:

    • Zamierzone zastosowanie
    • Punkt w logice rozszerzenia, w którym jest ono wykonywane
    • oczekiwane dane wejściowe i wyjściowe;
    • warunki (lub opcje) wykonania kodu;

    Dodatkowo ostrzegaj użytkowników, aby nie wykonywali żadnych działań w funkcji hook, które mogłyby wywołać to samo rozszerzenie, powodując nieskończoną pętlę.

Przykład

Rozszerzenie Algolia Search zawiera synchroniczny punkt zaczepienia służący do wywoływania dostarczonej przez użytkownika funkcji przekształcenia przed zapisem do Algolii.