במאמר הזה מוסבר איך ליצור תהליך עבודה בסיסי שיאפשר לאפליקציה או לשירות שלכם להודיע ל-Google Workspace Studio כשמתרחש אירוע ולהתחיל הפעלה של תהליך עבודה. ב-API, מציתים נקראים workflowTriggers.
טריגר לפעולה מתחיל תהליך, ושלב הוא משימה אחת ברצף המשימות שמרכיבות את התהליך. כשיוצרים טריגר לפעולה, המשתמשים יכולים להגדיר פעולות אוטומטיות שמגיבות לאירועים בזמן אמת מהאפליקציה או מהשירות שלכם.
כדי ליצור תוסף למתחילים, צריך להצהיר על התוסף בקובץ המניפסט של התוסף וליישם קריאות חוזרות (callback) של מחזור החיים ב-Google Apps Script, או להפעיל את התוסף על ידי פרסום מטענים ייעודיים (payload) לנקודת הקצה של Google Workspace Studio API.
דרישות מוקדמות והרשאת OAuth
כדי לתקשר עם נקודת הקצה של Workspace Studio API, האפליקציה או השירות שלכם צריכים לעבור אימות באמצעות OAuth 2.0. במהלך ההרשאה, האפליקציה צריכה לבקש מהמשתמשים את היקף ה-OAuth הייעודי הבא:
https://www.googleapis.com/auth/workspace.studio.trigger
היקף ההרשאות הזה מאשר לאפליקציה לקרוא ל-Workspace Studio API ולהפעיל רצפי פעולות שהמשתמש הגדיר עבור התבנית הזו.
גישה אופליין וטוקנים לרענון
מכיוון שרכיבי Starter שולחים ל-Workspace Studio הודעה באופן אסינכרוני כשמתרחש אירוע בשירות החיצוני – מה שיכול לקרות שעות, ימים או חודשים אחרי שמשתמש מגדיר זרימת עבודה – השירות שלכם צריך לספק אסימון גישה תקף מסוג OAuth 2.0 כשמתבצעת קריאה לנקודת הקצה של ה-API.
אסימון הגישה ש-Google מספקת באובייקט האירוע של התוסף (למשל במהלך הגדרת התוסף או בקשות של קריאות חוזרות (callback) של מחזור החיים) הוא לזמן קצר ותקף לשעה אחת בלבד. היא לא מספיקה להפעלת אירועים ראשוניים באופן אסינכרוני בעתיד. כדי לקרוא ל-Workspace Studio API לאורך זמן, השירות שלכם צריך טוקן רענון במצב אופליין כדי ליצור טוקנים חדשים של גישה לפי דרישה.
האופן שבו מטפלים בהרשאה ומקבלים אסימון רענון תלוי בזמן הריצה של התוסף:
תוספים ל-HTTP (סביבות ריצה חלופיות): בתוספים ל-HTTP, שירות ה-Backend צריך להטמיע תהליך הרשאה נפרד מסוג OAuth 2.0, שלא תלוי בהרשאה המובנית של התוסף, כדי לבקש גישה אופליין (
access_type=offline) ולקבל טוקן רענון.אתם יכולים להציג למשתמשים כרטיס התחברות או כרטיס הרשאה כשהם מגדירים את טריגר הפעולה ב-Workspace Studio, כדי לבקש מהם לאשר את החיבור הזה. למידע נוסף על החזרת כרטיסי הרשאה וטיפול בתהליך OAuth, אפשר לעיין במאמר קישור תוסף של Google Workspace לשירות צד שלישי (כאשר Google Workspace הוא שירות הצד השלישי שאליו מתחברים).
שירות לקצה העורפי צריך לאחסן את טוקן הרענון בצורה מאובטחת (לדוגמה, במסד הנתונים של השירות לצד
triggerId) ולהשתמש בו כדי לאחזר טוקן גישה חדש בכל פעם שמתרחש אירוע, לפני שליחת בקשות לנקודת הקצה שלnotifyUriאו לנקודת קצה ל-API שלtriggers.fire.תוספים של Google Apps Script: תוספים מבוססי Google Apps Script שמשתמשים בגורמים מפעילים מתוזמנים (מבוססי זמן) כדי לבדוק אם יש אירועים, יכולים לדלג על הטמעה של תהליך OAuth עצמאי. מכיוון שהפעלות מתוזמנות של טריגרים מתבצעות ישירות בסביבת זמן הריצה של Google Apps Script, המערכת מנהלת ומעדכנת אוטומטית את טוקני ה-OAuth באמצעות ההיקפים שמוצהרים במניפסט.
הגדרת הטריגר לפעולה בקובץ המניפסט
כדי להגדיר טריגר לפעולה, מוסיפים אותו לקובץ המניפסט של התוסף (appsscript.json) בתוך הבלוק addOns.studio.flows.workflowElements. ההגדרה הזו נדרשת גם ל-Apps Script וגם לסביבות זמן ריצה של HTTP (סביבות זמן ריצה חלופיות). מגדירים את הרכיב כ-workflowTrigger במקום כ-workflowAction (שמשמש להגדרת שלב). מידע נוסף זמין במאמר בנושא מבנה קובץ המניפסט של תוספים ל-Google Workspace.
בתוך הבלוק workflowTrigger, מציינים:
-
inputs: משתנים שהמשתמש מגדיר בכרטיס ההגדרה (כמו שם הפרויקט, מסנן המשאבים וכו'). -
outputs: משתנים שניתן להחזיר על ידי ה-starter לשלבים הבאים בתהליך. -
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 הייחודית של נקודת קצה ל-API בארכיטקטורת REST שמשויכת לרישום הזה של Starter (לדוגמה,https://workspacestudio.googleapis.com/v1/triggers/YOUR_TRIGGER_ID:fire).
inputs: קלט המשתנה שהוגדר על ידי המשתמש מהכרטיס.
מחיקת טריגר (
event.workflow.triggerDeletion): מופעל כשמסירים את הטריגר לפעולה מהתהליך, או כשמשביתים או מוחקים את התהליך כולו.-
triggerId: מחרוזת ה-UUID הייחודית של מופע המינוי שרוצים לנקות.
-
מחזור החיים של מינוי ל-Alternate Runtimes (HTTP API)
תוספים שנבנו באמצעות סביבות ריצה חלופיות, מקבלים התראות על מחזור החיים של המינוי באמצעות בקשות HTTP POST לכתובת ה-URL של נקודת הקצה של ה-HTTP שהוגדרה בתוסף, עם שם הפעולה שצוין על ידי פונקציית קריאה חוזרת onManageFunction. המטען הייעודי (payload) תואם לייצוג ב-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());
}
}
שימוש ב-Workspace Studio API
אפשר להשתמש ב-Workspace Studio API (workspacestudio.googleapis.com) כדי להודיע ל-Google באופן פרוגרמטי על אירועים שקשורים לטריגרים לפעולה.
נקודות הקצה נמצאות בנתיב הבסיס:
https://workspacestudio.googleapis.com/v1.
התראה על אירוע התחלתי
מפעיל starter באמצעות ה-method triggers.fire כדי להתחיל את ההפעלה של flow.
- שיטת HTTP:
POST - נתיב:
/v1/triggers/{triggerId}:fire(כאשר{triggerId}הוא המזהה הייחודי שאוחזר במהלך יצירת המינוי לטריגר) - היקף הרשאות OAuth:
https://www.googleapis.com/auth/workspace.studio.trigger
בדוגמת הקוד הבאה אפשר לראות איך להפעיל starter בבקשה.
בקשה
{
"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(מחרוזת, חובה): שם המשאב של ה-starter, בפורמטtriggers/{triggerId}. -
outputs(map, optional): A map of starter output variables representing the event data. כל ערך הוא אובייקטVariableDataשתומך ברשימות מוקלדות (לדוגמה,stringValues, booleanValues, integerValues). -
log(object, optional): ייצוג של תגי עיצובTextFormatשמוצג ביומני הפעילות של ההרצה ב-Workspace Studio. -
requestId(מחרוזת, אופציונלי): מזהה ייחודי (מומלץ UUID v4) באורך של עד 36 תווים ב-ASCII, כדי להבטיח אידמפוטנטיות של ה-API בניסיונות חוזרים.
תשובה
אם הפעולה בוצעה ללא שגיאות, מוחזר אובייקט JSON ריק {}.
מכסות של Workspace Studio API
התעבורה שנשלחת לשירות workspacestudio.googleapis.com מוגבלת כדי למנוע עומס יתר על המערכת, לעודד שימוש הוגן במשאבים ולהגן על הביצועים הכוללים של Google Workspace.
אלה המכסות שנאכפות:
| סוג המכסה | מכסה |
|---|---|
| Per minute per project | 1,000 בקשות ראשוניות |
| לדקה לכל משתמש | 100 בקשות ראשוניות |
סוגי המכסות הם:
- לדקה לכל פרויקט: מגביל את המספר המצטבר של אירועי התחלה שנשלחים מפרויקט יחיד של מפתח ב-Google Cloud ל-1,000 בקשות לדקה לכל המשתמשים שמריצים את קבצי ההתחלה שלו.
- לדקה לכל משתמש: מגביל את מספר ההפעלות המצטברות של התכונה למתחילים על ידי משתמש קצה יחיד בפרויקט Cloud נתון ל-100 בקשות לדקה.
טיפול בשגיאות שקשורות למכסה מבוססת-זמן
אם תחרגו מהמכסות האלה, ה-API יחזיר קוד שגיאה HTTP 429 Too Many Requests (או 429 Resource Exhausted) שמציין שחרגתם ממכסה לקצב הגשת בקשות.
כדי לפתור את השגיאות האלה, הקוד צריך לזהות את החריגה ולהשתמש באסטרטגיית השהיה מעריכית קטועה לפני ניסיון חוזר (truncated exponential backoff). השהיה מעריכית לפני ניסיון חוזר (exponential backoff) מאפשרת לנסות שוב בקשות שנכשלו עם השהיות ארוכות יותר ויותר בין הניסיונות, כולל תנודות אקראיות (חישוב מחדש של השהיה אקראית בכל איטרציה) כדי למנוע ממספר לקוחות להסתנכרן ולנסות שוב בו-זמנית:
- שליחת בקשה ל-API של Workspace Studio.
- אם הבקשה נכשלת עם השגיאה
429, צריך להמתין1 second + random_number_millisecondsולנסות שוב. - אם הפעולה נכשלת שוב, צריך להמתין
2 seconds + random_number_millisecondsולנסות שוב. - אם הפעולה נכשלת שוב, צריך להמתין
4 seconds + random_number_millisecondsולנסות שוב. - ממשיכים בלולאה הזו, ומכפילים את העיכוב עד שמגיעים לסף של
maximum_backoff(בדרך כלל 32 או 64 שניות). - אחרי שמגיעים למשך ההשהיה המקסימלי לפני ניסיון חוזר, המערכת מנסה שוב עם אותו עיכוב קבוע עד שמגיעים למגבלת הניסיונות החוזרים, ואז עוצרת ומתעדת את השגיאה.
שיטות מומלצות
כשמתכננים ומטמיעים תבנית התחלה, כדאי לפעול לפי השיטות המומלצות הבאות:
העברת אירועים בודדים במקום רשימות של אירועים
תכננו את ה-Starter כך שיפלוט אירוע נפרד לכל מקרה נפרד (כמו רשומה יחידה שעודכנה, הודעה חדשה שפורסמה או משימה שהוקצתה) במקום לפלוט אירוע יחיד שמכיל קבוצה או רשימה של פריטים:
- עקביות עם תבניות מובנות: ב-Workspace Studio, תבניות מובנות של Google Workspace (כמו קבלת אימייל ב-Gmail או הצטרפות של משתמש למרחב ב-Google Chat) מופעלות באירוע יחיד. הפצת אירועים של פריט יחיד תואמת להתנהגות הזו ומספקת למשתמשים חוויה עקבית וצפויה בכל התבניות.
- הגדרה פשוטה יותר של תהליכים: בדרך כלל, שלבים במורד הזרם בתהליך מעבדים פריט אחד בכל פעם. שליחת אירועים של פריט בודד מאפשרת למשתמשים למפות משתנים ישירות בלי להוסיף שלבים מורכבים כדי לבצע איטרציה על מערכים או לנתח רשימות.
- טיפול בסקרים ובשינויים באצווה בנפרד: אם שירות הקצה העורפי שלכם מבצע סקר של API חיצוני ומזהה כמה פריטים שהשתנו במהלך מרווח סקר אחד, מפעילים אירוע התחלה נפרד לכל פריט במקום לאגד אותם לאירוע אצווה אחד.
- ניהול קצב האירועים והמכסות: הפעלת אירועים נפרדים עבור כמה פריטים שהשתנו עלולה לגרום לפרץ פתאומי של בקשות. לכן, חשוב לוודא שהשירות שלכם לא חורג מהמכסות של Workspace Studio API (למשל, המגבלה של 100 בקשות לדקה לכל משתמש). אם מחזור בדיקה
מניב נפח גדול של פריטים (לדוגמה, יותר מ-100 רשומות שהשתנו),
כדאי להגביל את קצב השליחה של האירועים לאורך זמן כדי להימנע משגיאות
429 Too Many Requests.
התנהגויות ליבה ומקרי קצה
כשמשלבים קוד התחלתי, המפתחים צריכים לטפל בהתנהגויות ספציפיות של שגיאות ובתכונות של זמן ריצה:
- אין תמיכה בהרצת בדיקה: Workspace Studio לא תומך בהרצת בדיקה למתחילים.
- אידמפוטנטיות ומניעת הפעלה חוזרת: למרות שזה לא חובה, כדאי לכלול
requestIdייחודי (למשל UUID) במטען הייעודי (payload) של HTTP או Apps Script. הוספתrequestIdמבטיחה אידמפוטנטיות, כי היא מאפשרת ל-API לזהות ולהתעלם מהתראות כפולות, וכך מונעת את הפעלת התהליך כמה פעמים לאותו אירוע. רצפי פעולות שהושבתו והופעלו מחדש: כשמשביתים ב-Workspace Studio רצף פעולות שמכיל את ה-Starter שלכם, Google שולחת
triggerDeletionאירוע במחזור חייםonManageFunctionאל הקריאה החוזרת שלכם. בנוסף, כל הקריאות לשיטה המשויכתFireTriggerמחזירות קוד שגיאה404 Not Found(Requested entity was not found.). השירות צריך להגיב לשגיאות404על ידי הפסקת העברת הודעות על אירועים עתידיים עבור מזהה מופע ההפעלה הזה.אם משתמש מפעיל מחדש את התהליך מאוחר יותר, Google מתחילה מחזור חיים חדש של מינוי על ידי הפעלת הקריאה החוזרת
onManageFunctionעם אירועtriggerCreationחדש שמכילtriggerIdו-notifyUriחדשים. הגרסה הקודמת שלtriggerIdהוצאה משימוש לצמיתות ולא תופעל מחדש, ולכן השירות שלכם לא צריך לבצע בדיקות או סקרים כדי לראות אם מופעל מחדש מופע ישן של טריגר. מידע נוסף זמין במאמר בנושא ניהול מחזור החיים של מינוי Starter.מחיקת מינוי אידמפוטנטית: פונקציית הקריאה החוזרת
onManageFunctionשלך צריכה לטפל בבקשות למחיקת מינוי Starter מ-Google באופן אידמפוטנטי. אם Google קוראת לפונקציית ה-hook למחיקה מספר פעמים עבור אותוtriggerId(לדוגמה, במהלך ניסיונות חוזרים בגלל אובדן חיבור זמני), הפונקציה צריכה להחזיר הצלחה.מכסות של תהליכי עבודה: מעבר למכסות של Workspace Studio API, תהליכי עבודה של משתמשים כפופים לאמצעי בקרה נוספים של מכסות פנימיות. לולאות בתדירות גבוהה או נפח אירועים גבוה מדי עלולים לחרוג מספי הבטיחות, ולגרום להשבתה אוטומטית של התהליך.
נושאים קשורים
- איך יוצרים שלב
- קישור תוסף ל-Google Workspace לשירות של צד שלישי
- משתני קלט
- משתני פלט
- רישום פעילות ושגיאות ביומן
- טיפול בשגיאות
- אובייקטים של אירועים ב-Workspace Studio