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

Użytkownicy, którzy zainstalują Twoje rozszerzenie, mogą wstawiać własną logikę niestandardową do jego działania. Możesz 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ą wdrażać funkcje obsługi zdarzeń, które np. wysyłają powiadomienia po zakończeniu długotrwałych zadań, lub definiować własne funkcje przetwarzania końcowego.

  • Synchroniczne punkty zaczepienia: aby umożliwić użytkownikom dodawanie logiki blokowania do rozszerzenia, możesz dodać synchroniczne punkty zaczepienia w określonych miejscach działania rozszerzenia. W tych miejscach uruchamiasz funkcję dostawcy użytkownika i kontynuujesz działanie dopiero po jej zakończeniu. Zadania wstępnego przetwarzania często należą do tej kategorii.

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

Zdarzenia Eventarc

Aby publikować wydarzenia z rozszerzenia:

  1. Zadeklaruj typy zdarzeń, które będziesz 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 oddzielonych 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 jeden 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.
    

    Użytkownicy będą mogli wybrać, które wydarzenia chcą subskrybować, gdy zainstalują rozszerzenie.

  2. W funkcjach rozszerzenia zaimportuj interfejs Eventarc API z Admin SDKi zainicjuj kanał zdarzeń, używając ustawień instalacji użytkownika. Te ustawienia są udostępniane za pomocą tych zmiennych środowiskowych:

    • EVENTARC_CHANNEL: pełna nazwa kanału Eventarc, na którym użytkownik zdecydował się publikować zdarzenia.
    • EXT_SELECTED_EVENTS: lista typów wydarzeń wybranych przez użytkownika do opublikowania, oddzielona przecinkami. Gdy zainicjujesz kanał z tą wartością, pakiet Admin SDK automatycznie odfiltruje zdarzenia, których użytkownik nie wybrał.
    • EVENTARC_CLOUD_EVENT_SOURCE: identyfikator źródła Cloud Event. Pakiet Admin SDK automatycznie przekazuje tę wartość w polu source opublikowanych zdarzeń. Zwykle nie musisz używać tej zmiennej w sposób jawny.

    Jeśli zdarzenia nie zostały włączone podczas instalacji, te zmienne będą miały wartość undefined. Możesz wykorzystać ten fakt, 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 zdarzenia na kanale w miejscach w rozszerzeniu, 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. Zapisz opublikowane zdarzenia w pliku PREINSTALL lub POSTINSTALL.

    W przypadku każdego zdarzenia udokumentuj te informacje:

    • zamierzone przeznaczenie,
    • Moment w logice rozszerzenia, w którym jest ono uruchamiane.
    • Dane wyjściowe, które zawiera
    • warunki jego wykonania,

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

Gdy publikujesz zdarzenia z rozszerzenia, użytkownicy mogą wdrażać procedury obsługi zdarzeń, aby odpowiadać za pomocą niestandardowej logiki.

Na przykład poniższy kod usuwa oryginalny obraz 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.firebasestorage.app")
          .file(event.subject)
          .delete();
    });

Więcej informacji znajdziesz w sekcji Zdarzenia niestandardowe.

Przykład

Oficjalne rozszerzenie Resize Images udostępnia asynchroniczny punkt zaczepienia, publikując w Eventarc po zmianie rozmiaru obrazu.

Synchroniczne wywołania zwrotne

Jeśli chcesz udostępnić użytkownikom punkt zaczepienia, który musi zostać wykonany, aby jedna z funkcji rozszerzenia działała, użyj synchronicznych punktów zaczepienia.

Synchroniczny wywołuje zdefiniowaną przez użytkownika funkcję Cloud Function wywoływaną przez HTTPS i czeka na jej zakończenie (ewentualnie z wartością zwracaną) przed kontynuowaniem. Błąd w funkcji podanej przez użytkownika powoduje błąd w funkcji rozszerzenia.

Aby udostępnić synchroniczny hook:

  1. Dodaj do rozszerzenia parametr, który umożliwi użytkownikom skonfigurowanie rozszerzenia za pomocą adresu URL 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 rozszerzenia, w którym chcesz udostępnić hook, 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. W pliku PREINSTALL lub POSTINSTALL udokumentuj wszystkie udostępniane przez siebie punkty zaczepienia.

    W przypadku każdego haka udokumentuj te informacje:

    • zamierzone przeznaczenie,
    • Moment w logice rozszerzenia, w którym jest ono uruchamiane.
    • oczekiwane dane wejściowe i wyjściowe,
    • warunki (lub opcje) jego wykonania;

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

Przykład

Rozszerzenie Algolia Search udostępnia synchroniczny punkt zaczepienia do wywoływania funkcji przekształcania dostarczonej przez użytkownika przed zapisaniem danych w Algolii.