Créer un starter

Ce document explique comment créer un starter qui permet à votre application ou service d'informer Google Workspace Studio lorsqu'un événement se produit et de lancer l'exécution d'un flux. Dans l'API, les déclencheurs sont appelés workflowTriggers.

Un déclencheur lance un flux, tandis qu'une étape est une tâche unique dans la séquence de tâches qui composent un flux. En créant un starter, vous permettez aux utilisateurs de configurer des flux automatisés qui réagissent aux événements en temps réel de votre application ou service.

Pour créer un starter, vous devez le déclarer dans le fichier manifeste du module complémentaire et implémenter des rappels de cycle de vie dans Google Apps Script, ou déclencher le starter en publiant des charges utiles sur le point de terminaison de l'API Google Workspace Studio.

Conditions préalables et autorisation OAuth

Pour communiquer avec le point de terminaison de l'API Workspace Studio, votre application ou service doit s'authentifier à l'aide d'OAuth 2.0. L'application doit demander aux utilisateurs le niveau d'accès OAuth dédié suivant lors de l'autorisation :

https://www.googleapis.com/auth/workspace.studio.trigger

Ce champ d'application autorise l'application à appeler l'API Workspace Studio et à déclencher les flux que l'utilisateur a configurés pour ce starter.

Accès hors connexion et jetons d'actualisation

Étant donné que les déclencheurs avertissent Workspace Studio de manière asynchrone lorsqu'un événement se produit dans le service externe (ce qui peut se produire des heures, des jours ou des mois après qu'un utilisateur a configuré un flux), votre service doit fournir un jeton d'accès OAuth 2.0 valide lorsqu'il appelle le point de terminaison de l'API.

Le jeton d'accès fourni par Google dans l'objet d'événement du module complémentaire (par exemple, lors de la configuration initiale ou des requêtes de rappel de cycle de vie) est de courte durée et n'est valide que pendant une heure. Cela ne suffit pas pour déclencher des événements de démarrage de manière asynchrone à l'avenir. Pour appeler l'API Workspace Studio au fil du temps, votre service nécessite un jeton d'actualisation hors connexion pour générer de nouveaux jetons d'accès à la demande.

La façon dont vous gérez l'autorisation et obtenez un jeton d'actualisation dépend de l'environnement d'exécution de votre module complémentaire :

  • Modules complémentaires HTTP (environnements d'exécution alternatifs) : pour les modules complémentaires HTTP, votre service de backend doit implémenter un flux d'autorisation OAuth 2.0 distinct de l'autorisation de module complémentaire intégrée pour demander un accès hors connexion (access_type=offline) et recevoir un jeton d'actualisation.

    Vous pouvez inviter les utilisateurs à autoriser cette connexion en affichant une carte de connexion ou d'autorisation lorsqu'ils configurent le starter dans Workspace Studio. Pour en savoir plus sur le renvoi des cartes d'autorisation et la gestion du flux OAuth, consultez Associer votre module complémentaire Google Workspace à un service tiers (en traitant Google Workspace comme le service tiers auquel vous vous connectez).

    Votre service de backend doit stocker le jeton d'actualisation de manière sécurisée (par exemple, dans la base de données de votre service à côté de triggerId) et l'utiliser pour récupérer un nouveau jeton d'accès chaque fois qu'un événement se produit avant d'envoyer des requêtes au point de terminaison de l'API notifyUri ou triggers.fire du starter.

  • Modules complémentaires Google Apps Script : les modules complémentaires basés sur Google Apps Script qui utilisent des déclencheurs planifiés (déclenchés par le temps) pour interroger les événements peuvent ignorer l'implémentation d'un flux OAuth indépendant. Étant donné que les déclencheurs planifiés s'exécutent directement dans l'environnement d'exécution Google Apps Script, Google Apps Script gère et actualise automatiquement les jetons OAuth à l'aide des portées déclarées dans le fichier manifeste.

Définir le starter dans le fichier manifeste

Pour définir un starter, ajoutez-le au fichier manifeste de votre module complémentaire (appsscript.json) dans le bloc addOns.studio.flows.workflowElements. Cette configuration est requise pour les environnements d'exécution Apps Script et HTTP (environnements d'exécution alternatifs). Configurez l'élément en tant que workflowTrigger au lieu de workflowAction (qui est utilisé pour définir une étape). Pour en savoir plus, consultez Structure du fichier manifeste des modules complémentaires Google Workspace.

Dans le bloc workflowTrigger, spécifiez :

  • inputs : variables que l'utilisateur configure sur la fiche de configuration (nom du projet, filtre de ressources, etc.).
  • outputs : variables pouvant être renvoyées par le déclencheur aux étapes en aval du flux.
  • onConfigFunction : nom de la fonction de rappel qui affiche l'interface de configuration utilisateur.
  • onManageFunction : nom de la fonction de rappel appelée par Google pour gérer la création et la suppression des abonnements Starter.

L'exemple de code suivant montre une définition de fichier manifeste pour un starter d'événement :

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"
            }
          }
        ]
      }
    }
  }
}

Gérer le cycle de vie de l'abonnement Starter

Lorsqu'un utilisateur configure et active un flux contenant votre starter, ou si le flux est désactivé ou supprimé, Google appelle votre module complémentaire à l'aide de la fonction de rappel onManageFunction déclarée dans le fichier manifeste.

Objet d'événement de cycle de vie

La fonction de rappel reçoit un WorkflowEventObject contenant le contexte de l'action. Pour commencer, cela inclut :

  • Création du déclencheur (event.workflow.triggerCreation) : se déclenche lorsque le flux est publié ou activé.

    • triggerId : chaîne UUID unique identifiant cette instance d'enregistrement de démarrage.

    • notifyUri : URL unique du point de terminaison de l'API REST associée à cette inscription de démarrage (par exemple, https://workspacestudio.googleapis.com/v1/triggers/YOUR_TRIGGER_ID:fire).

    • inputs : entrées de variables configurées par l'utilisateur à partir de la fiche.

  • Suppression du déclencheur (event.workflow.triggerDeletion) : se déclenche lorsque le déclencheur de démarrage est supprimé du flux ou lorsque l'intégralité du flux est désactivée ou supprimée.

    • triggerId : chaîne UUID unique de l'instance d'abonnement à nettoyer.

Cycle de vie de l'abonnement Alternate Runtimes (API HTTP)

Pour les modules complémentaires créés à l'aide d'autres runtimes, les notifications sur le cycle de vie des abonnements sont envoyées à l'aide de requêtes HTTP POST à l'URL du point de terminaison HTTP configuré du module complémentaire, avec le nom de l'action spécifié par la fonction de rappel onManageFunction. La charge utile correspond à la représentation JSON de WorkflowEventObject.

Pour en savoir plus sur les autres runtimes, consultez Créer un module complémentaire Google Workspace à l'aide de points de terminaison HTTP.

Implémenter des rappels de cycle de vie dans Apps Script

L'exemple Apps Script suivant montre comment configurer la fiche d'interface utilisateur, gérer les événements de cycle de vie des abonnements à l'aide de onManageTrigger et renvoyer la requête de démarrage à Google lorsqu'un événement se produit.

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

Utiliser l'API Workspace Studio

Vous pouvez utiliser l'API Workspace Studio (workspacestudio.googleapis.com) pour informer Google de manière programmatique des événements de démarrage.

Les points de terminaison se trouvent sous le chemin de base : https://workspacestudio.googleapis.com/v1.

Notifie un événement de démarrage

Déclenche un starter à l'aide de la méthode triggers.fire pour lancer l'exécution d'un flux.

  • Méthode HTTP : POST
  • Chemin d'accès : /v1/triggers/{triggerId}:fire (où {triggerId} est l'identifiant unique récupéré lors de la création de l'abonnement au déclencheur)
  • Champ d'application OAuth : https://www.googleapis.com/auth/workspace.studio.trigger

L'exemple de code suivant montre comment déclencher un starter dans la requête.

Demande

{
  "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 (chaîne, obligatoire) : nom de ressource du starter, au format triggers/{triggerId}.
  • outputs (carte, facultatif) : carte des variables de sortie du déclencheur représentant les données d'événement. Chaque valeur est un objet VariableData compatible avec les listes typées (par exemple, stringValues, booleanValues, integerValues).
  • log (objet, facultatif) : représentation du balisage TextFormat affichée dans les journaux d'activité d'exécution Workspace Studio.
  • requestId (chaîne, facultatif) : identifiant unique (UUID v4 recommandé) comportant jusqu'à 36 caractères ASCII pour assurer l'idempotence de l'API en cas de nouvelles tentatives.

Réponse

En cas de réussite, la réponse renvoie un objet JSON vide {}.

Quotas de l'API Workspace Studio

Le trafic envoyé au service workspacestudio.googleapis.com est limité pour éviter la surcharge du système, encourager une utilisation équitable des ressources et protéger les performances globales de Google Workspace.

Les quotas suivants sont appliqués :

Type de quota Quota
Par minute et par projet 1 000 requêtes de démarrage
Par minute et par utilisateur 100 requêtes de démarrage

Voici les types de quotas :

  • Par minute et par projet : limite le nombre cumulé d'événements de démarrage déclenchés à partir du projet Google Cloud d'un même développeur à 1 000 requêtes par minute pour l'ensemble des utilisateurs exécutant ses starters.
  • Par minute et par utilisateur : limite à 100 requêtes par minute le nombre cumulé d'invocations de démarrage d'un même utilisateur final dans un projet Cloud donné.

Gérer les erreurs de quota basées sur le temps

Si vous dépassez ces quotas, l'API renvoie un code d'erreur HTTP 429 Too Many Requests (ou 429 Resource Exhausted) indiquant que le quota de débit a été dépassé.

Pour résoudre ces erreurs, votre code doit intercepter l'exception et utiliser une stratégie d'intervalle exponentiel entre les tentatives tronqué. L'intervalle exponentiel entre les tentatives permet de relancer les requêtes ayant échoué en utilisant des délais progressivement plus longs entre les tentatives, y compris un jitter aléatoire (recalcul d'un délai aléatoire à chaque itération) pour empêcher plusieurs clients de se synchroniser et de réessayer en même temps :

  1. Envoyez une requête à l'API Workspace Studio.
  2. Si la requête échoue avec une erreur 429, attendez 1 second + random_number_milliseconds et réessayez.
  3. Si l'opération échoue à nouveau, attendez 2 seconds + random_number_milliseconds et réessayez.
  4. Si l'opération échoue à nouveau, attendez 4 seconds + random_number_milliseconds et réessayez.
  5. Continuez cette boucle en doublant le délai jusqu'à un seuil de maximum_backoff (généralement 32 ou 64 secondes).
  6. Une fois que vous avez atteint la durée maximale de backoff, réessayez en utilisant ce délai constant jusqu'à ce que la limite maximale de nouvelles tentatives soit atteinte, puis arrêtez-vous et enregistrez l'erreur.

Bonnes pratiques

Lorsque vous concevez et implémentez un starter, tenez compte des bonnes pratiques suivantes :

Émettre des événements individuels au lieu de listes groupées

Concevez votre déclencheur pour qu'il émette un événement individuel pour chaque occurrence distincte (par exemple, un enregistrement mis à jour, un nouveau message publié ou une tâche attribuée) plutôt qu'un seul événement contenant un lot ou une liste d'éléments :

  • Cohérence avec les déclencheurs intégrés : dans Workspace Studio, les déclencheurs Google Workspace intégrés (comme la réception d'un e-mail dans Gmail ou l'arrivée d'un utilisateur dans un espace Google Chat) se déclenchent sur un seul événement. L'émission d'événements à un seul élément s'aligne sur ce comportement et offre une expérience cohérente et prévisible aux utilisateurs dans tous les starters.
  • Configuration de flux simplifiée : les étapes en aval d'un flux traitent généralement un élément à la fois. L'émission d'événements à un seul élément permet aux utilisateurs de mapper directement les variables sans ajouter d'étapes complexes pour itérer sur les tableaux ou analyser les listes.
  • Gérez individuellement l'interrogation et les modifications par lot : si votre service de backend interroge une API externe et détecte plusieurs éléments modifiés au cours d'un même intervalle d'interrogation, déclenchez un événement de démarrage individuel pour chaque élément au lieu de les regrouper dans un événement par lot.
  • Gérez le nombre d'événements et les quotas : comme le déclenchement d'événements individuels pour plusieurs éléments modifiés peut entraîner un pic soudain de requêtes, assurez-vous que votre service respecte les quotas de l'API Workspace Studio (par exemple, la limite de 100 requêtes par minute et par utilisateur). Si un cycle d'interrogation génère un grand nombre d'éléments (par exemple, plus de 100 enregistrements modifiés), cadrez ou limitez les envois d'événements au fil du temps pour éviter les erreurs 429 Too Many Requests.

Comportements principaux et cas limites

Lors de l'intégration de starters, les développeurs doivent gérer des comportements d'erreur et des fonctionnalités d'exécution spécifiques :

  • Aucune prise en charge des tests : Workspace Studio ne prend pas en charge les tests pour les débutants.
  • Idempotence et prévention de la relecture : bien que cela ne soit pas strictement nécessaire, vous devez inclure un requestId unique (tel qu'un UUID) dans votre charge utile HTTP ou Apps Script. Fournir un requestId assure l'idempotence en permettant à l'API de détecter et d'ignorer les notifications en double, ce qui empêche le flux de s'exécuter plusieurs fois pour un seul événement.
  • Flux désactivés et réactivés : lorsqu'un flux contenant votre starter est désactivé dans Workspace Studio, Google envoie un événement de cycle de vie triggerDeletion à votre rappel onManageFunction. De plus, tous les appels à la méthode FireTrigger associée renvoient un code d'erreur 404 Not Found (Requested entity was not found.). Votre service doit réagir aux erreurs 404 en arrêtant les futures notifications d'événements pour cet ID d'instance de déclencheur.

    Si un utilisateur réactive ultérieurement le flux, Google lance un nouveau cycle de vie d'abonnement en appelant votre rappel onManageFunction avec un nouvel événement triggerCreation contenant un nouveau triggerId et notifyUri. L'ancien triggerId est définitivement désactivé et ne sera pas réactivé. Votre service ne doit donc pas interroger ni vérifier si une ancienne instance de déclencheur a été réactivée. Pour en savoir plus, consultez Gérer le cycle de vie de l'abonnement Starter.

  • Suppression idempotente de l'abonnement : votre fonction de rappel onManageFunction doit gérer les demandes de suppression de l'abonnement Starter de Google de manière idempotente. Si Google appelle le hook de suppression plusieurs fois pour le même triggerId (par exemple, lors de nouvelles tentatives en raison de pertes de connexion temporaires), la fonction doit renvoyer un résultat positif.

  • Quotas de flux : en plus des quotas de l'API Workspace Studio, les flux utilisateur sont soumis à des contrôles de quota internes supplémentaires. Les boucles à haute fréquence ou le volume d'événements excessif peuvent dépasser les seuils de sécurité, ce qui entraîne la désactivation automatique du flux.