Lưu lượng sử dụng

Các bước để sử dụng tính năng xử lý hàng loạt như sau:

Tạo một công việc hàng loạt mới

Bạn cần tạo tài nguyên BatchJob bằng cách gọi MutateBatchJob.

Java

private String createBatchJob(BatchJobServiceClient batchJobServiceClient, long customerId) {
  BatchJobOperation operation =
      BatchJobOperation.newBuilder().setCreate(BatchJob.newBuilder().build()).build();
  String batchJobResourceName =
      batchJobServiceClient
          .mutateBatchJob(Long.toString(customerId), operation)
          .getResult()
          .getResourceName();
  System.out.printf("Created a mutate job with resource name: '%s'.%n", batchJobResourceName);

  return batchJobResourceName;
}
      

C#

private static string CreateBatchJob(BatchJobServiceClient batchJobService,
    long customerId)
{
    BatchJobOperation operation = new BatchJobOperation()
    {
        Create = new BatchJob()
        {
        }
    };
    string batchJobResourceName =
        batchJobService.MutateBatchJob(customerId.ToString(), operation)
        .Result.ResourceName;
    Console.WriteLine($"Created a batch job with resource name: " +
        $"'{batchJobResourceName}'.");

    return batchJobResourceName;
}
      

PHP

private static function createBatchJob(
    BatchJobServiceClient $batchJobServiceClient,
    int $customerId
): string {
    // Creates a batch job operation to create a new batch job.
    $batchJobOperation = new BatchJobOperation();
    $batchJobOperation->setCreate(new BatchJob());

    // Issues a request to the API and get the batch job's resource name.
    $batchJobResourceName = $batchJobServiceClient->mutateBatchJob(
        MutateBatchJobRequest::build($customerId, $batchJobOperation)
    )->getResult()->getResourceName();
    printf(
        "Created a batch job with resource name: '%s'.%s",
        $batchJobResourceName,
        PHP_EOL
    );
    return $batchJobResourceName;
}
      

Python

def create_batch_job(batch_job_service, customer_id, batch_job_operation):
    """Creates a batch job for the specified customer ID.

    Args:
        batch_job_service: an instance of the BatchJobService message class.
        customer_id: a str of a customer ID.
        batch_job_operation: a BatchJobOperation instance set to "create"

    Returns: a str of a resource name for a batch job.
    """
    try:
        response = batch_job_service.mutate_batch_job(
            customer_id=customer_id, operation=batch_job_operation
        )
        resource_name = response.result.resource_name
        print(f'Created a batch job with resource name "{resource_name}"')
        return resource_name
    except GoogleAdsException as exception:
        handle_googleads_exception(exception)
      

Ruby

def create_batch_job(client, batch_job_service, customer_id)
  # Creates a batch job operation to create a new batch job.
  operation = client.operation.create_resource.batch_job

  # Issues a request to the API and get the batch job's resource name.
  response = batch_job_service.mutate_batch_job(
    customer_id: customer_id,
    operation: operation
  )

  batch_job_resource_name = response.result.resource_name
  puts "Created a batch job with resource name: '#{batch_job_resource_name}'"

  batch_job_resource_name
end
      

Perl

sub create_batch_job {
  my ($batch_job_service, $customer_id) = @_;

  # Create a batch job operation.
  my $batch_job_operation =
    Google::Ads::GoogleAds::V17::Services::BatchJobService::BatchJobOperation->
    new({create => Google::Ads::GoogleAds::V17::Resources::BatchJob->new({})});

  my $batch_job_resource_name = $batch_job_service->mutate({
      customerId => $customer_id,
      operation  => $batch_job_operation
    })->{result}{resourceName};

  printf
    "Created a batch job with resource name: '%s'.\n",
    $batch_job_resource_name;

  return $batch_job_resource_name;
}
      

Tại thời điểm này trong quá trình, status của công việc là PENDING.

Thêm một hoặc nhiều thao tác thay đổi vào tác vụ hàng loạt

Thêm một hoặc nhiều MutateOperation vào công việc hàng loạt được tạo ở bước trước bằng cách gọi AddBatchJobOperations. Chiến lược phát hành đĩa đơn response (phản hồi) sau đó chứa sau:

  • Tổng số hoạt động được thêm vào tính đến nay cho công việc này
  • Mã thông báo trình tự được dùng khi gọi phương thức này để thêm các thao tác khác

Khi bạn gọi AddBatchJobOperations để thêm các thao tác khác, hãy đảm bảo bạn chỉ định các thao tác thu được mã thông báo trình tự trong sequence_token của một yêu cầu. Nếu bạn gọi phương thức sử dụng bất kỳ mã thông báo trình tự nào khác với phương thức đã nhận được trước đó, thì phương thức này dẫn đến lỗi.

sequence_token cũng có sẵn dưới dạng next_add_sequence_token trong số BatchJob để bạn có thể truy xuất sau.

Nếu bạn đang tạo các đối tượng phụ thuộc, chẳng hạn như một chiến dịch hoàn chỉnh bao gồm chiến dịch mới và nhóm quảng cáo, quảng cáo và từ khoá tương ứng, bạn có thể sử dụng mã nhận dạng tạm thời để chỉ định một tên tài nguyên.

Java

private void addAllBatchJobOperations(
    BatchJobServiceClient batchJobServiceClient, long customerId, String batchJobResourceName) {
  AddBatchJobOperationsResponse response =
      batchJobServiceClient.addBatchJobOperations(
          AddBatchJobOperationsRequest.newBuilder()
              .setResourceName(batchJobResourceName)
              .addAllMutateOperations(buildAllOperations(customerId))
              .build());
  System.out.printf(
      "%d mutate operations have been added so far.%n", response.getTotalOperations());

  // You can use this next sequence token for calling addBatchJobOperations() next time.
  System.out.printf(
      "Next sequence token for adding next operations is '%s'.%n",
      response.getNextSequenceToken());
}
      

C#

private static void AddAllBatchJobOperations(BatchJobServiceClient batchJobService,
    long customerId, string batchJobResourceName)
{
    AddBatchJobOperationsResponse response =
        batchJobService.AddBatchJobOperations(
            new AddBatchJobOperationsRequest()
            {
                ResourceName = batchJobResourceName,
                MutateOperations = { BuildAllOperations(customerId) }
            });
    Console.WriteLine($"{response.TotalOperations} mutate operations have been added" +
        $" so far.");

    // You can use this next sequence token for calling AddBatchJobOperations() next time.
    Console.WriteLine($"Next sequence token for adding next operations is " +
        $"'{response.NextSequenceToken}'.");
}
      

PHP

private static function addAllBatchJobOperations(
    BatchJobServiceClient $batchJobServiceClient,
    int $customerId,
    string $batchJobResourceName
): void {
    $response = $batchJobServiceClient->addBatchJobOperations(
        AddBatchJobOperationsRequest::build(
            $batchJobResourceName,
            '',
            self::buildAllOperations($customerId)
        )
    );
    printf(
        "%d mutate operations have been added so far.%s",
        $response->getTotalOperations(),
        PHP_EOL
    );
    // You can use this next sequence token for calling addBatchJobOperations() next time.
    printf(
        "Next sequence token for adding next operations is '%s'.%s",
        $response->getNextSequenceToken(),
        PHP_EOL
    );
}
      

Python

def add_all_batch_job_operations(batch_job_service, operations, resource_name):
    """Adds all mutate operations to the batch job.

    As this is the first time for this batch job, we pass null as a sequence
    token. The response will contain the next sequence token that we can use
    to upload more operations in the future.

    Args:
        batch_job_service: an instance of the BatchJobService message class.
        operations: a list of a mutate operations.
        resource_name: a str of a resource name for a batch job.
    """
    try:
        response = batch_job_service.add_batch_job_operations(
            resource_name=resource_name,
            sequence_token=None,
            mutate_operations=operations,
        )

        print(
            f"{response.total_operations} mutate operations have been "
            "added so far."
        )

        # You can use this next sequence token for calling
        # add_batch_job_operations() next time.
        print(
            "Next sequence token for adding next operations is "
            f"{response.next_sequence_token}"
        )
    except GoogleAdsException as exception:
        handle_googleads_exception(exception)
      

Ruby

def add_all_batch_job_operations(
  client,
  batch_job_service,
  customer_id,
  batch_job_resource_name)
  response = batch_job_service.add_batch_job_operations(
    resource_name: batch_job_resource_name,
    mutate_operations: build_all_operations(client, customer_id),
  )
  puts "#{response.total_operations} mutate operations have been added so far."

  # You can use this next sequence token for calling
  # add_all_batch_job_operations() next time
  puts "Next sequence token for adding next operations is " \
    "'#{response.next_sequence_token}'"
end
      

Perl

sub add_all_batch_job_operations {
  my ($batch_job_service, $customer_id, $batch_job_resource_name) = @_;

  my $add_batch_job_operations_response = $batch_job_service->add_operations({
      resourceName     => $batch_job_resource_name,
      sequenceToken    => undef,
      mutateOperations => build_all_operations($customer_id)});

  printf
    "%d batch operations have been added so far.\n",
    $add_batch_job_operations_response->{totalOperations};

  # You can use this next sequence token for calling add_operations() next time.
  printf
    "Next sequence token for adding next operations is '%s'.\n",
    $add_batch_job_operations_response->{nextSequenceToken};
}
      

Nhấp để xem nội dung của hàm hoạt động xây dựng trong GitHub cho thư viện ứng dụng:

Chạy tác vụ hàng loạt

Sau khi thêm tất cả hoạt động, bạn có thể yêu cầu API Google Ads để chạy lô công việc bằng cách gọi RunBatchJob trên các hoạt động đã tải lên.

Java

private OperationFuture runBatchJob(
    BatchJobServiceClient batchJobServiceClient, String batchJobResourceName) {
  OperationFuture operationResponse =
      batchJobServiceClient.runBatchJobAsync(batchJobResourceName);

  // BEWARE! The above call returns an OperationFuture. The execution of that future depends on
  // the thread pool which is owned by batchJobServiceClient. If you use this future, you *must*
  // keep the service client in scope too.
  // See https://developers.google.com/google-ads/api/docs/client-libs/java/lro for more detail.

  System.out.printf(
      "Mutate job with resource name '%s' has been executed.%n", batchJobResourceName);

  return operationResponse;
}
      

C#

private Operation<Empty, BatchJobMetadata> RunBatchJob(
    BatchJobServiceClient batchJobService, string batchJobResourceName)
{
    Operation<Empty, BatchJobMetadata> operationResponse =
        batchJobService.RunBatchJob(batchJobResourceName);
    Console.WriteLine($"Batch job with resource name '{batchJobResourceName}' has been " +
        $"executed.");

    return operationResponse;
}
      

PHP

private static function runBatchJob(
    BatchJobServiceClient $batchJobServiceClient,
    string $batchJobResourceName
): OperationResponse {
    $operationResponse =
        $batchJobServiceClient->runBatchJob(RunBatchJobRequest::build($batchJobResourceName));
    printf(
        "Batch job with resource name '%s' has been executed.%s",
        $batchJobResourceName,
        PHP_EOL
    );
    return $operationResponse;
}
      

Python

def run_batch_job(batch_job_service, resource_name):
    """Runs the batch job for executing all uploaded mutate operations.

    Args:
        batch_job_service: an instance of the BatchJobService message class.
        resource_name: a str of a resource name for a batch job.

    Returns: a google.api_core.operation.Operation instance.
    """
    try:
        response = batch_job_service.run_batch_job(resource_name=resource_name)
        print(
            f'Batch job with resource name "{resource_name}" has been '
            "executed."
        )
        return response
    except GoogleAdsException as exception:
        handle_googleads_exception(exception)
      

Ruby

def run_batch_job(batch_job_service, batch_job_resource_name)
  operation_response = batch_job_service.run_batch_job(
    resource_name: batch_job_resource_name,
  )
  puts "Batch job with resource name '#{batch_job_resource_name}' " \
    "has been executed."
  operation_response
end
      

Perl

sub run_batch_job {
  my ($batch_job_service, $batch_job_resource_name) = @_;

  my $batch_job_lro =
    $batch_job_service->run({resourceName => $batch_job_resource_name});

  printf
    "Batch job with resource name '%s' has been executed.\n",
    $batch_job_resource_name;

  return $batch_job_lro;
}
      

Phản hồi được trả về là một đối tượng của Operation chạy trong thời gian dài (LRO). LRO chứa siêu dữ liệu của lô của bạn cùng với thông tin về trạng thái công việc.

Thăm dò trạng thái của công việc theo lô cho đến khi hoàn tất

Bước tiếp theo là thăm dò trạng thái của công việc hàng loạt bằng cách sử dụng LRO GetOperation cho đến LRO done hiện là true.

Java

private void pollBatchJob(OperationFuture operationResponse) {
  try {
    operationResponse.get(MAX_TOTAL_POLL_INTERVAL_SECONDS, TimeUnit.SECONDS);
  } catch (InterruptedException | ExecutionException | TimeoutException e) {
    System.err.printf("Failed polling the mutate job. Exception: %s%n", e);
    System.exit(1);
  }
}
      

C#

private static void PollBatchJob(Operation<Empty, BatchJobMetadata> operationResponse)
{
    PollSettings pollSettings = new PollSettings(
        Expiration.FromTimeout(TimeSpan.FromSeconds(MAX_TOTAL_POLL_INTERVAL_SECONDS)),
        TimeSpan.FromSeconds(1));
    operationResponse.PollUntilCompleted(pollSettings);
}
      

PHP

private static function pollBatchJob(OperationResponse $operationResponse): void
{
    $operationResponse->pollUntilComplete([
        'initialPollDelayMillis' => self::POLL_FREQUENCY_SECONDS * 1000,
        'totalPollTimeoutMillis' => self::MAX_TOTAL_POLL_INTERVAL_SECONDS * 1000
    ]);
}
      

Python

def poll_batch_job(operations_response, event):
    """Polls the server until the batch job execution finishes.

    Sets the initial poll delay time and the total time to wait before time-out.

    Args:
        operations_response: a google.api_core.operation.Operation instance.
        event: an instance of asyncio.Event to invoke once the operations have
            completed, alerting the awaiting calling code that it can proceed.
    """
    loop = asyncio.get_event_loop()

    def done_callback(future):
        # The operations_response object will call callbacks from a daemon
        # thread so we must use a threadsafe method of setting the event here
        # otherwise it will not trigger the awaiting code.
        loop.call_soon_threadsafe(event.set)

    # operations_response represents a Long-Running Operation or LRO. The class
    # provides an interface for polling the API to check when the operation is
    # complete. Below we use the asynchronous interface, but there's also a
    # synchronous interface that uses the Operation.result method.
    # See: https://googleapis.dev/python/google-api-core/latest/operation.html
    operations_response.add_done_callback(done_callback)
      

Ruby

def poll_batch_job(operation_response)
  operation_response.wait_until_done!
end
      

Perl

sub poll_batch_job {
  my ($operation_service, $batch_job_lro) = @_;

  $operation_service->poll_until_done({
    name                 => $batch_job_lro->{name},
    pollFrequencySeconds => POLL_FREQUENCY_SECONDS,
    pollTimeoutSeconds   => POLL_TIMEOUT_SECONDS
  });
}
      

Liệt kê tất cả kết quả công việc hàng loạt

Khi tất cả các công việc theo lô của bạn hoàn tất, bạn có thể liệt kê kết quả của các công việc đó bằng cách sử dụng ListBatchJobResults đến in trạng thái và phản hồi của họ:

Java

private void fetchAndPrintResults(
    BatchJobServiceClient batchJobServiceClient, String batchJobResourceName) {
  System.out.printf(
      "Mutate job with resource name '%s' has finished. Now, printing its results...%n",
      batchJobResourceName);
  // Gets all the results from running mutate job and prints their information.
  ListBatchJobResultsPagedResponse batchJobResults =
      batchJobServiceClient.listBatchJobResults(
          ListBatchJobResultsRequest.newBuilder()
              .setResourceName(batchJobResourceName)
              .setPageSize(PAGE_SIZE)
              .build());
  for (BatchJobResult batchJobResult : batchJobResults.iterateAll()) {
    System.out.printf(
        "Mutate job #%d has a status '%s' and response of type '%s'.%n",
        batchJobResult.getOperationIndex(),
        batchJobResult.getStatus().getMessage().isEmpty()
            ? "N/A"
            : batchJobResult.getStatus().getMessage(),
        batchJobResult
                .getMutateOperationResponse()
                .getResponseCase()
                .equals(ResponseCase.RESPONSE_NOT_SET)
            ? "N/A"
            : batchJobResult.getMutateOperationResponse().getResponseCase());
  }
}
      

C#

private static void FetchAndPrintResults(BatchJobServiceClient batchJobService,
    string batchJobResourceName)
{
    Console.WriteLine($"batch job with resource name '{batchJobResourceName}' has " +
        $"finished. Now, printing its results...");

    ListBatchJobResultsRequest request = new ListBatchJobResultsRequest()
    {
        ResourceName = batchJobResourceName,
        PageSize = PAGE_SIZE,
    };
    ListBatchJobResultsResponse resp = new ListBatchJobResultsResponse();
    // Gets all the results from running batch job and prints their information.
    foreach (BatchJobResult batchJobResult in
        batchJobService.ListBatchJobResults(request))
    {
        if (!batchJobResult.IsFailed)
        {
            Console.WriteLine($"batch job result #{batchJobResult.OperationIndex} is " +
                $"successful and response is of type " +
                $"'{batchJobResult.MutateOperationResponse.ResponseCase}'.");
        }
        else
        {
            Console.WriteLine($"batch job result #{batchJobResult.OperationIndex} " +
                $"failed with error message {batchJobResult.Status.Message}.");

            foreach (GoogleAdsError error in batchJobResult.Failure.Errors)
            {
                Console.WriteLine($"Error found: {error}.");
            }
        }
    }
}
      

PHP

private static function fetchAndPrintResults(
    BatchJobServiceClient $batchJobServiceClient,
    string $batchJobResourceName
): void {
    printf(
        "Batch job with resource name '%s' has finished. Now, printing its results...%s",
        $batchJobResourceName,
        PHP_EOL
    );
    // Gets all the results from running batch job and print their information.
    $batchJobResults = $batchJobServiceClient->listBatchJobResults(
        ListBatchJobResultsRequest::build($batchJobResourceName)->setPageSize(self::PAGE_SIZE)
    );
    foreach ($batchJobResults->iterateAllElements() as $batchJobResult) {
        /** @var BatchJobResult $batchJobResult */
        printf(
            "Batch job #%d has a status '%s' and response of type '%s'.%s",
            $batchJobResult->getOperationIndex(),
            $batchJobResult->getStatus()
                ? $batchJobResult->getStatus()->getMessage() : 'N/A',
            $batchJobResult->getMutateOperationResponse()
                ? $batchJobResult->getMutateOperationResponse()->getResponse()
                : 'N/A',
            PHP_EOL
        );
    }
}
      

Python

def fetch_and_print_results(client, batch_job_service, resource_name):
    """Prints all the results from running the batch job.

    Args:
        client: an initialized GoogleAdsClient instance.
        batch_job_service: an instance of the BatchJobService message class.
        resource_name: a str of a resource name for a batch job.
    """
    print(
        f'Batch job with resource name "{resource_name}" has finished. '
        "Now, printing its results..."
    )

    list_results_request = client.get_type("ListBatchJobResultsRequest")
    list_results_request.resource_name = resource_name
    list_results_request.page_size = 1000
    # Gets all the results from running batch job and prints their information.
    batch_job_results = batch_job_service.list_batch_job_results(
        request=list_results_request
    )

    for batch_job_result in batch_job_results:
        status = batch_job_result.status.message
        status = status if status else "N/A"
        result = batch_job_result.mutate_operation_response
        result = result or "N/A"
        print(
            f"Batch job #{batch_job_result.operation_index} "
            f'has a status "{status}" and response type "{result}"'
        )
      

Ruby

def fetch_and_print_results(batch_job_service, batch_job_resource_name)
  puts "Batch job with resource name '#{batch_job_resource_name}' has " \
    "finished. Now, printing its results..." \

  # Gets all the results from running batch job and print their information.
  batch_job_results = batch_job_service.list_batch_job_results(
    resource_name: batch_job_resource_name,
    page_size: PAGE_SIZE,
  )
  batch_job_results.each do |result|
    puts "Batch job ##{result.operation_index} has a status " \
      "#{result.status ? result.status.message : 'N/A'} and response of type " \
      "#{result.mutate_operation_response ? result.mutate_operation_response.response : 'N/A'}"
  end
end
      

Perl

sub fetch_and_print_results {
  my ($batch_job_service, $batch_job_resource_name) = @_;

  printf "Batch job with resource name '%s' has finished. " .
    "Now, printing its results...\n", $batch_job_resource_name;

  # Get all the results from running batch job and print their information.
  my $list_batch_job_results_response = $batch_job_service->list_results({
    resourceName => $batch_job_resource_name,
    pageSize     => PAGE_SIZE
  });

  foreach my $batch_job_result (@{$list_batch_job_results_response->{results}})
  {
    printf
      "Batch job #%d has a status '%s' and response of type '%s'.\n",
      $batch_job_result->{operationIndex},
      $batch_job_result->{status} ? $batch_job_result->{status}{message}
      : "N/A",
      $batch_job_result->{mutateOperationResponse}
      ? [keys %{$batch_job_result->{mutateOperationResponse}}]->[0]
      : "N/A";
  }
}
      

Nếu thao tác tương ứng thành công, response / mutate_operation_response chứa kết quả với resource_name của nó. Ngoài ra, nguồn lực của kết quả chứa tài nguyên đã sửa đổi với tất cả các trường có thể thay đổi được điền sẵn nếu response_content_type được đặt thành MUTABLE_RESOURCE.

Nếu thao tác tương ứng gây ra lỗi và không thể được hoàn tất, mutate_operation_response trường là null.

Trường status của BatchJobResult chứa thông tin chi tiết về lỗi của từng thao tác không thành công.

Xử lý lỗi

BatchJobService tự động thử lại các thao tác không thành công do lỗi tạm thời lỗi, tuy nhiên, không phải tất cả các trường hợp thất bại đều có thể tránh được. Thao tác không thành công do lỗi xác thực có thể được khắc phục và gửi lại trong hàng loạt. Bạn có thể thử lại các thao tác đã bị huỷ bằng cách thêm chúng vào một công việc hàng loạt.