3

I am testing google workflow and would like to call a workflow from another workflow but as a separate process (not a subworkflow)

I am able to start the execution but currently unable to retrieve the return value. I receive instead an instance of the execution:

{
     "argument": "null",
     "name": "projects/xxxxxxxxxxxx/locations/us-central1/workflows/child-workflow/executions/9fb4aa01-2585-42e7-a79f-cfb4b57b22d4",
     "startTime": "2020-12-09T01:38:07.073406981Z",
     "state": "ACTIVE",
     "workflowRevisionId": "000003-cf3"
 }

parent-workflow.yaml

main:
params: [args]

steps:
    
    - callChild:
        call: http.post
        args:
            url: 'https://workflowexecutions.googleapis.com/v1beta/projects/my-project/locations/us-central1/workflows/child-workflow/executions'
            auth: 
                type: OAuth2
                scope: 'https://www.googleapis.com/auth/cloud-platform'
        result: callresult
    
    - returnValue:
        return: ${callresult.body}

child-workflow.yaml:

 - getCurrentTime:
        call: http.get
        args:
            url: https://us-central1-workflowsample.cloudfunctions.net/datetime
        result: CurrentDateTime
    - readWikipedia:
        call: http.get
        args:
            url: https://en.wikipedia.org/w/api.php
            query:
                action: opensearch
                search: ${CurrentDateTime.body.dayOfTheWeek}
        result: WikiResult
    - returnOutput:
        return: ${WikiResult.body[1]}

also as an added question how can create a dynamic url from a variable. ${} doesn't seem to work there

Pascal DeMilly
  • 681
  • 1
  • 6
  • 16
  • You have a low rate. Important on SO, you have to mark accepted answers by using the tick on the left of the posted answer, below the voting. This will increase your rate. See how this works by visinting this link: http://meta.stackoverflow.com/questions/5234/how-does-accepting-an-answer-work#5235 – Pentium10 Dec 09 '20 at 15:41

2 Answers2

4

As Executions are async API calls, you need to POLL for the workflow to see when finished.

You can have the following algorithm:

main:
  steps:  
    - callChild:
        call: http.post
        args:
            url: ${"https://workflowexecutions.googleapis.com/v1beta/projects/"+sys.get_env("GOOGLE_CLOUD_PROJECT_ID")+"/locations/us-central1/workflows/http_bitly_secrets/executions"}
            auth: 
                type: OAuth2
                scope: 'https://www.googleapis.com/auth/cloud-platform'
        result: workflow
    - waitExecution:
        call: CloudWorkflowsWaitExecution
        args:
          execution: ${workflow.body.name}
        result: workflow
    - returnValue:
        return: ${workflow}
CloudWorkflowsWaitExecution:
  params: [execution]
  steps:
    - init:
        assign:
          - i: 0
          - valid_states: ["ACTIVE","STATE_UNSPECIFIED"]
          - result: 
              state: ACTIVE
    - check_condition:
        switch:
          - condition: ${result.state in valid_states AND i<100}
            next: iterate
        next: exit_loop
    - iterate:
        steps:
          - sleep:
              call: sys.sleep
              args:
                seconds: 10
          - process_item:
              call: http.get
              args:
                url: ${"https://workflowexecutions.googleapis.com/v1beta/"+execution}
                auth:
                  type: OAuth2
              result: result
          - assign_loop:
              assign:
                - i: ${i+1}
                - result: ${result.body} 
        next: check_condition
    - exit_loop:
        return: ${result}

What you see here is that we have a CloudWorkflowsWaitExecution subworkflow which will loop 100 times at most, also has a 10 second delay, it will stop when the workflow has finished, and returns the result.

The output is:

argument: 'null'
endTime: '2020-12-09T13:00:11.099830035Z'
name: projects/985596417983/locations/us-central1/workflows/call_another_workflow/executions/05eeefb5-60bb-4b20-84bd-29f6338fa66b
result: '{"argument":"null","endTime":"2020-12-09T13:00:00.976951808Z","name":"projects/985596417983/locations/us-central1/workflows/http_bitly_secrets/executions/2f4b749c-4283-4c6b-b5c6-e04bbcd57230","result":"{\"archived\":false,\"created_at\":\"2020-10-17T11:12:31+0000\",\"custom_bitlinks\":[],\"deeplinks\":[],\"id\":\"j.mp/2SZaSQK\",\"link\":\"//<edited>/2SZaSQK\",\"long_url\":\"https://cloud.google.com/blog\",\"references\":{\"group\":\"https://api-ssl.bitly.com/v4/groups/Bg7eeADYBa9\"},\"tags\":[]}","startTime":"2020-12-09T13:00:00.577579042Z","state":"SUCCEEDED","workflowRevisionId":"000001-478"}'
startTime: '2020-12-09T13:00:00.353800247Z'
state: SUCCEEDED
workflowRevisionId: 000012-cb8

in the result there is a subkey that holds the results from the external Workflow execution.

Pentium10
  • 204,586
  • 122
  • 423
  • 502
  • Thanks. You answered all my questions. I have another but maybe I should create a new thread. Let me know.Can I use another language (DSL) than yaml to create a workflow. 30 lines for a loop seems like a throwback to cobol time :-) – Pascal DeMilly Dec 09 '20 at 21:13
  • Nope, that's a highly requested feature as well. – Pentium10 Dec 09 '20 at 21:16
2

The best method is now the workflows.executions.run helper method, which formats the request and blocks until the workflow execution has completed:

- run_execution:
    try:
      call: googleapis.workflowexecutions.v1.projects.locations.workflows.executions.run
      args:
        workflow_id: ${workflow}
        location: ${location}   # Defaults to current location
        project_id: ${project}  # Defaults to current project
        argument: ${arguments}  # Arguments could be specified inline as a map instead.
      result: r1
    except:
      as: e
      steps: ... # handle a failed execution
Kris Braun
  • 1,330
  • 13
  • 21