Von AWS Step Functions zu Workflows migrieren

Auf dieser Seite werden die wichtigsten Gemeinsamkeiten und Unterschiede zwischen den beiden Produkten erläutert, damit Sie sich auf die Migration von AWS-Schrittfunktionen (Amazon Web Services) zu Workflows in Google Cloud vorbereiten können. Diese Informationen sollen Nutzern helfen, die bereits mit Step Functions vertraut sind, eine ähnliche Architektur mit Workflows zu implementieren.

Ähnlich wie Step Functions ist Workflows eine vollständig verwaltete, zustandsbasierte Orchestrierungsplattform, die Dienste in einer von Ihnen definierten Reihenfolge ausführt: einem Workflow. Diese Workflows können Dienste kombinieren, einschließlich benutzerdefinierter Dienste, die in Cloud Run oder Cloud Run Functions gehostet werden, Google Cloud-Diensten wie Cloud Vision AI und BigQuery und einer beliebigen HTTP-basierten API.

Express-Workflows sind ein Workflowtyp von AWS Step Functions, der hier nicht berücksichtigt wird, da die Dauer eines Express-Workflows begrenzt ist und eine Workflowausführung genau einmal nicht unterstützt wird.

Hello World

In Step Functions ist ein FSM ein Workflow und eine Aufgabe ist ein Status in einem Workflow, der eine einzelne Arbeitseinheit darstellt, die von einem anderen AWS-Dienst ausgeführt wird. Bei Step Functions muss für jeden Status der nächste Status definiert werden.

In Workflows werden die auszuführenden Aufgaben durch eine Reihe von Schritten mit der Workflow-Syntax beschrieben. In Workflows werden Schritte so behandelt, als wären sie in einer sortierten Liste, und sie werden nacheinander ausgeführt, bis alle Schritte ausgeführt wurden.

Im folgenden „Hallo Welt“-Beispiel wird die Verwendung von Zuständen in Schrittfunktionen und Schritten in Workflows veranschaulicht:

Schrittfunktionen

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

YAML-Datei für Workflows

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

Workflows JSON

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

Vergleich – Übersicht

In diesem Abschnitt werden die beiden Produkte genauer verglichen.

SchrittfunktionenWorkflows
SyntaxJSON (YAML in Tools) YAML oder JSON
AblaufsteuerungStatuswechsel Imperative Ablaufsteuerung mit Schritten
ArbeiterRessourcen (ARN) und HTTP-Task HTTP-Anfragen und Connectors
ZuverlässigkeitAuffangen/Wiederholen Auffangen/Wiederholen
ParallelitätUnterstützt Unterstützt
StatusdatenStatus wird übergeben Workflow-Variablen
AuthentifizierungIAM IAM
Auswirkungen für NutzerWorkflow Studio, CLI, SDK, IaC Google Cloud Console, CLI, SDK, IaC
Preise Preise für Step Functions Workflow-Preise
Syntax

In Step Functions werden Funktionen hauptsächlich mit JSON definiert und YAML wird nicht direkt unterstützt. Im AWS Toolkit für Visual Studio Code und in AWS CloudFormation können Sie jedoch YAML für eine Step Functions-Definition verwenden.

Sie können Workflow-Schritte mit der Workflows-Syntax beschreiben. Sie können entweder in YAML oder JSON geschrieben werden. Die meisten Workflows sind in YAML. Die Beispiele auf dieser Seite zeigen die Vorteile von YAML, darunter die einfache Les- und Schreibbarkeit sowie die native Unterstützung von Kommentaren. Eine ausführliche Erläuterung der Workflows-Syntax finden Sie in der Syntaxreferenz.

Kontrollfluss

Sowohl Workflows als auch Step Functions modellieren Workflows als eine Reihe von Aufgaben: Schritte in Workflows und Zustände in Step Functions. Bei beiden können Sie angeben, welche Aufgabe als Nächstes ausgeführt werden soll, und schalterschieneähnliche Bedingungen unterstützen, um die nächste Arbeitseinheit basierend auf dem aktuellen Status auszuwählen. Ein wichtiger Unterschied besteht darin, dass bei Step Functions jeder Status den nächsten definiert, während bei Workflows die Schritte in der Reihenfolge ausgeführt werden, in der sie angegeben sind (einschließlich alternativer nächster Schritte). Weitere Informationen finden Sie unter Voraussetzungen und Schritte.

Worker

Beide Produkte orchestrieren Rechenressourcen wie Funktionen, Container und andere Webdienste, um Aufgaben zu erledigen. In Step Functions wird der Worker durch ein Resource-Feld identifiziert, das syntaktisch ein URI ist. Die URIs, die zum Identifizieren von Arbeitsressourcen verwendet werden, sind im Amazon Resource Name (ARN)-Format. Wenn Sie einen beliebigen HTTP-Endpunkt direkt aufrufen möchten, können Sie eine HTTP-Aufgabe definieren.

Workflows können HTTP-Anfragen an einen beliebigen HTTP-Endpunkt senden und eine Antwort erhalten. Mithilfe von Connectors können Sie eine Verbindung zu anderen Google Cloud APIs in einem Workflow herstellen und Ihre Workflows in andere Google Cloud-Produkte wie Pub/Sub, BigQuery oder Cloud Build integrieren. Connectors vereinfachen den Aufruf von Diensten, da sie die Formatierung von Anfragen für Sie verarbeiten und Methoden und Argumente bereitstellen. Sie müssen also die Details einer Google Cloud API nicht kennen. Sie können auch die Zeitüberschreitung und die Abfragerichtlinien konfigurieren.

Zuverlässigkeit

Wenn eine Aufgabe fehlschlägt, muss Ihr Workflow die Ausführung entsprechend wiederholen, bei Bedarf Ausnahmen abfangen und den Workflow nach Bedarf umleiten können. Sowohl Schrittfunktionen als auch Workflows erreichen mit ähnlichen Mechanismen Zuverlässigkeit: Ausnahmebehandlung mit Wiederholungen und eventuelle Weiterleitung an eine andere Stelle im Workflow. Weitere Informationen finden Sie unter Workflow-Fehler.

Parallelität

Möglicherweise möchten Sie, dass Ihr Workflow mehrere Aufgaben parallel ausführt. Mit Schrittfunktionen gibt es zwei Möglichkeiten, dies zu erreichen: Sie können ein Datenelement parallel an mehrere verschiedene Aufgaben übergeben oder ein Array verwenden und seine Elemente an dieselbe Aufgabe übergeben.

In Workflows können Sie einen Teil Ihres Workflows definieren, in dem zwei oder mehr Schritte gleichzeitig ausgeführt werden können. Sie können entweder Äste definieren, die gleichzeitig ausgeführt werden, oder eine Schleife, in der Iterationen gleichzeitig ausgeführt werden. Weitere Informationen finden Sie unter Workflowschritte parallel ausführen.

Statusdaten

Ein Vorteil einer Workflow-Engine besteht darin, dass Statusdaten ohne externen Datenspeicher verwaltet werden. In Step Functions werden die Statusdaten in einer JSON-Struktur von einem Status an einen anderen übergeben.

In Workflows können Sie die Statusdaten in globalen Variablen speichern. Da die Ausführungsdauer bis zu einem Jahr betragen darf, können Sie die Statusdaten so lange aufbewahren, wie die Instanz noch ausgeführt wird.

Authentifizierung

Beide Produkte nutzen ein untergeordnetes IAM-System (Identity and Access Management) für die Authentifizierung und Zugriffssteuerung. Sie können beispielsweise eine IAM-Rolle verwenden, um Step Functions aufzurufen.

In Workflows können Sie ein Dienstkonto verwenden, um einen Workflow aufzurufen. Sie können OAuth 2.0 oder OIDC verwenden, um eine Verbindung zu Google Cloud APIs herzustellen. Außerdem können Sie einen Autorisierungsanfrage-Header verwenden, um sich bei einer Drittanbieter-API zu authentifizieren. Weitere Informationen finden Sie unter Zugriff auf Google Cloud-Ressourcen für einen Workflow gewähren und Authentifizierte Anfragen von einem Workflow aus ausführen.

Nutzer

Sie können ein Befehlszeilentool oder ein IaC-Tool (Infrastructure as Code) wie Terraform verwenden, um sowohl Step Functions als auch Workflows zu definieren und zu verwalten.

Außerdem unterstützt Workflows die Ausführung von Workflows mit den Clientbibliotheken, in der Google Cloud Console, mit der Google Cloud CLI oder durch Senden einer Anfrage an die Workflows REST API. Weitere Informationen finden Sie unter Workflow ausführen.

Preise

Beide Produkte haben eine kostenlose Stufe. Weitere Informationen finden Sie auf den jeweiligen Preisseiten: Step Functions-Preise und Workflows-Preise.

Statustypen zu Schritten zuordnen

In Step Functions gibt es acht Statustypen. Zustände sind Elemente in einem Zustandsautomaten, die anhand ihrer Eingabe Entscheidungen treffen, Aktionen ausführen und die Ausgabe an andere Zustände weitergeben können. Bevor Sie von Step Functions zu Workflows migrieren, sollten Sie wissen, wie Sie jeden Statustyp in einen Workflowschritt umwandeln.

Choice

Mit einem Choice-Status wird einem Zustandsautomaten eine Verzweigungslogik hinzugefügt.

In Workflows können Sie einen switch-Block als Auswahlmechanismus verwenden, mit dem der Wert eines Ausdrucks den Ablauf der Ausführung eines Workflows steuern kann. Wenn ein Wert übereinstimmt, wird die Anweisung dieser Bedingung ausgeführt. Weitere Informationen finden Sie unter Bedingungen.

Schrittfunktionen

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

YAML-Datei für Workflows

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

Workflows JSON

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

Fail

Im Status Fail wird die Ausführung des Zustandsautomaten beendet und als Fehler gekennzeichnet.

In Workflows können Sie mit der raise-Syntax benutzerdefinierte Fehler auslösen und mit einem try/except-Block Fehler abfangen und behandeln. Weitere Informationen finden Sie unter Fehler melden.

Schrittfunktionen

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

YAML-Datei für Workflows

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

Workflows JSON

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

Map

Mit einem Map-Zustand können Sie eine Reihe von Schritten für jedes Element eines Eingabearrays ausführen.

In Workflows können Sie for-Schleifen für iterations verwenden.

Schrittfunktionen

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

YAML-Datei für Workflows

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

Workflows 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

Mit einem Parallel-Status können Sie parallele Ausführungszweige in Ihrem Zustandsautomaten erstellen. Im folgenden Step Functions-Beispiel werden eine Adressen- und eine Telefonnummernsuche parallel ausgeführt.

In Workflows können Sie mit einem parallel-Schritt einen Teil Ihres Workflows definieren, in dem zwei oder mehr Schritte gleichzeitig ausgeführt werden können. Weitere Informationen finden Sie unter Parallele Schritte.

Schrittfunktionen

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

YAML-Datei für Workflows

  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}

Workflows 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

Im Status Pass wird die Eingabe an die Ausgabe übergeben, ohne dass eine Arbeit ausgeführt wird. Diese Methode wird häufig verwendet, um die Statusdaten in JSON zu manipulieren.

Da Workflows Daten nicht auf diese Weise weitergeben, können Sie den Status als „No-Op“ belassen oder die Variablen mit einem Zuweisungsschritt ändern. Weitere Informationen finden Sie unter Variablen zuweisen.

Schrittfunktionen

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

YAML-Datei für Workflows

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

Workflows JSON

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

Erfolgreich

Mit dem Status Succeed wird eine Ausführung erfolgreich beendet.

In Workflows können Sie return im Hauptworkflow verwenden, um die Ausführung eines Workflows zu beenden. Sie können einen Workflow auch durch Ausführen des letzten Schritts beenden (vorausgesetzt, der Schritt springt nicht zu einem anderen). Mit next: end können Sie die Ausführung eines Workflows beenden, wenn Sie keinen Wert zurückgeben müssen. Weitere Informationen finden Sie unter Ausführung eines Workflows abschließen.

Schrittfunktionen

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

YAML-Datei für Workflows

  return: "Success!"
  next: end

Workflows JSON

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

Task

Ein Task-Status stellt eine einzelne Arbeitseinheit dar, die von einem Zustandsautomaten ausgeführt wird. Im folgenden Step Functions-Beispiel wird eine Lambda-Funktion aufgerufen. Aktivitäten sind eine Funktion von AWS Step Functions, mit der Sie in Ihrem Zustandsautomaten eine Aufgabe definieren können, bei der die Arbeit an anderer Stelle ausgeführt wird.

Im Workflow-Beispiel wird ein HTTP-Endpunkt aufgerufen, um eine Cloud Run-Funktion aufzurufen. Sie können auch einen Connector verwenden, der den einfachen Zugriff auf andere Google Cloud-Produkte ermöglicht. Außerdem können Sie einen Workflow pausieren und nach Daten abfragen. Alternativ können Sie einen Callback-Endpunkt verwenden, um Ihrem Workflow zu signalisieren, dass ein bestimmtes Ereignis aufgetreten ist, und auf dieses Ereignis ohne Abfrage warten.

Schrittfunktionen

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

YAML-Datei für Workflows

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

Workflows JSON

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

Wait

Im Status Wait wird die Ausführung der FSM für eine bestimmte Zeit pausiert.

Mit der Standardbibliotheksfunktion sys.sleep von Workflows können Sie die Ausführung für die angegebene Anzahl von Sekunden bis zu maximal 31536000 (ein Jahr) pausieren.

Schrittfunktionen

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

YAML-Datei für Workflows

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

Workflows JSON

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

Beispiel: Mikrodienste orchestrieren

Im folgenden Beispiel für Step Functions wird ein Aktienkurs geprüft, ob gekauft oder verkauft werden soll, und das Ergebnis ausgegeben. Der Statusautomat im Beispiel wird durch Übergeben von Parametern in AWS Lambda eingebunden. Er verwendet eine Amazon SQS-Warteschlange, um eine manuelle Genehmigung anzufordern, und ein Amazon SNS-Topic, um die Ergebnisse der Abfrage zurückzugeben.

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

Zu Workflows migrieren

Wenn Sie das vorherige Step Functions-Beispiel zu Workflows migrieren möchten, können Sie die entsprechenden Workflow-Schritte erstellen, indem Sie Cloud Run-Funktionen einbinden, einen Callback-Endpunkt unterstützen, der auf das Eintreffen von HTTP-Anfragen an diesem Endpunkt wartet, und einen Workflows-Connector verwenden, um in einem Pub/Sub-Thema zu veröffentlichen, anstelle des Amazon SNS-Themas:

  1. Führen Sie die Schritte zum Erstellen eines Workflows aus, stellen Sie ihn jedoch noch nicht bereit.

  2. Fügen Sie in der Definition des Workflows einen Schritt hinzu, um einen Callback-Endpunkt zu erstellen, der auf eine manuelle Eingabe wartet, und einen Schritt, mit dem über einen Workflows-Connector in einem Pub/Sub-Thema veröffentlicht wird. Beispiel:

    YAML-Datei für Workflows

      ---
      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
      ...

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

    Ersetzen Sie Folgendes:

    • LOCATION: einer unterstützten Google Cloud-Region. Beispiel: us-central1
    • PUBSUB_TOPIC_NAME: der Name Ihres Pub/Sub-Themas. Beispiel: my_stock_example.
  3. Stellen Sie den Workflow bereit und führen Sie ihn aus.

  4. Während der Ausführung des Workflows wird eine Pause eingelegt und auf die Aufrufung des Rückruf-Endpunkts gewartet. Dazu können Sie einen curl-Befehl verwenden. Beispiel:

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

    Ersetzen Sie CALLBACK_URL durch den Rest des Pfads zu Ihrem Callback-Endpunkt.

  5. Sobald der Workflow abgeschlossen ist, können Sie die Nachricht über das Pub/Sub-Abo empfangen. Beispiel:

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

    Die Ausgabe sollte in etwa so aussehen (entweder buy oder sell):

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

Nächste Schritte