Migrar da AWS Step Functions para os fluxos de trabalho

Para ajudar você a se preparar para migrar do Amazon Web Services (AWS) Step Functions para os fluxos de trabalho no Google Cloud, esta página explica as principais semelhanças e diferenças entre os dois produtos. Essas informações têm o objetivo de ajudar aqueles que já conhecem o Step Functions implementam uma do Compute Engine usando o Workflows.

Assim como o Step Functions, o Workflows é um serviço totalmente gerenciado, de orquestração que executa serviços na ordem que você definir: um fluxo de trabalho. Esses fluxos de trabalho podem combinar serviços, incluindo serviços personalizados hospedados no Cloud Run ou nas funções do Cloud Run, serviços do Google Cloud como o Cloud Vision AI e o BigQuery, além de qualquer API baseada em HTTP.

Os Fluxos de trabalho Express do Step Functions são um tipo de fluxo de trabalho da AWS Step Functions que não é considerado aqui, porque a duração de um fluxo de trabalho Express é limitada e não há suporte para execução de fluxo de trabalho exatamente uma vez.

Hello World

Nessas funções, uma máquina de estado é um fluxo de trabalho, e uma tarefa é um estado em um que representa uma única unidade de trabalho executada por outro serviço da AWS. As funções em etapas exigem que cada estado defina o próximo.

No Workflows, uma série de etapas que usam o Workflows descreve as tarefas a serem executadas. O Workflows trata as etapas como se estivessem em uma lista ordenada, e os executava, um de cada vez, até que etapas executadas.

O exemplo "Hello World" a seguir demonstra o uso de estados em funções de etapa e etapas em fluxos de trabalho:

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

YAML de fluxos de trabalho

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

JSON de fluxos de trabalho

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

Visão geral da comparação

Esta seção compara os dois produtos em mais detalhes.

Step FunctionsFluxos de trabalho
SintaxeJSON (YAML nas ferramentas) YAML ou JSON
Fluxo de controleTransição entre estados Controle imperativo de fluxo com etapas
WorkerRecursos (ARN) Solicitações HTTP e conectores
ConfiabilidadePegar/tentar de novo Pegar/tentar de novo
ParalelismoCompatível Compatível
Dados de estadoO estado é transmitido Variáveis de fluxos de trabalho
AuthenticationIAM IAM
Experiência do usuárioWorkflow Studio, CLI, SDK, IaC Console do Google Cloud, CLI, SDK, IaC
Preços Preços do Step Functions Preços do Workflows
Sintaxe

O Step Functions usa principalmente JSON para definir funções e não oferece suporte YAML diretamente; No entanto, no AWS Toolkit para Visual Studio Code e no AWS, CloudFormation, é possível usar YAML para uma definição de funções de etapa.

É possível descrever as etapas dos fluxos de trabalho usando a sintaxe dos fluxos de trabalho, e elas podem ser gravadas em YAML ou JSON. A maioria são em YAML. Os exemplos nesta página demonstram as vantagens de YAML, incluindo facilidade de leitura e escrita e suporte nativo de comentários. Para uma explicação detalhada sobre a sintaxe do Workflows, consulte a Referência de sintaxe.

Fluxo de controle

O Workflows e o Step Functions modelam fluxos de trabalho como uma série de tarefas: etapas no Workflows e estados no Step Functions. Ambos permitem que uma tarefa indique qual tarefa será executada em seguida e são compatíveis com chaves condicionais para escolher a próxima unidade de trabalho com base no estado atual. Uma das principais diferenças é que as funções de etapa exigem que cada estado defina o próximo, enquanto os fluxos de trabalho executam as etapas na ordem em que são especificadas (incluindo as próximas etapas alternativas). Para mais informações, consulte Condições e Etapas.

Worker

Ambos os produtos orquestram recursos de computação, como funções, contêineres e outros serviços da Web para realizar tarefas. Nas funções em etapas, o worker é identificado por um campo Resource, que é sintaticamente um URI. Os URIs usados para identificar recursos de worker estão no formato Nome de Recurso da Amazon (ARN, na sigla em inglês), e os usuários não podem invocar diretamente um endpoint HTTP arbitrário.

Os fluxos de trabalho podem enviar solicitações HTTP para um endpoint HTTP arbitrário e receber uma resposta. Conectores facilitam a conexão com outras APIs do Google Cloud em um fluxo de trabalho, e integrar seus fluxos de trabalho a outros produtos do Google Cloud, como Pub/Sub, BigQuery ou Cloud Build. Conectores simplificam a chamada de serviços porque eles cuidam da formatação das solicitações para você, fornecendo métodos e argumentos para que você não precise saber os detalhes de uma com a API Google Cloud. Também é possível configurar o tempo limite e a sondagem políticas.

Confiabilidade

Se uma tarefa falhar, o fluxo de trabalho precisa ser capaz de tentar novamente de forma adequada, detectar exceções quando necessário e redirecionar o fluxo de trabalho conforme necessário. Ambas as etapas O Functions e o Workflows alcançam confiabilidade usando recursos detecção de exceções com novas tentativas e eventual envio para em outras partes do fluxo de trabalho. Para mais informações, consulte Erros de fluxo de trabalho.

Paralelismo

Talvez você queira que seu fluxo de trabalho orquestre várias tarefas em paralelo. As funções de etapa oferecem duas maneiras de fazer isso: você pode usar um item de dados e transmiti-lo em paralelo para várias tarefas diferentes ou usar uma matriz e transmitir os elementos dela para a mesma tarefa.

Nele, é possível definir uma parte do fluxo em que duas ou mais etapas podem ser executadas simultaneamente. É possível definir ramos que são executados simultaneamente ou um loop em que as iterações são executadas simultaneamente. Para saber mais, consulte Executar etapas do fluxo de trabalho em paralelo.

Dados de estado

Um dos benefícios de um mecanismo de fluxo de trabalho é que os dados de estado são mantidos para você sem um repositório de dados externo. No Step Functions, os dados de estado são transmitidos em uma estrutura JSON de um estado para outro.

No Workflows, é possível salvar os dados de estado em variáveis globais. Como você pode ter uma duração de execução de até um ano, é possível manter os dados de estado enquanto a instância ainda estiver em execução.

Autenticação

Ambos os produtos dependem de um sistema de gerenciamento de identidade e acesso (IAM) para autenticação e controle de acesso. Por exemplo, é possível usar um papel do IAM para invocar funções de etapa.

No Workflows, é possível usar uma conta de serviço para invocar um workflow; use o OAuth 2.0 ou o OIDC para se conectar ao Google Cloud APIs; e você pode usar um cabeçalho de solicitação de autorização para autenticar com uma API de terceiros. Para mais informações, consulte Conceder permissão a um fluxo de trabalho para acessar recursos do Google Cloud e Fazer solicitações autenticadas de um fluxo de trabalho.

Experiência do usuário

É possível usar uma ferramenta de linha de comando ou infraestrutura como código (IaC, na sigla em inglês) como: Terraform, para definir e gerenciar funções de etapa e Workflows.

Além disso, o Workflows oferece suporte à execução de fluxos de trabalho usando as bibliotecas de cliente, o console do Google Cloud, a Google Cloud CLI, ou enviando uma solicitação para a API REST do Workflows. Para mais detalhes, consulte Executar um fluxo de trabalho.

Preços

Os dois produtos têm um nível gratuito. Para mais detalhes, consulte as respectivas páginas de preços: Preços do Step Functions e Preços dos fluxos de trabalho.

Como associar tipos de estado a etapas

Há oito tipos de estado no Step Functions. Estados são elementos em um estado máquina capaz de tomar decisões com base em entradas, realizar ações e transmitir de saída para outros estados. Antes de migrar do Step Functions para Workflows, saiba como traduzir cada um deles. tipo de estado para uma etapa do Workflows.

Choice

O estado Choice adiciona lógica de ramificação a uma máquina de estado.

Nos fluxos de trabalho, é possível usar um bloco switch como um mecanismo de seleção que permite que o valor de uma expressão controle o fluxo da execução de um fluxo de trabalho. Se um valor for correspondente, a instrução dessa condição será executada. Para mais informações, consulte Condições.

Step Functions

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

YAML de fluxos de trabalho

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

JSON de fluxos de trabalho

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

Fail

O estado Fail interrompe a execução da máquina de estado e a marca como um falha.

No Workflows, é possível gerar erros personalizados usando o raise e você pode identificar e corrigir erros usando um bloco try/except. Para Para mais informações, consulte Gerar erros.

Step Functions

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

YAML de fluxos de trabalho

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

JSON do Workflows

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

Map

Um estado Map pode ser usado para executar um conjunto de etapas para cada elemento de uma matriz de entrada.

No Workflows, é possível usar uma repetição for para iterations.

Funções de etapa

  { "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 de fluxos de trabalho

  - 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 de fluxos de trabalho

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

Um estado Parallel pode ser usado para criar ramificações paralelas de execução na máquina de estados. No exemplo de Step Functions abaixo, uma pesquisa de endereço e telefone é realizada em paralelo.

Nos fluxos de trabalho, é possível usar uma etapa parallel para definir uma parte do fluxo de trabalho em que duas ou mais etapas podem ser executadas simultaneamente. Para mais informações, consulte Etapas paralelas.

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

YAML de fluxos de trabalho

  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 de fluxos de trabalho

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

Um estado Pass transmite a entrada para a saída sem realizar trabalho. Isso é comumente usado para manipular os dados de estado no JSON.

Como o Workflows não transmite dados dessa maneira, é possível deixe o estado como autônomo ou use uma etapa de atribuição para modificar variáveis. Para mais informações, consulte Atribua variáveis.

Step Functions

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

YAML de fluxos de trabalho

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

JSON de fluxos de trabalho

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

Sucesso

O estado Succeed interrompe uma execução.

Nos fluxos de trabalho, é possível usar return no fluxo principal para interromper a execução de um fluxo de trabalho. Você também pode finalizar um fluxo de trabalho concluindo etapa final (supondo que ela não pule para outra) ou use next: end para interromper a execução de um fluxo de trabalho se você não precisar retornar um valor. Para mais informações, consulte Conclua a execução de um fluxo de trabalho.

Step Functions

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

YAML de fluxos de trabalho

  return: "Success!"
  next: end

JSON de fluxos de trabalho

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

Task

Um estado Task representa uma única unidade de trabalho realizada por uma máquina de estados. Em no exemplo de funções de etapa a seguir, ela invoca uma função Lambda. As atividades são um recurso das funções de etapa da AWS que permitem executar uma tarefa na máquina de estado em que o trabalho é realizado em outro lugar.)

No exemplo do Workflows, um chamada a um endpoint HTTP para invocar uma função do Cloud Run. Também é possível usar um conector. o que facilita o acesso a outros produtos do Google Cloud. Além disso, é possível pausar um fluxo de trabalho e consultar dados. Ou você usar um endpoint de callback. para sinalizar ao fluxo de trabalho que um evento especificado ocorreu e aguardar esse evento sem sondagem.

Step Functions

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

YAML de fluxos de trabalho

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

JSON de fluxos de trabalho

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

Wait

Um estado Wait atrasa a continuidade da máquina de estados por um período especificado.

É possível usar a função da biblioteca padrão sys.sleep do Workflows para suspender a execução pelo número determinado de segundos até um máximo de 31536000 (um ano).

Funções de etapa

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

YAML de fluxos de trabalho

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

JSON de fluxos de trabalho

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

Exemplo: orquestrar microsserviços

O exemplo de funções da etapa a seguir verifica o preço de uma ação e determina se é preciso compra ou venda e informa o resultado. A máquina de estado no exemplo integra com o AWS Lambda passando parâmetros, usa uma fila do Amazon SQS para solicitar aprovação humana, e usa um tópico do Amazon SNS para retornar os resultados da consulta.

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

Migrar para o Workflows

Para migrar o exemplo de funções da etapa anterior para o Workflows, crie as etapas equivalentes do Workflows integrando Funções do Cloud Run, com suporte a uma endpoint de callback que aguarda solicitações HTTP que cheguem a esse endpoint, e usando uma Workflows conector para publicar em um tópico do Pub/Sub no lugar do tópico do Amazon SNS:

  1. Conclua as etapas para criar um fluxo de trabalho. mas não o implante ainda.

  2. Na definição do fluxo de trabalho, adicione uma etapa para criar um endpoint de callback que aguarda a contribuição humana, e uma etapa que usa um Workflows para publicar em um tópico do Pub/Sub. Exemplo:

    YAML de fluxos de trabalho

      ---
      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 de fluxos de trabalho

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

    Substitua:

    • LOCATION: uma região do Google Cloud compatível. Por exemplo, us-central1.
    • PUBSUB_TOPIC_NAME: o nome do tópico do Pub/Sub. Por exemplo, my_stock_example.
  3. Implante e execute o fluxo de trabalho.

  4. Durante a execução do fluxo de trabalho, ele é pausado e aguarda que você invoque o endpoint de callback. Você pode usar um comando curl para fazer isso. Exemplo:

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

    Substitua CALLBACK_URL pelo restante do para o endpoint de callback.

  5. Depois que o fluxo de trabalho for concluído, você poderá receber a mensagem da assinatura do Pub/Sub. Exemplo:

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

    A mensagem de saída precisa ser semelhante a esta (buy ou sell):

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

A seguir