태스크 상태 폴링

구조화된 데이터 파일을 업로드해도 리소스가 즉시 생성되거나 업데이트되지는 않습니다. Display & Video 360에서 SDF를 처리하고 업데이트를 적용하는 데 몇 초에서 몇 시간이 걸릴 수 있습니다. 중복되는 리소스가 포함되어 있지 않다면 여러 파일을 동시에 업로드할 수 있습니다.

작업이 완료되었는지 확인하려면 sdfuploadtasks.operations.get를 사용하여 작업을 정기적으로 가져오고 done 필드가 True이고 작업이 완료되었는지 확인합니다. 이 프로세스를 '폴링'이라고 합니다.

작업이 완료되면 response 또는 error 필드가 설정됩니다. error 필드가 채워져 있으면 작업이 실패한 것이며 실패에 관한 세부정보는 결과 Status 객체에서 확인할 수 있습니다. response 필드가 채워지면 SdfUploadTask이 필드에 할당됩니다. 이는 Display & Video 360에서 업로드된 SDF를 성공적으로 처리했음을 의미합니다. SdfUploadTask.resourceName 필드에 제공된 위치에서 결과 파일을 다운로드합니다.

장기 실행 보고서를 확인하는 비효율적인 폴링 구현은 많은 API 요청 할당량을 소비합니다. 재시도를 제한하고 할당량을 보존하려면 지수 백오프를 사용하세요.

지수 백오프를 사용하여 SDF 업로드 작업을 폴링하는 방법은 다음과 같습니다.

# Import the necessary libraries
import random
import time

# Provide the name of the sdfuploadtask 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

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

sleep = 0

start_time = time.time()
while True:
  # Get current status of the report.
  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 result files can be '
        f'downloaded at {operation["response"]["resourceName"]}.')
    break
  elif time.time() - start_time > max_retry_elapsed_time:
    print("Polling deadline exceeded.")
    break

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

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