Вы можете предоставить пользователям, установившим ваше расширение, возможность встраивать собственную логику в его выполнение. Это можно сделать двумя способами:
События Eventarc : чтобы предоставить пользователям возможность асинхронно реагировать на события, вы можете публиковать их в Eventarc. Пользователи могут развертывать функции обработчиков событий, которые, например, отправляют уведомления после завершения длительных задач, или определять собственные функции постобработки.
Синхронные хуки : чтобы предоставить пользователям возможность добавлять блокирующую логику в ваше расширение, вы можете добавлять синхронные хуки в предопределенных точках работы расширения. В этих точках вы запускаете функцию-поставщик данных и продолжаете работу только после ее завершения. Задачи предварительной обработки часто относятся к этой категории.
Расширение может использовать один из этих методов или оба сразу.
События Eventarc
Для публикации событий из расширения:
В файле
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Идентификатор
typeсостоит из нескольких полей, разделенных точками. Поля «ID издателя» , «имя расширения» и «имя события» являются обязательными. Поле «версия» рекомендуется. Для каждого публикуемого вами типа события выбирайте уникальное и описательное имя события.Например, расширение
storage-resize-imagesобъявляет единственный тип события: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.После установки расширения пользователи смогут выбирать, на какие события подписаться.
В функциях расширения импортируйте API Eventarc из Admin SDK и инициализируйте канал событий, используя параметры установки пользователя. Эти параметры доступны через следующие переменные среды:
-
EVENTARC_CHANNEL: полное имя канала Eventarc, в который пользователь решил публиковать события. -
EXT_SELECTED_EVENTS: список типов событий, разделенных запятыми, которые пользователь выбрал для публикации. При инициализации канала с этим значением Admin SDK автоматически отфильтровывает события, которые пользователь не выбрал. -
EVENTARC_CLOUD_EVENT_SOURCE: идентификатор источника облачных событий. Административный SDK автоматически передает это значение в полеsourceопубликованных событий. Обычно нет необходимости явно использовать эту переменную.
Если при установке не была включена поддержка событий, эти переменные будут неопределенными. Вы можете использовать это для инициализации канала событий только тогда, когда события включены:
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, });-
Публикуйте события в канале в тех местах вашего расширения, которые вы хотите сделать доступными для пользователей. Например:
// 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: { // ... } });Документируйте публикуемые вами события в файле PREINSTALL или POSTINSTALL.
Для каждого события задокументируйте следующее:
- Его предназначение
- Точка в логике вашего расширения, где оно выполняется.
- Выходные данные, которые он включает
- Условия его исполнения
Кроме того, следует предупредить пользователей о том, что в обработчиках событий не следует выполнять действия, которые могут активировать то же самое расширение, что приведет к бесконечному циклу.
При публикации событий из расширения пользователи могут развертывать обработчики событий для генерации собственной логики.
Например, следующий пример удаляет исходное изображение после изменения его размера. Обратите внимание, что в этом примере обработчик использует свойство subject события, которое в данном случае представляет собой исходное имя файла изображения.
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();
});
Дополнительную информацию см. в разделе «Пользовательские триггеры событий» .
Пример
Официальное расширение Resize Images обеспечивает асинхронный перехват, публикуя данные в Eventarc после изменения размера изображения.
Синхронные крючки
Если вам нужно предоставить пользователям хук, который должен успешно завершиться для корректной работы одной из ваших функций расширения, используйте синхронные хуки .
Синхронный обработчик вызывает определяемую пользователем облачную функцию, запускаемую по протоколу HTTPS , и ожидает завершения (возможно, с возвращенным значением), прежде чем продолжить. Ошибка в предоставленной пользователем функции приводит к ошибке в функции расширения.
Чтобы открыть синхронный обработчик:
Добавьте в расширение параметр, позволяющий пользователям настраивать расширение, указывая URL-адрес их собственной облачной функции. Например:
- 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В том месте вашего расширения, где вы хотите сделать хук доступным, вызовите функцию, используя её URL-адрес. Например:
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. // ... });Задокументируйте все доступные вам перехватчики событий в файлах PREINSTALL или POSTINSTALL.
Для каждого крючка задокументируйте следующее:
- Его предназначение
- Точка в логике вашего расширения, где оно выполняется.
- Ожидаемые входные и выходные данные
- Условия (или варианты) его выполнения
Кроме того, следует предупредить пользователей о том, что в функции-перехватчике нельзя выполнять действия, которые могут активировать то же самое расширение, что приведет к бесконечному циклу.
Пример
Расширение Algolia Search предоставляет синхронный обработчик для вызова предоставленной пользователем функции преобразования перед записью в Algolia.