В этом документе объясняется, как создать стартовый объект, который позволит вашему приложению или сервису уведомлять Google Workspace Studio о возникновении события и инициировать выполнение потока. В API стартовые объекты называются workflowTriggers .
Запуск (стартер) — это начало процесса, а шаг (шаг) — это отдельная задача в последовательности задач, составляющих этот процесс. Создав стартер, вы позволяете пользователям настраивать автоматизированные процессы, реагирующие на события в реальном времени из вашего приложения или сервиса.
Создание стартового приложения включает в себя объявление стартового приложения в файле манифеста дополнения и реализацию обратных вызовов жизненного цикла в Google Apps Script, либо запуск стартового приложения путем отправки полезных нагрузок на конечную точку API Google Workspace Studio.
Предварительные условия и авторизация OAuth.
Для взаимодействия с конечной точкой API Workspace Studio ваше приложение или служба должны пройти аутентификацию с использованием OAuth 2.0. Приложение должно запросить у пользователей следующую выделенную область действия OAuth во время авторизации:
https://www.googleapis.com/auth/workspace.studio.trigger
Данная область действия разрешает приложению вызывать API Workspace Studio и запускать потоки, которые пользователь настроил для данного стартового набора.
Токены для доступа в автономном режиме и обновления
Поскольку стартовые процессы асинхронно уведомляют Workspace Studio о событиях, происходящих во внешней службе (что может случиться через несколько часов, дней или месяцев после того, как пользователь настроит поток), ваша служба должна предоставлять действительный токен доступа OAuth 2.0 при вызове конечной точки API.
Токен доступа, предоставляемый Google в объекте события дополнения (например, во время начальной настройки или запросов обратного вызова жизненного цикла), имеет короткий срок действия и действителен только в течение 1 часа. Его недостаточно для асинхронного запуска событий запуска в будущем. Для вызова API Workspace Studio с течением времени вашему сервису потребуется офлайн- токен обновления для генерации новых токенов доступа по запросу.
Способ обработки авторизации и получения токена обновления зависит от среды выполнения вашего дополнения:
HTTP-дополнения (альтернативные среды выполнения) : Для HTTP-дополнений ваша серверная служба должна реализовать отдельный поток авторизации OAuth 2.0, независимый от встроенной авторизации дополнения, чтобы запросить доступ в автономном режиме (
access_type=offline) и получить токен обновления.Вы можете предложить пользователям авторизовать это соединение, отобразив карточку входа или авторизации при настройке стартового шаблона в Workspace Studio. Дополнительную информацию о возврате карточек авторизации и обработке потока OAuth см. в разделе «Подключение надстройки Google Workspace к стороннему сервису (рассматривая Google Workspace как сторонний сервис, к которому вы подключаетесь)».
Ваш бэкэнд-сервис должен надежно хранить токен обновления (например, в базе данных вашего сервиса вместе с
triggerId) и использовать его для получения нового токена доступа при каждом возникновении события, прежде чем отправлять запросы кnotifyUriстартового объекта или конечной точке APItriggers.fire.Дополнения Google Apps Script : Дополнения на основе Google Apps Script, использующие запланированные (управляемые временем) триггеры для опроса событий, могут обойтись без реализации независимого потока OAuth. Поскольку запланированные триггеры выполняются непосредственно в среде выполнения Google Apps Script, Google Apps Script автоматически управляет и обновляет токены OAuth, используя области действия, объявленные в манифесте.
Определите загрузчик в файле манифеста.
Чтобы определить стартовый элемент, добавьте его в файл манифеста дополнения ( appsscript.json ) в блоке addOns.studio.flows.workflowElements . Эта конфигурация необходима как для среды выполнения Apps Script, так и для среды выполнения HTTP (альтернативные среды выполнения). Настройте элемент как workflowTrigger вместо workflowAction (который используется при определении шага). Для получения дополнительной информации см. раздел «Структура манифеста для дополнений Google Workspace» .
Внутри блока workflowTrigger укажите:
-
inputs: переменные, которые пользователь настраивает на карточке конфигурации (например, название проекта, фильтр ресурсов и т. д.). -
outputs: Переменные, возвращаемые стартовым процессом последующим этапам потока. -
onConfigFunction: Имя функции обратного вызова, которая отображает интерфейс пользовательской конфигурации. -
onManageFunction: Название функции обратного вызова, вызываемой Google для обработки создания и удаления начальной подписки.
В следующем примере кода показано определение манифеста для запуска события:
JSON
{
"timeZone": "America/Los_Angeles",
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"addOns": {
"common": {
"name": "Trigger App",
"logoUrl": "https://fonts.gstatic.com/s/i/short-term/release/googlesymbols/start/default/24px.svg",
"useLocaleFromApp": true
},
"studio": {
"flows": {
"workflowElements": [
{
"id": "triggerDemo",
"state": "ACTIVE",
"name": "Event Trigger",
"description": "Fires when a event occurs in the app.",
"workflowTrigger": {
"inputs": [
{
"id": "projectId",
"description": "The project identifier to watch.",
"cardinality": "SINGLE",
"dataType": {
"basicType": "STRING"
}
}
],
"outputs": [
{
"id": "eventName",
"description": "The name of the triggered event.",
"cardinality": "SINGLE",
"dataType": {
"basicType": "STRING"
}
},
{
"id": "eventMessage",
"description": "Detailed event message description.",
"cardinality": "SINGLE",
"dataType": {
"basicType": "STRING"
}
}
],
"onConfigFunction": "onConfigTrigger",
"onManageFunction": "onManageTrigger"
}
}
]
}
}
}
}
Управление жизненным циклом стартовой подписки
Когда пользователь настраивает и активирует поток, содержащий ваш стартовый шаблон, или если поток отключен или удален, Google вызывает ваше дополнение, используя функцию обратного вызова onManageFunction объявленную в манифесте.
Объект события жизненного цикла
Функция обратного вызова получает объект WorkflowEventObject , содержащий контекст действия. Для начала это включает в себя:
Создание триггера (
event.workflow.triggerCreation) : срабатывает при публикации или включении потока.triggerId: Уникальная строка UUID, идентифицирующая этот экземпляр начальной регистрации.notifyUri: Уникальный URL-адрес конечной точки REST API, связанный с этой начальной регистрацией (например,https://workspacestudio.googleapis.com/v1/triggers/YOUR_TRIGGER_ID:fire).inputs: переменные входных параметров, задаваемые пользователем на карточке.
Удаление триггера (
event.workflow.triggerDeletion) : срабатывает, когда инициатор удаляется из потока, или когда весь поток отключается или удаляется.-
triggerId: Уникальный UUID-код экземпляра подписки, подлежащего очистке.
-
Жизненный цикл подписки на альтернативные среды выполнения (HTTP API)
Для дополнений, созданных с использованием альтернативных сред выполнения, уведомления о жизненном цикле подписки доставляются с помощью HTTP POST-запросов к настроенному HTTP-адресу конечной точки дополнения с именем действия, указанным в функции обратного вызова onManageFunction . Полезная нагрузка соответствует JSON-представлению объекта WorkflowEventObject .
Для получения дополнительной информации об альтернативных средах выполнения см. раздел «Создание дополнения Google Workspace с использованием HTTP-конечных точек» .
Реализуйте обратные вызовы жизненного цикла в Apps Script.
В следующем примере Apps Script показано, как настроить карточку пользовательского интерфейса, обрабатывать события жизненного цикла подписки с помощью onManageTrigger и отправлять запрос на запуск обратно в Google при возникновении события.
Apps Script
/**
* Generates and returns the user configuration card to collect inputs.
*/
function onConfigTrigger() {
const projectInput = CardService.newTextInput()
.setFieldName("projectId")
.setTitle("Project ID")
.setHint("Enter the project identifier to watch");
const section = CardService.newCardSection()
.setHeader("Configure Event Trigger")
.addWidget(projectInput);
const card = CardService.newCardBuilder()
.addSection(section)
.build();
return card;
}
/**
* Handles subscription lifecycle events sent from Google Workspace Studio.
*
* @param {Object} event The Workspace Studio event object.
*/
function onManageTrigger(event) {
const triggerCreation = event.workflow.triggerCreation;
const triggerDeletion = event.workflow.triggerDeletion;
if (triggerCreation) {
const triggerId = triggerCreation.triggerId;
const notifyUri = triggerCreation.notifyUri;
const inputs = triggerCreation.inputs;
// Extract input values configured by the user.
const projectId = inputs["projectId"].stringValues[0];
// TODO: Save triggerId, notifyUri, and projectId in your database/service.
// Your backend service listens for events related to 'projectId'
// and calls notifyUri when those events occur.
console.log("Trigger subscription created: " + triggerId +
", Notify URI: " + notifyUri +
", Match Project: " + projectId);
} else if (triggerDeletion) {
const triggerId = triggerDeletion.triggerId;
// TODO: Remove references to triggerId from your database and stop
// sending future event notifications to the associated notifyUri.
console.log("Trigger subscription deleted: " + triggerId);
}
}
/**
* Mock function showing how your backend service fires the trigger.
* This logic runs on your service when a watched event occurs.
*
* @param {string} notifyUri The stored notifyUri associated with the trigger.
* @param {string} triggerId The stored triggerId.
* @param {string} userAccessToken The OAuth 2.0 access token for the user
* (obtained using your stored refresh token).
*/
function simulateEventFire(notifyUri, triggerId, userAccessToken) {
// A unique UUID version 4 is recommended as the requestId for idempotency.
const requestId = Utilities.getUuid();
const payload = {
"name": "triggers/" + triggerId,
"outputs": {
"eventName": { "stringValues": ["EventOccurred"] },
"eventMessage": { "stringValues": ["Hello from the service!"] }
},
"requestId": requestId
};
const options = {
"method": "POST",
"contentType": "application/json",
"headers": {
"Authorization": "Bearer " + userAccessToken
},
"payload": JSON.stringify(payload),
"muteHttpExceptions": true
};
const response = UrlFetchApp.fetch(notifyUri, options);
const responseCode = response.getResponseCode();
if (responseCode === 200) {
console.log("Trigger successfully fired!");
} else if (responseCode === 404) {
// 404 means the trigger registration is invalid or deleted.
console.log("Trigger not found. Stop sending events for this trigger.");
// TODO: Clean up the trigger from your backend database.
} else if (responseCode === 429 || responseCode >= 500) {
console.log("Temporary error (" + responseCode + "). Retry using exponential backoff.");
} else {
console.log("Failed to fire trigger. HTTP Code: " + responseCode + " - " + response.getContentText());
}
}
Используйте API Workspace Studio
Вы можете использовать API Workspace Studio ( workspacestudio.googleapis.com ) для программного уведомления Google о событиях запуска.
Конечные точки находятся по базовому пути: https://workspacestudio.googleapis.com/v1 .
Уведомляет о начале события
Запускает пусковой механизм с помощью метода triggers.fire для инициирования выполнения потока.
- Метод HTTP :
POST - Путь :
/v1/triggers/{triggerId}:fire(где{triggerId}— уникальный идентификатор, полученный при создании подписки на триггер) - Область действия OAuth :
https://www.googleapis.com/auth/workspace.studio.trigger
Приведённый ниже пример кода показывает, как запустить стартовый процесс в запросе.
Запрос
{
"name": "triggers/TRIGGER_ID",
"outputs": {
"eventName": {
"stringValues": [
"EventOccurred"
]
},
"eventMessage": {
"stringValues": [
"Hello from the service!"
]
}
},
"log": {
"textFormatElements": [
{
"text": "An event occurred in the app."
}
]
},
"requestId": "UNIQUE_REQUEST_ID"
}
-
name(строка, обязательно): Имя ресурса стартера, отформатированное какtriggers/{triggerId}. -
outputs(map, optional): Карта начальных выходных переменных, представляющих данные события. Каждое значение представляет собой объектVariableData, поддерживающий типизированные списки (например,stringValues,booleanValues,integerValues). -
log(object, optional): Представление разметкиTextFormatотображаемое в журналах активности выполнения Workspace Studio. -
requestId(строка, необязательно): Уникальный идентификатор (рекомендуется UUID v4) длиной до 36 символов ASCII для обеспечения идемпотентности API при повторных попытках.
Ответ
В случае успеха ответ возвращает пустой JSON-объект {} .
Квоты API Workspace Studio
Трафик, направляемый в сервис workspacestudio.googleapis.com , ограничивается во избежание перегрузки системы, для обеспечения справедливого использования ресурсов и защиты общей производительности Google Workspace.
Вводятся следующие квоты:
| Тип квоты | Квота |
|---|---|
| Поминутно на проект | 1000 стартовых запросов |
| Поминутно с пользователя | 100 стартовых запросов |
Типы квот:
- За минуту на проект : ограничивает суммарное количество событий запуска, запускаемых из проекта Google Cloud одного разработчика, до 1000 запросов в минуту для всех пользователей, запускающих эти события.
- За минуту на пользователя : ограничивает суммарное количество запусков программы одним конечным пользователем в рамках данного облачного проекта до 100 запросов в минуту.
Обработка ошибок, связанных с временными квотами.
Если вы превысите эти квоты, API вернет код ошибки HTTP 429 Too Many Requests (или 429 Resource Exhausted ), указывающий на то, что квота на количество запросов превышена.
Для устранения этих ошибок ваш код должен перехватывать исключение и использовать стратегию усеченной экспоненциальной задержки. Экспоненциальная задержка повторяет неудачные запросы, используя постепенно увеличивающиеся задержки между попытками, включая случайный джиттер (пересчет случайной задержки на каждой итерации), чтобы предотвратить одновременную синхронизацию и повторные попытки нескольких клиентов:
- Отправьте запрос к API Workspace Studio.
- Если запрос завершится с ошибкой
429, подождите1 second + random_number_millisecondsи повторите попытку. - Если ошибка повторится, подождите
2 seconds + random_number_millisecondsи повторите попытку. - Если ошибка повторится, подождите
4 seconds + random_number_millisecondsи повторите попытку. - Продолжайте этот цикл, удваивая задержку до достижения порогового значения
maximum_backoff(обычно 32 или 64 секунды). - Как только будет достигнута максимальная продолжительность задержки, повторите попытку, используя эту постоянную задержку, пока не будет достигнут максимальный лимит повторных попыток, затем остановите процесс и запишите ошибку в журнал.
Передовые методы
При разработке и внедрении стартового пакета следует учитывать следующие передовые методы:
Вместо пакетных списков генерировать отдельные события.
Настройте свой стартовый сценарий таким образом, чтобы он генерировал отдельное событие для каждого отдельного случая (например, обновление одной записи, отправка нового сообщения или назначение задачи), а не одно событие, содержащее пакет или список элементов:
- Согласованность со встроенными запускающими событиями : В Workspace Studio встроенные запускающие события Google Workspace (например, получение электронного письма в Gmail или присоединение пользователя к пространству в Google Chat) срабатывают по одному событию. Генерация событий, состоящих из одного элемента, соответствует этому поведению и обеспечивает согласованный и предсказуемый пользовательский опыт для всех запускающих событий.
- Упрощенная конфигурация потока : последующие этапы потока обычно обрабатывают один элемент за раз. Генерация событий для отдельных элементов позволяет пользователям напрямую сопоставлять переменные без добавления сложных шагов для итерации по массивам или разбора списков.
- Обрабатывайте опросы и пакетные изменения по отдельности : если ваш бэкэнд-сервис опрашивает внешний API и обнаруживает несколько измененных элементов в течение одного интервала опроса, запускайте отдельное событие-запуск для каждого элемента, а не объединяйте их в одно пакетное событие.
- Управление частотой событий и квотами : Поскольку отправка отдельных событий для множества измененных элементов может вызвать внезапный всплеск запросов, убедитесь, что ваш сервис остается в пределах квот API Workspace Studio (например, лимит в 100 запросов в минуту на пользователя). Если цикл опроса генерирует большой объем элементов (например, более 100 измененных записей), регулируйте или ограничивайте отправку событий во времени, чтобы избежать ошибок
429 Too Many Requests.
Основные модели поведения и граничные случаи
При интеграции стартовых модулей разработчикам необходимо обрабатывать специфические ошибки и учитывать особенности среды выполнения:
- Отсутствие поддержки тестовых запусков : Workspace Studio изначально не поддерживает тестовые запуски.
- Идемпотентность и предотвращение повторного воспроизведения : Хотя это и не является строго обязательным, следует включать уникальный
requestId(например, UUID) в полезную нагрузку HTTP или Apps Script. Предоставление идентификатораrequestIdобеспечивает идемпотентность, позволяя API обнаруживать и игнорировать дублирующиеся уведомления, предотвращая многократное выполнение потока для одного и того же события. Отключенные и повторно включенные потоки : Когда поток, содержащий ваш стартовый объект, отключается в Workspace Studio, Google отправляет событие жизненного цикла
triggerDeletionв ваш коллбэкonManageFunction. Кроме того, любые вызовы связанного методаFireTriggerвозвращают код ошибки404 Not Found(Requested entity was not found.). Ваш сервис должен реагировать на ошибки404, прекращая дальнейшую доставку уведомлений о событиях для этого идентификатора экземпляра стартового объекта.Если пользователь впоследствии повторно активирует поток, Google запускает новый цикл жизни подписки, вызывая ваш коллбэк
onManageFunctionс новым событиемtriggerCreation, содержащим новыйtriggerIdиnotifyUri. ПредыдущийtriggerIdнавсегда выводится из эксплуатации и не активируется повторно, поэтому ваш сервис не должен опрашивать или проверять, был ли повторно активирован старый экземпляр триггера. Для получения дополнительной информации см. раздел «Обработка начального цикла подписки» .Идемпотентное удаление подписки : Ваша функция обратного вызова
onManageFunctionдолжна обрабатывать запросы на удаление от Google идемпотентно. Если Google вызывает обработчик удаления несколько раз для одного и того жеtriggerId(например, во время повторных попыток из-за временной потери соединения), функция должна успешно завершить работу.Квоты потоков : Помимо квот API Workspace Studio, на пользовательские потоки распространяются дополнительные внутренние ограничения. Частотные циклы или чрезмерный объем событий могут превысить пороговые значения безопасности, что приведет к автоматическому отключению потока.
Связанные темы
- Постройте ступеньку
- Подключите надстройку Google Workspace к стороннему сервису.
- Входные переменные
- Выходные переменные
- Журналы активности и ошибок
- Обработка ошибок
- Объекты событий Workspace Studio