העברה מ-AWS Step Functions ל-Workflows

כדי לעזור לכם להתכונן למעבר מ-Amazon Web Services (AWS) Step Functions ל-Workflows ב- Google Cloud, בדף הזה מוסברים קווי הדמיון וההבדלים העיקריים בין שני המוצרים. המידע הזה מיועד לעזור למי שכבר מכיר את Step Functions להטמיע ארכיטקטורה דומה באמצעות Workflows.

בדומה ל-Step Functions,‏ Workflows היא פלטפורמת תזמור מנוהלת לחלוטין שמבוססת על מצב ומבצעת שירותים בסדר שאתם מגדירים: תהליך עבודה. בתהליכי העבודה האלה אפשר לשלב שירותים, כולל שירותים בהתאמה אישית שמארחים ב-Cloud Run או בפונקציות Cloud Run, Google Cloud שירותים כמו Cloud Vision AI ו-BigQuery, וכל API מבוסס-HTTP.

הערה: Express Workflows ב-Step Functions הוא סוג של תהליך עבודה ב-AWS Step Functions שלא נכלל כאן, כי משך הזמן של Express Workflow מוגבל, וביצוע של תהליך עבודה בדיוק פעם אחת לא אפשרי.

שלום עולם

ב-Step Functions, מכונת מצבים היא תהליך עבודה, ומשימה היא מצב בתהליך עבודה שמייצג יחידת עבודה יחידה ששירות אחר של AWS מבצע. ב-Step Functions, כל מצב צריך להגדיר את המצב הבא.

ב-Workflows, סדרת שלבים שמשתמשת בתחביר של Workflows מתארת את המשימות לביצוע. ב-Workflows, השלבים נחשבים לרשימה מסודרת והם מבוצעים אחד אחרי השני עד שכל השלבים מסתיימים.

בדוגמה הבאה של 'Hello world' מוצג השימוש במצבים ב-Step Functions ובשלבים ב-Workflows:

Step Functions

  {
    "Comment": "Hello world example of Pass states in Amazon States Language",
    "StartAt": "Hello",
    "States": {
      "Hello": {
        "Type": "Pass",
        "Result": "Hello",
        "Next": "World"
      },
      "World": {
        "Type": "Pass",
        "Result": "World",
        "End": true
      }
    }
  }

Workflows YAML

  ---
  # Hello world example of steps using Google Cloud Workflows syntax
  main:
      steps:
      - Hello:
          next: World
      - World:
          next: end
  ...

קובץ JSON של תהליכי עבודה

  {
    "main": {
      "steps": [
        {
          "Hello": {
            "next": "World"
          }
        },
        {
          "World": {
            "next": "end"
          }
        }
      ]
    }
  }

סקירה כללית של השוואה

בקטע הזה מוצגת השוואה מפורטת יותר בין שני המוצרים.

Step FunctionsWorkflows
תחביר‫JSON (YAML בכלי) YAML או JSON
זרימת בקרהמעבר בין מצבים בקרה על זרימת נתונים עם שלבים
Workerמשאבים (ARN) ומשימת HTTP בקשות HTTP ומחברים
אמינותתפיסה/ניסיון חוזר תפיסה/ניסיון חוזר
מקביליותנתמך נתמך
נתונים ברמת המדינההמצב מועבר משתנים של Workflows
אימותIAM IAM
חוויית משתמשWorkflow Studio, ‏ CLI, ‏ SDK, ‏ IaC Google Cloud מסוף, CLI, ‏ SDK, ‏ IaC
Pricing תמחור של Step Functions מחירון של Workflows
תחביר

‫Step Functions משתמש בעיקר ב-JSON כדי להגדיר פונקציות, ולא תומך ישירות ב-YAML. עם זאת, ב-AWS Toolkit ל-Visual Studio Code וב-AWS CloudFormation, אפשר להשתמש ב-YAML להגדרה של Step Functions.

אפשר לתאר את השלבים ב-Workflows באמצעות התחביר של Workflows, והם יכולים להיכתב ב-YAML או ב-JSON. רוב תהליכי העבודה הם ב-YAML. הדוגמאות בדף הזה ממחישות את היתרונות של YAML, כולל קלות הקריאה והכתיבה, ותמיכה מובנית בתגובות. הסבר מפורט על התחביר של Workflows מופיע במאמר הפניה לתחביר.

בקרת זרימה

גם ב-Workflows וגם ב-Step Functions, תהליכי עבודה מוגדרים כסדרה של משימות: שלבים ב-Workflows ומצבים ב-Step Functions. שניהם מאפשרים למשימה לציין איזו משימה להפעיל בהמשך, ותומכים בתנאים דמויי switch כדי לבחור את יחידת העבודה הבאה על סמך המצב הנוכחי. ההבדל העיקרי הוא שב-Step Functions צריך להגדיר את המצב הבא לכל מצב, ואילו ב-Workflows השלבים מבוצעים בסדר שבו הם מוגדרים (כולל השלבים הבאים החלופיים). מידע נוסף זמין במאמרים בנושא תנאים ושלבים.

קובץ שירות

שני המוצרים מתזמנים משאבי מחשוב כמו פונקציות, קונטיינרים ושירותי אינטרנט אחרים כדי לבצע משימות. ב-Step Functions, העובד מזוהה על ידי השדה Resource, שהוא URI מבחינה תחבירית. כתובות ה-URI שמשמשות לזיהוי משאבי העובדים הן בפורמט של שם משאב Amazon‏ (ARN). כדי להפעיל ישירות נקודת קצה (endpoint) שרירותית של HTTP, אפשר להגדיר משימת HTTP.

תהליכי עבודה יכולים לשלוח בקשות HTTP לנקודת קצה שרירותית של HTTP ולקבל תגובה. מחברים מאפשרים להתחבר בקלות ל-API אחרים של Google Cloud בתהליך עבודה, ולשלב את תהליכי העבודה עם מוצרים אחרים של Google Cloud כמו Pub/Sub,‏ BigQuery או Cloud Build. מחברים מפשטים את הקריאה לשירותים כי הם מטפלים בפורמט של הבקשות בשבילכם, ומספקים שיטות וארגומנטים כך שלא תצטרכו לדעת את הפרטים שלGoogle Cloud API. אפשר גם להגדיר את מדיניות הזמן הקצוב לתפוגה והסקר.

אמינות

אם משימה נכשלת, תהליך העבודה צריך להיות מסוגל לנסות שוב בצורה מתאימה, לזהות חריגים כשצריך ולנתב מחדש את תהליך העבודה לפי הצורך. גם Step Functions וגם Workflows משיגים אמינות באמצעות מנגנונים דומים: טיפול בחריגים עם ניסיונות חוזרים, ושליחה בסופו של דבר למקום אחר בתהליך העבודה. מידע נוסף זמין במאמר בנושא שגיאות בתהליך העבודה.

מקביליות

יכול להיות שתרצו שתהליך העבודה יתזמן כמה משימות במקביל. ב-Step Functions יש שתי דרכים לעשות את זה: אפשר לקחת פריט נתונים אחד ולהעביר אותו במקביל לכמה משימות שונות, או להשתמש במערך ולהעביר את הרכיבים שלו לאותה משימה.

ב-Workflows, אפשר להגדיר חלק בתהליך העבודה שבו שני שלבים או יותר יכולים להתבצע בו-זמנית. אפשר להגדיר ענפים שפועלים במקביל, או לולאה שבה האיטרציות פועלות במקביל. פרטים נוספים זמינים במאמר בנושא ביצוע שלבים בתהליך עבודה במקביל.

נתונים לפי מדינה

אחד היתרונות של מנוע זרימת עבודה הוא שנתוני המצב נשמרים בשבילכם ללא מאגר נתונים חיצוני. ב-Step Functions, נתוני המצב מועברים במבנה JSON ממצב אחד למצב אחר.

ב-Workflows, אפשר לשמור את נתוני המצב במשתנים גלובליים. מכיוון שמותר לכם להגדיר משך ביצוע של עד שנה אחת, אתם יכולים לשמור את נתוני המצב כל עוד המופע עדיין פועל.

אימות

שני המוצרים מסתמכים על מערכת בסיסית לניהול זהויות והרשאות גישה (IAM) לצורך אימות ובקרת גישה. לדוגמה, אפשר להשתמש בתפקיד IAM כדי להפעיל את Step Functions.

ב-Workflows, אפשר להשתמש בחשבון שירות כדי להפעיל תהליך עבודה, להשתמש ב-OAuth 2.0 או ב-OIDC כדי להתחבר לממשקי API של Google Cloud, ולהשתמש בכותרת הבקשה של הרשאה כדי לבצע אימות באמצעות API של צד שלישי. מידע נוסף זמין במאמרים איך מעניקים הרשאה לזרימת עבודה לגשת למשאבים Google Cloud ואיך שולחים בקשות מאומתות מזרימת עבודה.

חוויית משתמש

אפשר להשתמש בכלי שורת פקודה או בתשתית כקוד (IaC) כמו Terraform כדי להגדיר ולנהל את Step Functions ואת Workflows.

בנוסף, Workflows תומך בהרצת תהליכי עבודה באמצעות ספריות הלקוח, במסוף Google Cloud , באמצעות Google Cloud CLI או על ידי שליחת בקשה ל-Workflows API בארכיטקטורת REST. פרטים נוספים זמינים במאמר הפעלת תהליך עבודה.

תמחור

לשני המוצרים יש תוכנית בחינם. פרטים נוספים זמינים בדפי התמחור המתאימים: תמחור של Step Functions ותמחור של Workflows.

מיפוי של סוגי מצבים לשלבים

יש שמונה סוגים של מצבים ב-Step Functions. מצבים הם רכיבים במכונת מצבים שיכולים לקבל החלטות על סמך הקלט שלהם, לבצע פעולות ולהעביר פלט למצבים אחרים. לפני שמעבירים מ-Step Functions ל-Workflows, חשוב להבין איך לתרגם כל סוג של מצב לשלב ב-Workflows.

Choice

מצב Choice מוסיף לוגיקה של הסתעפות למכונת מצבים.

ב-Workflows, אפשר להשתמש בבלוק switch כמנגנון בחירה שמאפשר לערך של ביטוי לשלוט בזרימת הביצוע של תהליך העבודה. אם יש התאמה לערך, מתבצעת ההצהרה של התנאי הזה. מידע נוסף מופיע במאמר בנושא תנאים.

Step Functions

  "ChoiceState": {
    "Type": "Choice",
    "Choices": [
      {
        "Variable": "$.foo",
        "NumericEquals": 1,
        "Next": "FirstMatchState"
      },
      {
        "Variable": "$.foo",
        "NumericEquals": 2,
        "Next": "SecondMatchState"
      }
    ],
    "Default": "DefaultState"
  }

Workflows YAML

  switch:
    - condition: ${result.body.SomeField < 10}
      next: small
    - condition: ${result.body.SomeField < 100}
      next: medium
    - condition: true
      next: default_step

קובץ JSON של תהליכי עבודה

  {
    "switch": [
      {
        "condition": "${result.body.SomeField < 10}",
        "next": "small"
      },
      {
        "condition": "${result.body.SomeField < 100}",
        "next": "medium"
      },
      {
        "condition": true,
        "next": "default_step"
      }
    ]
  }

Fail

מצב Fail מפסיק את הביצוע של מכונת המצבים ומסמן אותה ככישלון.

ב-Workflows, אפשר ליצור שגיאות מותאמות אישית באמצעות התחביר raise ואפשר לזהות ולטפל בשגיאות באמצעות בלוק try/except. מידע נוסף מופיע במאמר בנושא העלאת שגיאות.

Step Functions

  "FailState": {
      "Type": "Fail",
      "Error": "ErrorA",
      "Cause": "Kaiju attack"
  }

Workflows YAML

  raise:
      code: 55
      message: "Something went wrong."

קובץ JSON של תהליכי עבודה

  {
    "raise": {
      "code": 55,
      "message": "Something went wrong."
    }
  }

Map

אפשר להשתמש במצב Map כדי להפעיל קבוצה של שלבים לכל רכיב במערך קלט.

ב-Workflows, אפשר להשתמש בלולאות for בשביל איטרציות.

Step Functions

  { "StartAt": "ExampleMapState",
    "States": {
      "ExampleMapState": {
        "Type": "Map",
        "Iterator": {
           "StartAt": "CallLambda",
           "States": {
             "CallLambda": {
               "Type": "Task",
               "Resource": "arn:aws:lambda:us-east-1:123456789012:function:HelloFunction",
               "End": true
             }
           }
        }, "End": true
      }
    }
  }

Workflows YAML

  - assignStep:
      assign:
        - map:
            1: 10
            2: 20
            3: 30
        - sum: 0
  - loopStep:
      for:
          value: key
          in: ${keys(map)}
          steps:
            - sumStep:
                assign:
                  - sum: ${sum + map[key]}
  - returnStep:
      return: ${sum}

קובץ JSON של תהליכי עבודה

  [
    {
      "assignStep": {
        "assign": [
          {
            "map": {
              "1": 10,
              "2": 20,
              "3": 30
            }
          },
          {
            "sum": 0
          }
        ]
      }
    },
    {
      "loopStep": {
        "for": {
          "value": "key",
          "in": "${keys(map)}",
          "steps": [
            {
              "sumStep": {
                "assign": [
                  {
                    "sum": "${sum + map[key]}"
                  }
                ]
              }
            }
          ]
        }
      }
    },
    {
      "returnStep": {
        "return": "${sum}"
      }
    }
  ]

Parallel

אפשר להשתמש במצב Parallel כדי ליצור ענפים מקבילים של ביצוע במכונת המצבים. בדוגמה הבאה של Step Functions, מתבצעת בדיקה מקבילה של כתובת ומספר טלפון.

בתהליכי עבודה, אפשר להשתמש בשלב parallel כדי להגדיר חלק בתהליך העבודה שבו שני שלבים או יותר יכולים לפעול בו-זמנית. מידע נוסף זמין במאמר בנושא שלבים מקבילים.

Step Functions

  { "StartAt": "LookupCustomerInfo",
    "States": {
      "LookupCustomerInfo": {
        "Type": "Parallel",
        "End": true,
        "Branches": [
          {
           "StartAt": "LookupAddress",
           "States": {
             "LookupAddress": {
               "Type": "Task",
               "Resource": "arn:aws:lambda:us-east-1:123456789012:function:AddressFinder",
               "End": true
             }
           }
         },
         {
           "StartAt": "LookupPhone",
           "States": {
             "LookupPhone": {
               "Type": "Task",
               "Resource": "arn:aws:lambda:us-east-1:123456789012:function:PhoneFinder",
               "End": true
             }
           }
         }
        ]
      }
    }
  }

Workflows YAML

  main:
     params: [args]
     steps:
     - init:
         assign:
         - workflow_id: "lookupAddress"
         - customer_to_lookup:
             - address: ${args.customerId}
             - phone: ${args.customerId}
         - addressed: ["", ""] # to write to this variable, you must share it
     - parallel_address:
         parallel:
             shared: [addressed]
             for:
                 in: ${customer_to_lookup}
                 index: i # optional, use if index is required
                 value: arg
                 steps:
                 - address:
                     call: googleapis.workflowexecutions.v1.projects.locations.workflows.executions.run
                     args:
                         workflow_id: ${workflow_id}
                         argument: ${arg}
                     result: r
                 - set_result:
                     assign:
                     - addressed[i]: ${r}
     - return:
             return: ${addressed}

קובץ JSON של תהליכי עבודה

  {
    "main": {
      "params": [
        "args"
      ],
      "steps": [
        {
          "init": {
            "assign": [
              {
                "workflow_id": "lookupAddress"
              },
              {
                "customer_to_lookup": [
                  {
                    "address": "${args.customerId}"
                  },
                  {
                    "phone": "${args.customerId}"
                  }
                ]
              },
              {
                "addressed": [
                  "",
                  ""
                ]
              }
            ]
          }
        },
        {
          "parallel_address": {
            "parallel": {
              "shared": [
                "addressed"
              ],
              "for": {
                "in": "${customer_to_lookup}",
                "index": "i",
                "value": "arg",
                "steps": [
                  {
                    "address": {
                      "call": "googleapis.workflowexecutions.v1.projects.locations.workflows.executions.run",
                      "args": {
                        "workflow_id": "${workflow_id}",
                        "argument": "${arg}"
                      },
                      "result": "r"
                    }
                  },
                  {
                    "set_result": {
                      "assign": [
                        {
                          "addressed[i]": "${r}"
                        }
                      ]
                    }
                  }
                ]
              }
            }
          }
        },
        {
          "return": {
            "return": "${addressed}"
          }
        }
      ]
    }
  }

Pass

מצב Pass מעביר את הקלט שלו לפלט, בלי לבצע עבודה. בדרך כלל משתמשים בזה כדי לשנות את נתוני המצב ב-JSON.

מכיוון ש-Workflows לא מעביר נתונים בצורה הזו, אפשר להשאיר את המצב כפעולה שלא עושה כלום, או להשתמש בשלב הקצאה כדי לשנות את המשתנים. מידע נוסף זמין במאמר בנושא הקצאת משתנים.

Step Functions

  "No-op": {
    "Type": "Pass",
    "Result": {
      "x-datum": 0.38,
      "y-datum": 622.22
    },
    "ResultPath": "$.coords",
    "Next": "End"
  }

Workflows YAML

  assign:
      - number: 5
      - number_plus_one: ${number+1}
      - other_number: 10
      - string: "hello"

קובץ JSON של תהליכי עבודה

  {
    "assign": [
      {
        "number": 5
      },
      {
        "number_plus_one": "${number+1}"
      },
      {
        "other_number": 10
      },
      {
        "string": "hello"
      }
    ]
  }

הצלחה

מצב Succeed מפסיק את ההרצה בהצלחה.

ב-Workflows, אפשר להשתמש ב-return בתהליך העבודה הראשי כדי להפסיק את ההרצה של תהליך העבודה. אפשר גם לסיים תהליך עבודה על ידי השלמת השלב האחרון (בהנחה שהשלב לא קופץ לשלב אחר), או להשתמש ב-next: end כדי להפסיק את הביצוע של תהליך עבודה אם לא צריך להחזיר ערך. מידע נוסף זמין במאמר בנושא השלמת ההפעלה של תהליך עבודה.

Step Functions

  "SuccessState": {
    "Type": "Succeed"
  }

Workflows YAML

  return: "Success!"
  next: end

קובץ JSON של תהליכי עבודה

  {
    "return": "Success!",
    "next": "end"
  }

Task

מצב Task מייצג יחידת עבודה אחת שמבוצעת על ידי מכונת מצבים. בדוגמה הבאה של Step Functions, מופעלת פונקציית Lambda. (פעילויות הן תכונה של AWS Step Functions שמאפשרת לכם להגדיר משימה במכונת המצבים שבה העבודה מתבצעת במקום אחר).

בדוגמה של Workflows, מתבצעת קריאה לנקודת קצה של HTTP כדי להפעיל פונקציית Cloud Run. אפשר גם להשתמש במחבר כדי לגשת בקלות למוצרים אחרים של Google Cloud . בנוסף, אפשר להשהות תהליך עבודה ולבצע סקר כדי לקבל נתונים. אפשר גם להשתמש בנקודת קצה (endpoint) להתקשרות חזרה כדי לסמן לתהליך העבודה שאירוע מסוים התרחש, ולהמתין לאירוע הזה בלי לבצע סקר.

Step Functions

  "HelloWorld": {
    "Type": "Task",
    "Resource": "arn:aws:lambda:us-east-1:123456789012:function:HelloFunction",
    "End": true
  }

Workflows YAML

  - HelloWorld:
      call: http.get
      args:
          url: https://REGION-PROJECT_ID.cloudfunctions.net/helloworld
      result: helloworld_result

קובץ JSON של תהליכי עבודה

  [
    {
      "HelloWorld": {
        "call": "http.get",
        "args": {
          "url": "https://REGION-PROJECT_ID.cloudfunctions.net/helloworld"
        },
        "result": "helloworld_result"
      }
    }
  ]

Wait

מצב Wait מעכב את המשך הפעולה של מכונת המצבים למשך זמן מוגדר.

אפשר להשתמש בsys.sleep פונקציית הספרייה הרגילה של Workflows כדי להשהות את הביצוע למספר השניות שצוין, עד למקסימום של 31,536,000 (שנה אחת).

Step Functions

  "wait_ten_seconds" : {
    "Type" : "Wait",
    "Seconds" : 10,
    "Next": "NextState"
  }

Workflows YAML

  - someSleep:
      call: sys.sleep
      args:
          seconds: 10

קובץ JSON של תהליכי עבודה

  [
    {
      "someSleep": {
        "call": "sys.sleep",
        "args": {
          "seconds": 10
        }
      }
    }
  ]

דוגמה: תזמור מיקרו-שירותים

בדוגמה הבאה של Step Functions נבדק מחיר מניה, נקבע אם לקנות או למכור, והתוצאה מדווחת. מכונת המצבים בדוגמה משתלבת עם AWS Lambda על ידי העברת פרמטרים, משתמשת בתור של Amazon SQS כדי לבקש אישור אנושי ומשתמשת בנושא של Amazon SNS כדי להחזיר את תוצאות השאילתה.

{
      "StartAt": "Check Stock Price",
      "Comment": "An example of integrating Lambda functions in Step Functions state machine",
      "States": {
          "Check Stock Price": {
              "Type": "Task",
              "Resource": "CHECK_STOCK_PRICE_LAMBDA_ARN",
              "Next": "Generate Buy/Sell recommendation"
          },
          "Generate Buy/Sell recommendation": {
              "Type": "Task",
              "Resource": "GENERATE_BUY_SELL_RECOMMENDATION_LAMBDA_ARN",
              "ResultPath": "$.recommended_type",
              "Next": "Request Human Approval"
          },
          "Request Human Approval": {
              "Type": "Task",
              "Resource": "arn:PARTITION:states:::sqs:sendMessage.waitForTaskToken",
              "Parameters": {
                  "QueueUrl": "REQUEST_HUMAN_APPROVAL_SQS_URL",
                  "MessageBody": {
                      "Input.$": "$",
                      "TaskToken.$": "$$.Task.Token"
                  }
              },
              "ResultPath": null,
              "Next": "Buy or Sell?"
          },
          "Buy or Sell?": {
              "Type": "Choice",
              "Choices": [
                  {
                      "Variable": "$.recommended_type",
                      "StringEquals": "buy",
                      "Next": "Buy Stock"
                  },
                  {
                      "Variable": "$.recommended_type",
                      "StringEquals": "sell",
                      "Next": "Sell Stock"
                  }
              ]
          },
          "Buy Stock": {
              "Type": "Task",
              "Resource": "BUY_STOCK_LAMBDA_ARN",
              "Next": "Report Result"
          },
          "Sell Stock": {
              "Type": "Task",
              "Resource": "SELL_STOCK_LAMBDA_ARN",
              "Next": "Report Result"
          },
          "Report Result": {
              "Type": "Task",
              "Resource": "arn:PARTITION:states:::sns:publish",
              "Parameters": {
                  "TopicArn": "REPORT_RESULT_SNS_TOPIC_ARN",
                  "Message": {
                      "Input.$": "$"
                  }
              },
              "End": true
          }
      }
  }

מעבר ל-Workflows

כדי להעביר את הדוגמה הקודמת של Step Functions ל-Workflows, אפשר ליצור את השלבים המקבילים של Workflows על ידי שילוב של פונקציות Cloud Run, תמיכה בנקודת קצה של קריאה חוזרת שמחכה לבקשות HTTP שיגיעו לנקודת הקצה הזו, ושימוש במחבר Workflows לפרסום בנושא Pub/Sub במקום בנושא Amazon SNS:

  1. משלימים את השלבים ליצירת תהליך עבודה, אבל לא פורסים אותו עדיין.

  2. בהגדרת תהליך העבודה, מוסיפים שלב ליצירת נקודת קצה של callback שמחכה לקלט אנושי, ושלב שמשתמש במחבר Workflows כדי לפרסם בנושא Pub/Sub. לדוגמה:

    Workflows YAML

      ---
      main:
        steps:
          - init:
              assign:
                - projectId: '${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}'
                - region: LOCATION
                - topic: PUBSUB_TOPIC_NAME
          - Check Stock Price:
              call: http.get
              args:
                url: ${"https://" + region + "-" + projectId + ".cloudfunctions.net/CheckStockPrice"}
                auth:
                  type: OIDC
              result: stockPriceResponse
          - Generate Buy/Sell Recommendation:
              call: http.get
              args:
                url: ${"https://" + region + "-" + projectId + ".cloudfunctions.net/BuySellRecommend"}
                auth:
                  type: OIDC
                query:
                  price: ${stockPriceResponse.body.stock_price}
              result: recommendResponse
          - Create Approval Callback:
              call: events.create_callback_endpoint
              args:
                  http_callback_method: "GET"
              result: callback_details
          - Print Approval Callback Details:
              call: sys.log
              args:
                  severity: "INFO"
                  text: ${"Listening for callbacks on " + callback_details.url}
          - Await Approval Callback:
              call: events.await_callback
              args:
                  callback: ${callback_details}
                  timeout: 3600
              result: approvalResponse
          - Approval?:
              try:
                switch:
                  - condition: ${approvalResponse.http_request.query.response[0] == "yes"}
                    next: Buy or Sell?
              except:
                as: e
                steps:
                  - unknown_response:
                      raise: ${"Unknown response:" + e.message}
                      next: end
          - Buy or Sell?:
              switch:
                - condition: ${recommendResponse.body == "buy"}
                  next: Buy Stock
                - condition: ${recommendResponse.body == "sell"}
                  next: Sell Stock
                - condition: true
                  raise: ${"Unknown recommendation:" + recommendResponse.body}
          - Buy Stock:
              call: http.post
              args:
                url: ${"https://" + region + "-" + projectId + ".cloudfunctions.net/BuyStock"}
                auth:
                  type: OIDC
                body:
                  action: ${recommendResponse.body}
              result: message
          - Sell Stock:
              call: http.post
              args:
                url: ${"https://" + region + "-" + projectId + ".cloudfunctions.net/SellStock"}
                auth:
                  type: OIDC
                body:
                  action: ${recommendResponse.body}
              result: message
          - Report Result:
              call: googleapis.pubsub.v1.projects.topics.publish
              args:
                topic: ${"projects/" + projectId + "/topics/" + topic}
                body:
                  messages:
                  - data: '${base64.encode(json.encode(message))}'
              next: end
      ...

    קובץ JSON של תהליכי עבודה

      {
        "main": {
          "steps": [
            {
              "init": {
                "assign": [
                  {
                    "projectId": "${sys.get_env(\"GOOGLE_CLOUD_PROJECT_ID\")}"
                  },
                  {
                    "region": "LOCATION"
                  },
                  {
                    "topic": [
                      "PUBSUB_TOPIC_NAME"
                    ]
                  }
                ]
              }
            },
            {
              "Check Stock Price": {
                "call": "http.get",
                "args": {
                  "url": "${\"https://\" + region + \"-\" + projectId + \".cloudfunctions.net/CheckStockPrice\"}",
                  "auth": {
                    "type": "OIDC"
                  }
                },
                "result": "stockPriceResponse"
              }
            },
            {
              "Generate Buy/Sell Recommendation": {
                "call": "http.get",
                "args": {
                  "url": "${\"https://\" + region + \"-\" + projectId + \".cloudfunctions.net/BuySellRecommend\"}",
                  "auth": {
                    "type": "OIDC"
                  },
                  "query": {
                    "price": "${stockPriceResponse.body.stock_price}"
                  }
                },
                "result": "recommendResponse"
              }
            },
            {
              "Create Approval Callback": {
                "call": "events.create_callback_endpoint",
                "args": {
                  "http_callback_method": "GET"
                },
                "result": "callback_details"
              }
            },
            {
              "Print Approval Callback Details": {
                "call": "sys.log",
                "args": {
                  "severity": "INFO",
                  "text": "${\"Listening for callbacks on \" + callback_details.url}"
                }
              }
            },
            {
              "Await Approval Callback": {
                "call": "events.await_callback",
                "args": {
                  "callback": "${callback_details}",
                  "timeout": 3600
                },
                "result": "approvalResponse"
              }
            },
            {
              "Approval?": {
                "try": {
                  "switch": [
                    {
                      "condition": "${approvalResponse.http_request.query.response[0] == \"yes\"}",
                      "next": "Buy or Sell?"
                    }
                  ]
                },
                "except": {
                  "as": "e",
                  "steps": [
                    {
                      "unknown_response": {
                        "raise": "${\"Unknown response:\" + e.message}",
                        "next": "end"
                      }
                    }
                  ]
                }
              }
            },
            {
              "Buy or Sell?": {
                "switch": [
                  {
                    "condition": "${recommendResponse.body == \"buy\"}",
                    "next": "Buy Stock"
                  },
                  {
                    "condition": "${recommendResponse.body == \"sell\"}",
                    "next": "Sell Stock"
                  },
                  {
                    "condition": true,
                    "raise": "${\"Unknown recommendation:\" + recommendResponse.body}"
                  }
                ]
              }
            },
            {
              "Buy Stock": {
                "call": "http.post",
                "args": {
                  "url": "${\"https://\" + region + \"-\" + projectId + \".cloudfunctions.net/BuyStock\"}",
                  "auth": {
                    "type": "OIDC"
                  },
                  "body": {
                    "action": "${recommendResponse.body}"
                  }
                },
                "result": "message"
              }
            },
            {
              "Sell Stock": {
                "call": "http.post",
                "args": {
                  "url": "${\"https://\" + region + \"-\" + projectId + \".cloudfunctions.net/SellStock\"}",
                  "auth": {
                    "type": "OIDC"
                  },
                  "body": {
                    "action": "${recommendResponse.body}"
                  }
                },
                "result": "message"
              }
            },
            {
              "Report Result": {
                "call": "googleapis.pubsub.v1.projects.topics.publish",
                "args": {
                  "topic": "${\"projects/\" + projectId + \"/topics/\" + topic}",
                  "body": {
                    "messages": [
                      {
                        "data": "${base64.encode(json.encode(message))}"
                      }
                    ]
                  }
                },
                "next": "end"
              }
            }
          ]
        }
      }

    מחליפים את מה שכתוב בשדות הבאים:

    • LOCATION: Google Cloud אזור נתמך. לדוגמה, us-central1.
    • PUBSUB_TOPIC_NAME: השם של נושא ה-Pub/Sub. לדוגמה, my_stock_example.
  3. פורסים ואז מפעילים את תהליך העבודה.

  4. במהלך ההפעלה של תהליך העבודה, הוא מושהה וממתין להפעלת נקודת הקצה של הקריאה החוזרת. אפשר להשתמש בפקודת curl כדי לעשות את זה. לדוגמה:

    curl -H "Authorization: Bearer $(gcloud auth print-access-token)"
    https://workflowexecutions.googleapis.com/v1/projects/CALLBACK_URL?response=yes
    

    מחליפים את CALLBACK_URL בשאר הנתיב לנקודת הקצה (endpoint) של הקריאה החוזרת.

  5. אחרי שהשלמתם את תהליך העבודה, תוכלו לקבל את ההודעה מהמינוי ל-Pub/Sub. לדוגמה:

    gcloud pubsub subscriptions pull stock_example-sub  --format="value(message.data)" | jq
    

    הודעת הפלט צריכה להיות דומה להודעה הבאה (buy או sell):

    {
      "body": "buy",
      "code": 200,
      "headers": {
      [...]
      }
    

המאמרים הבאים