Các bước sử dụng tính năng xử lý hàng loạt như sau:
Tạo một lô công việc mới
Để tạo tài nguyên BatchJob, hãy gọi MutateBatchJob. Khi tạo đối tượng BatchJob, bạn có thể tuỳ ý đặt metadata.execution_limit_seconds để định cấu hình giới hạn trên (tính bằng giây) về thời gian mà công việc có thể chạy trước khi tự động bị huỷ (xem phần Hướng dẫn bổ sung về cách sử dụng).
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: BatchJobServiceClient, customer_id: str, batch_job_operation: BatchJobOperation, ) -> str: """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: MutateBatchJobResponse = batch_job_service.mutate_batch_job( customer_id=customer_id, operation=batch_job_operation ) resource_name: str = 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) # This line will likely not be reached due to sys.exit(1) in handle_googleads_exception # but to satisfy the type checker, we add a return statement. return "" # Or raise an 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::V25::Services::BatchJobService::BatchJobOperation-> new({create => Google::Ads::GoogleAds::V25::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; }
curl
# Creates a batch job. # # Variables: # API_VERSION, # CUSTOMER_ID, # DEVELOPER_TOKEN, # MANAGER_CUSTOMER_ID, # OAUTH2_ACCESS_TOKEN: # See https://developers.google.com/google-ads/api/rest/auth#request_headers # for details. curl -f --request POST \ "https://googleads.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}/batchJobs:mutate" \ --header "Content-Type: application/json" \ --header "developer-token: ${DEVELOPER_TOKEN}" \ --header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \ --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \ --data @- <<EOF { "operation": { "create": {} } } EOF
Tại thời điểm này trong quy trình, status của công việc là PENDING.
Thêm các thao tác biến đổi vào lệnh hàng loạt
Thêm một hoặc nhiều đối tượng MutateOperation vào lô công việc được tạo ở bước trước bằng cách gọi AddBatchJobOperations. Phản hồi sau đó sẽ chứa những thông tin sau:
total_operations: Tổng số thao tác đã thêm cho đến nay cho công việc này.next_sequence_token: Mã thông báo chuỗi để truyền vào trườngsequence_tokenkhi gọi lại phương thức này để thêm các thao tác khác.
Yêu cầu AddBatchJobOperations đầu tiên cho một công việc hàng loạt phải bỏ qua sequence_token. Khi bạn gọi lại AddBatchJobOperations để thêm các thao tác khác, hãy chỉ định mã thông báo chuỗi đã nhận được trước đó trong trường sequence_token của request. Việc gọi phương thức bằng danh sách mutate_operations trống sẽ trả về lỗi BatchJobError.EMPTY_OPERATIONS, việc gọi phương thức bằng bất kỳ mã thông báo chuỗi nào khác ngoài mã thông báo đã nhận trước đó sẽ trả về lỗi BatchJobError.INVALID_SEQUENCE_TOKEN và việc cố gắng thêm các thao tác sau khi công việc bắt đầu chạy sẽ trả về lỗi BatchJobError.CANNOT_MODIFY_JOB_AFTER_JOB_STARTS_RUNNING.
Trong khi status của công việc hàng loạt là PENDING, sequence_token cũng có sẵn dưới dạng next_add_sequence_token trên tài nguyên BatchJob mà bạn có thể truy xuất sau này.
Nếu đ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à các 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 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: BatchJobServiceClient, operations: List[MutateOperation], resource_name: str, ) -> None: """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: AddBatchJobOperationsResponse = ( batch_job_service.add_batch_job_operations( resource_name=resource_name, sequence_token=None, # type: ignore 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}; }
curl
# Adds operations to a batch job. # # Variables: # API_VERSION, # CUSTOMER_ID, # DEVELOPER_TOKEN, # MANAGER_CUSTOMER_ID, # OAUTH2_ACCESS_TOKEN: # See https://developers.google.com/google-ads/api/rest/auth#request_headers # for details. # BATCH_JOB_RESOURCE_NAME: # The resource name of the batch job to which the operations should be added # as returned by the previous step. curl -f --request POST \ "https://googleads.googleapis.com/v${API_VERSION}/${BATCH_JOB_RESOURCE_NAME}:addOperations" \ --header "Content-Type: application/json" \ --header "developer-token: ${DEVELOPER_TOKEN}" \ --header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \ --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \ --data @- <<EOF { "mutateOperations": [ { "campaignBudgetOperation": { "create": { "resourceName": "customers/${CUSTOMER_ID}/campaignBudgets/-1", "name": "batch job budget #${RANDOM}", "deliveryMethod": "STANDARD", "amountMicros": 5000000 } } }, { "campaignOperation": { "create": { "advertisingChannelType": "SEARCH", "status": "PAUSED", "name": "batch job campaign #${RANDOM}", "campaignBudget": "customers/${CUSTOMER_ID}/campaignBudgets/-1", "resourceName": "customers/${CUSTOMER_ID}/campaigns/-2", "manualCpc": { } } }, } ] } EOF
Nhấp để xem nội dung của hàm thao tác bản dựng trong GitHub cho thư viện ứng dụng của bạn:
Java
buildAllOperations()
C#
BuildAllOperations()
PHP
buildAllOperations()
Python
build_all_operations()
Ruby
build_all_operations()
Perl
build_all_operations
Chạy công việc theo lô
Sau khi thêm tất cả các thao tác, bạn có thể yêu cầu Google Ads API chạy lô công việc bằng cách gọi RunBatchJob trên các thao tác đã tải lên.
Việc gọi RunBatchJob sau khi công việc đã bắt đầu chạy sẽ trả về lỗi BatchJobError.CANNOT_MODIFY_JOB_AFTER_JOB_STARTS_RUNNING.
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: BatchJobServiceClient, resource_name: str ) -> Operation: """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: Operation = 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) # This line will likely not be reached due to sys.exit(1) in handle_googleads_exception # but to satisfy the type checker, we add a return statement. # In a real application, you might want to return a dummy Operation or raise an error. return Operation( op_type_name="type.googleapis.com/google.protobuf.Empty", complete=True, done_callbacks=[], metadata_type=None, result_type=None, ) # type: ignore
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; }
curl
# Runs a batch job. # # Variables: # API_VERSION, # CUSTOMER_ID, # DEVELOPER_TOKEN, # MANAGER_CUSTOMER_ID, # OAUTH2_ACCESS_TOKEN: # See https://developers.google.com/google-ads/api/rest/auth#request_headers # for details. # BATCH_JOB_RESOURCE_NAME: # The resource name of the batch job to run as returned by the previous step. curl -f --request POST \ "https://googleads.googleapis.com/v19/${BATCH_JOB_RESOURCE_NAME}:run" \ --header "Content-Type: application/json" \ --header "developer-token: ${DEVELOPER_TOKEN}" \ --header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \ --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \ --data @- <<EOF {} EOF
Phản hồi được trả về là một đối tượng Operation (LRO) chạy trong thời gian dài. LRO chứa siêu dữ liệu của công việc hàng loạt cùng với thông tin về trạng thái công việc.
Theo dõi trạng thái của lô công việc 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 GetOperation của LRO cho đến khi giá trị done của LRO 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: Operation, event: asyncio.Event ) -> None: """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.AbstractEventLoop = asyncio.get_event_loop() def done_callback(future: Coroutine[Any, Any, Any]) -> None: # 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) # type: ignore
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 }); }
curl
# Gets the status of a batch job. # # Variables: # API_VERSION, # CUSTOMER_ID, # DEVELOPER_TOKEN, # MANAGER_CUSTOMER_ID, # OAUTH2_ACCESS_TOKEN: # See https://developers.google.com/google-ads/api/rest/auth#request_headers # for details. # BATCH_JOB_OPERATION_NAME: # The operation name of the running batch job as returned by the previous # step. curl -f --request GET \ "https://googleads.googleapis.com/v${API_VERSION}/${BATCH_JOB_OPERATION_NAME}" \ --header "Content-Type: application/json" \ --header "developer-token: ${DEVELOPER_TOKEN}" \ --header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \ --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
Truy xuất một thao tác hiện có diễn ra trong thời gian dài
Nếu ứng dụng của bạn thăm dò các công việc hàng loạt từ một quy trình riêng biệt hoặc cần tiếp tục thăm dò sau khi khởi động lại, bạn có thể truy xuất tên của thao tác diễn ra trong thời gian dài bằng cách sử dụng GoogleAdsService.Search hoặc GoogleAdsService.SearchStream:
Truy vấn tài nguyên
batch_jobđể đọc trườnglong_running_operationcủa tài nguyên đó:SELECT batch_job.id, batch_job.status, batch_job.long_running_operation FROM batch_job WHERE batch_job.id = BATCH_JOB_IDXác minh rằng
batch_job.statuslàRUNNINGhoặcDONE(long_running_operationchỉ được điền sau khiRunBatchJobđược gọi và không được đặt trong khi công việc đang ở trạng tháiPENDING), đồng thời đọc chuỗilong_running_operationtừ đối tượngBatchJobđược trả về.Truyền chuỗi tên thao tác đó đến
GetOperationtrênOperationsClientcủa thư viện ứng dụng để kiểm tra hoặc tiếp tục thăm dòOperation.
Tìm hiểu siêu dữ liệu về thao tác
Khi bạn thăm dò hoạt động diễn ra trong thời gian dài, trường metadata trong phản hồi Operation sẽ cung cấp thêm thông tin chi tiết về tiến trình của công việc hàng loạt. Trường này chứa một đối tượng BatchJobMetadata. Các lĩnh vực phụ chính bao gồm:
creation_date_time: Dấu thời gian khi lệnh hàng loạt được tạo.start_date_time: Dấu thời gian khi lệnh hàng loạt bắt đầu chạy.completion_date_time: Dấu thời gian khi công việc hàng loạt hoàn tất (chỉ xuất hiện nếu công việc đã hoàn tất).estimated_completion_ratio: Ước tính tỷ lệ phần trăm công việc đã hoàn thành (từ 0 đến 1).operation_count: Tổng số thao tác trong công việc hàng loạt.executed_operation_count: Số lượng thao tác đã được thực thi cho đến thời điểm hiện tại.execution_limit_seconds: Giới hạn trên gần đúng (tính bằng giây) cho thời gian chạy của lệnh xử lý hàng loạt trước khi bị huỷ.
Những trường này, đặc biệt là estimated_completion_ratio và số lượng thao tác, có thể giúp bạn đánh giá tiến trình của công việc, ước tính thời gian còn lại và điều chỉnh tần suất thăm dò. Ví dụ: bạn có thể thăm dò ý kiến ít thường xuyên hơn khi estimated_completion_ratio ở mức thấp và thường xuyên hơn khi chỉ số này tiến gần đến 1.0.
Liệt kê tất cả kết quả của lệnh hàng loạt
Khi tất cả các lệnh hàng loạt của bạn hoàn tất, hãy dùng ListBatchJobResults để liệt kê kết quả của các lệnh đó, đồng thời in trạng thái và phản hồi của các lệnh đó:
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: GoogleAdsClient, batch_job_service: BatchJobServiceClient, resource_name: str, ) -> None: """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: ListBatchJobResultsRequest = 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: ListBatchJobResultsResponse = ( batch_job_service.list_batch_job_results(request=list_results_request) ) for batch_job_result in batch_job_results: status: str = batch_job_result.status.message status = status if status else "N/A" result: Any = 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"; } }
curl
# Gets the results of a batch job. # # Variables: # API_VERSION, # CUSTOMER_ID, # MANAGER_CUSTOMER_ID, # OAUTH2_ACCESS_TOKEN: # See https://developers.google.com/google-ads/api/rest/auth#request_headers # for details. # BATCH_JOB_RESOURCE_NAME: # The operation name of the running batch job as returned by the previous # step. curl -f --request GET \ "https://googleads.googleapis.com/v${API_VERSION}/${BATCH_JOB_RESOURCE_NAME}:listResults?pageSize=1000" \ --header "Content-Type: application/json" \ --header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \ --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}"
Trong ListBatchJobResultsRequest, trường page_size mặc định là giá trị tối đa của 1000 nếu bị bỏ qua hoặc đặt thành 0. Việc đặt page_size thành một giá trị lớn hơn 1000 hoặc nhỏ hơn 0 sẽ trả về lỗi BatchJobError.INVALID_PAGE_SIZE.
Mỗi BatchJobResult xác định thao tác tương ứng bằng cách sử dụng operation_index, chỉ mục dựa trên 0 của MutateOperation đã tải lên trong công việc hàng loạt.
- Thao tác thành công:
mutate_operation_responseđược điền sẵn (responsechứaresource_namecủa tài nguyên đã được sửa đổi, cộng với tất cả các trường có thể thay đổi nếuresponse_content_typeđược đặt thànhMUTABLE_RESOURCE) vàstatuskhông được đặt. - Thao tác không thành công (hoặc chưa thực hiện):
mutate_operation_responsechưa được đặt vàstatuschứa thông tin chi tiết về lỗi cho thao tác.
Huỷ hoặc xoá một công việc hàng loạt
Cách bạn dừng hoặc loại bỏ một công việc hàng loạt phụ thuộc vào việc RunBatchJob đã được gọi hay chưa:
- Trước khi gọi
RunBatchJob: Trong khistatuscủa công việc làPENDING, bạn có thể loại bỏ công việc hàng loạt bằng cách gọiMutateBatchJobbằngBatchJobOperation.remove. Việc gọiremovesau khi công việc bắt đầu chạy sẽ trả về lỗiBatchJobError.CAN_ONLY_REMOVE_PENDING_JOB. - Sau khi gọi
RunBatchJob: Khi một thao tác diễn ra trong thời gian dài tồn tại, bạn có thể thử huỷ thao tác hàng loạt đang chạy bằng cách gọiCancelOperationtrên thao tác diễn ra trong thời gian dài. Vì các thao tác tiêu chuẩn trong một lô công việc thực thi khi bật lỗi một phần (các thao tác trong lô con nguyên tử được khôi phục cùng nhau), nên việc huỷ một lô công việc sẽ không khôi phục các thao tác đã hoàn tất trước khi lệnh huỷ có hiệu lực. Sau khistatuscủa một công việc đã huỷ (hoặc bị huỷ) chuyển sangDONE, việc gọiListBatchJobResultssẽ trả về các mụcBatchJobResultcho tiền tố đã thực thi (operation_index<executed_operation_count) cùng với kết quả thực thi riêng lẻ, tiếp theo là các mụcBatchJobResultcho tất cả các thao tác chưa thực thi còn lại (operation_indextừexecuted_operation_countđếnoperation_count- 1) vớimutate_operation_responsechưa đặt vàstatusđược điền sẵn trạng thái lỗi ở cấp độ công việc (hoặcInternalError.INTERNAL_ERROR).
Xử lý lỗi
BatchJobService thực thi các thao tác tiêu chuẩn khi bật lỗi một phần (các thao tác thành công sẽ cam kết ngay cả khi các thao tác khác trong cùng một công việc không thành công, ngoại trừ trong các lô con nguyên tử) và tự động thử lại các thao tác không thành công do lỗi tạm thời. Tuy nhiên, không phải trường hợp thất bại nào cũng có thể tránh được. Bạn có thể sửa các thao tác không thành công do lỗi xác thực và gửi lại trong một lô công việc mới. Tương tự, khi một lô công việc bị huỷ hoặc bị gián đoạn trước khi hoàn tất tất cả các thao tác, bạn có thể gửi lại các thao tác chưa thực hiện (operation_index
>= executed_operation_count) cùng với mọi thao tác không thành công từ tiền tố đã thực hiện trong một lô công việc mới.