Search code examples
google-workflows

how do you start a workflow from another workflow and retrieve the return value of called workflow


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


Solution

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