Poll for task status

更新时间:
复制 MD 格式

Learn how to build a reliable polling workflow in Serverless Workflow to track the status of a long-running task until it completes.

How the polling pattern works

The polling pattern is a recurring process that periodically checks an external system until a condition is met — for example, querying job status until it succeeds or fails. Unlike a fixed-interval timer trigger, a Serverless Workflow polling loop waits between iterations (avoiding overlap) and persists its state, so the workflow resumes from where it left off if the polling process fails mid-run.

Use this pattern when a long-running task does not support callbacks. If the task can notify your workflow on completion, use a callback instead — it is simpler and more efficient.

This tutorial implements a polling workflow for a multimedia processing task that may take anywhere from one minute to several hours. The workflow periodically calls a status-check function and exits as soon as the task succeeds — or after three polling attempts if it has not.

Implementation in Serverless Workflow

This tutorial walks through the following three steps to build the polling workflow:

  1. Create a function in Function Compute

  2. Create a workflow in Serverless Workflow

  3. Execute the workflow and view the result

Step 1: Create a function in Function Compute

Create a service named fnf-demo in Function Compute, then create the following two Python 3.10 functions in that service. For setup instructions, see Quickly create a function.

  • StartJob — simulates calling an API to start a long-running task. Returns a unique job ID that the polling loop uses to track that task.

    import logging
    import uuid
    
    def handler(event, context):
      logger = logging.getLogger()
      id = uuid.uuid4()
      logger.info('Started job with ID %s' % id)
      return {"job_id": str(id)}           
  • GetJobStatus — simulates calling an API to check the status of a running task. It compares the elapsed time since first execution against the delay threshold and returns either "success" or "running". It also increments try_count on each call so the workflow can enforce a maximum retry limit.

    import logging
    import uuid
    import time
    import json
    
    # Record the time this function instance was first loaded
    start_time = int(time.time())
    
    def handler(event, context):
      evt = json.loads(event)
      logger = logging.getLogger()
      job_id = evt["job_id"]
      logger.info('Started job with ID %s' % job_id)
    
      now = int(time.time())
      status = "running"
    
      # Default delay before the task is considered complete (seconds)
      delay = 60
      if "delay" in evt:
        delay = evt["delay"]
    
      # If enough time has elapsed, mark the task as successful
      if now - start_time > delay:
        status = "success"
    
      try_count = 0
      if "try_count" in evt:
        try_count = evt["try_count"]
    
      # Track how many times the status has been polled
      try_count = try_count + 1
      logger.info('Job %s, status %s, try_count %d' % (job_id, status, try_count))
      return {"job_id": job_id, "job_status":status, "try_count":try_count}         

Step 2: Create a workflow in Serverless Workflow

In the Flows page of the CloudFlow console, click Create Flow. In the Flow Definition step of the Create Flow wizard, configure the Details and Definition sections.

The workflow runs the following polling loop:

  1. StartJob: Calls the StartJob function to start the task and get its job ID.

  2. Wait10s: Pauses for 10 seconds before the next status check, preventing unnecessary API calls.

  3. GetJobStatus: Calls the GetJobStatus function to query the current task status.

  4. CheckJobComplete: Evaluates the status returned by GetJobStatus and branches accordingly:

    • "success" — the workflow ends successfully.

    • try_count > 3 — the task has been polled three or more times without completing, so the workflow fails.

    • "running" — loops back to the Wait10s step to wait before the next poll.

    version: v1
    type: flow
    steps:
      - type: task
        name: StartJob
        resourceArn: acs:fc:{region}:{accountID}:services/fnf-demo/functions/StartJob
      - type: pass
        name: Init
        outputMappings:
          - target: try_count
            source: 0
      - type: wait
        name: Wait10s
        duration: 10
      - type: task
        name: GetJobStatus
        resourceArn: acs:fc:{region}:{accountID}:services/fnf-demo/functions/GetJobStatus
        inputMappings:
          - target: job_id
            source: $local.job_id
          - target: delay
            source: $input.delay
          - target: try_count
            source: $local.try_count
      - type: choice
        name: CheckJobComplete
        inputMappings:
          - target: status
            source: $local.job_status
          - target: try_count
            source: $local.try_count
        choices:
            - condition: $.status == "success"
              goto: JobSucceeded
            - condition: $.try_count > 3
              goto: JobFailed
            - condition: $.status == "running"
              goto: Wait10s
      - type: succeed
        name: JobSucceeded
      - type: fail
        name: JobFailed           

Step 3: Execute the workflow and view the result

In the CloudFlow console, find the workflow, click Start Execution, and enter the following JSON as the execution input. The delay value controls how many seconds the task takes to complete. With delay set to 20, the GetJobStatus function returns "running" for the first 20 seconds, then "success". Adjust delay to observe different execution paths.

{
  "delay": 20
}
  • The following figure shows the visual execution trace of the polling workflow from start to finish.Screen Shot 2019-06-26 at 12.30.01 PM

  • As shown below, the task takes 20 seconds. The first call to GetJobStatus returns "running", so CheckJobComplete sends the workflow back to Wait10s. The second call returns "success", and the workflow ends successfully.Screen Shot 2019-06-26 at 12.39.26 PM