タスクのステータスをポーリングする

構造化データファイル(SDF)の生成には、数秒から数時間かかることがあります。Operationdone フィールドが True の場合、タスクは完了しています。

Operation は、/sdfdownloadtasks/operations/{id} 形式の名前で識別されます。sdfdownloadtasks.operations.get を使用して、この名前の Operation を定期的に取得し、タスクが完了したかどうかを確認します。このプロセスを「ポーリング」と呼びます。

doneTrue の場合、response フィールドまたは error フィールドのいずれかが設定されます。失敗したタスクは error フィールドを設定します。割り当てられた Status オブジェクトには、障害の詳細が示されます。タスクが成功すると、response フィールドが設定されます。結果の SDF を response.resourceName からダウンロードします。

非効率的なポーリングは、API リクエストの割り当てを大量に消費する可能性があります。指数バックオフを使用して、再試行回数を制限し、割り当てを節約します。

指数バックオフを使用して SDF ダウンロード タスクをポーリングする方法は次のとおりです。

Java

// Provide the name of the sdfdownloadtask operation.
String operationName = operation-name;

// Configure the Operations.get request.
Sdfdownloadtasks.Operations.Get operationRequest =
    service.sdfdownloadtasks().operations().get(operationName);

// Configure exponential backoff for checking the status of our operation.
ExponentialBackOff backOff =
    new ExponentialBackOff.Builder()
        .setInitialIntervalMillis(5000) // setting initial interval to five seconds
        .setMaxIntervalMillis(5000 * 60) // setting max interval to five minutes
        .setMaxElapsedTimeMillis(5000 * 60 * 60) // setting max elapsed time to five hours
        .build();
long backoffMillis = 0;

// Create default operation variable.
Operation operation = new Operation();

do {
  // Sleep before retrieving operation again.
  Thread.sleep(backoffMillis);

  // Retrieve operation.
  operation = operationRequest.execute();

  // If operation is not done, calculate next sleep period.
  if (operation.getDone() == null) {
    backoffMillis = backOff.nextBackOffMillis();
    if (backoffMillis == ExponentialBackOff.STOP) {
      System.out.printf("The operation has taken more than five hours to complete.%n");
      break;
    }
    System.out.printf(
        "Operation %s is still running, sleeping for %s milliseconds.%n",
        operationName, backoffMillis);
  }
} while (operation.getDone() == null);

// Check whether operation finished with an error, or is completed and ready to download.
if (operation.getDone() != null) {
  if (operation.getError() != null) {
    System.out.printf(
        "The operation finished in error with code %s: %s%n",
        operation.getError().getCode(), operation.getError().getMessage());
  } else {
    System.out.printf(
        "The operation completed successfully. Resource %s was created.%n",
        operation.getResponse().get("resourceName").toString());
  }
}

Python

# Provide the name of the sdfdownloadtask operation.
operation_name = operation-name

# Set the following values that control retry behavior while the operation
# is running.
# Minimum amount of time between polling requests. Defaults to 5 seconds.
min_retry_interval = 5
# Maximum amount of time between polling requests. Defaults to 5 minutes.
max_retry_interval = 5 * 60
# Maximum amount of time to spend polling. Defaults to 5 hours.
max_retry_elapsed_time = 5 * 60 * 60

def next_sleep_interval(previous_sleep_interval):
  """Calculates the next sleep interval based on the previous."""
  min_interval = previous_sleep_interval or min_retry_interval
  max_interval = previous_sleep_interval * 3 or min_retry_interval
  return min(max_retry_interval, random.randint(min_interval, max_interval))

# Configure the sdfdownloadtasks.operations.get request.
get_request = service.sdfdownloadtasks().operations().get(name=operation_name)

sleep = 0
start_time = time.time()

while True:
  # Retrieve the operation.
  operation = get_request.execute()

  if "done" in operation:
    if "error" in operation:
      print(
          f"The operation finished in error with code "
          f'{operation["error"]["code"]}: {operation["error"]["message"]}'
      )
    else:
      print(
          f"The operation completed successfully. The resulting files can be "
          f'downloaded at {operation["response"]["resourceName"]}.'
      )
    break
  elif time.time() - start_time > max_retry_elapsed_time:
    print("SDF generation deadline exceeded.")
    break

  sleep = next_sleep_interval(sleep)
  print(
      f"Operation {operation_name} is still running, sleeping for "
      f"{sleep} seconds."
  )
  time.sleep(sleep)

PHP

// The following values control retry behavior while the task is processing.
// Minimum amount of time between polling requests. Defaults to 5 seconds.
$minRetryInterval = 5;
// Maximum amount of time between polling requests. Defaults to 5 minutes.
$maxRetryInterval = 300;
// Maximum amount of time to spend polling. Defaults to 5 hours.
$maxRetryElapsedTime = 18000;

// Provide the name of the sdfdownloadtask operation.
$operationName = operation-name;

// Poll operation.
$sleep = 0;
$startTime = time();
do {
    try {
        // Call the API, retrieving the SDF Download Task.
        $operation = $this->service->sdfdownloadtasks_operations->get(
            $operationName
        );
    } catch (\Exception $e) {
        $this->renderError($e);
        return;
    }

    // Check if retrieved operation is finished.
    if ($operation->getDone() === true) {
        if($operation->getError() !== null) {
            $error = $operation->getError();
            printf(
                'The operation finished in error with code %s: %s<br>',
                $error->setCode(),
                $error->setMessage()
            );
            break;
        } else {
            $response = $operation->getResponse();
            printf(
                'The operation completed successfully. Resource %s '
                    . 'was created.<br>',
                $response['resourceName']
            );
            break;
        }
    } elseif (time() - $startTime > self::MAX_RETRY_ELAPSED_TIME) {
        print '<p>SDF download task processing deadline exceeded</p>';
        break;
    }

    // Generate next sleep interval.
    $minInterval = max($minRetryInterval, $sleep);
    $maxInterval = max(
        $minRetryInterval,
        $sleep * 3
    );
    $sleep = min($maxRetryInterval, rand($minInterval, $maxInterval));

    // Sleep a determined amount of time before retrieving the operation
    // again.
    printf(
        'Operation %s is still running, sleeping for %d seconds<br>',
        $operationName,
        $sleep
    );
    sleep($sleep);
} while (true);