As etapas para usar o processamento em lote são as seguintes:
Criar um job em lote
Para criar um recurso BatchJob, chame
MutateBatchJob. Ao criar o objeto
BatchJob, é possível definir
metadata.execution_limit_seconds como um número inteiro positivo para
configurar um limite superior aproximado, em segundos, de quanto tempo o job pode ser executado
antes de ser cancelado automaticamente (consulte
Orientações adicionais de uso).
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::V26::Services::BatchJobService::BatchJobOperation-> new({create => Google::Ads::GoogleAds::V26::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, # 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 "login-customer-id: ${MANAGER_CUSTOMER_ID}" \ --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \ --data @- <<EOF { "operation": { "create": {} } } EOF
Nesse ponto do processo, o status do job é
PENDING.
Adicionar operações de mutação ao job em lote
Adicione um ou mais objetos MutateOperation ao job em lote
criado na etapa anterior chamando
AddBatchJobOperations. A
resposta contém o seguinte:
total_operations: número total de operações adicionadas até o momento para esse job.next_sequence_token: token de sequência a ser transmitido no camposequence_tokenao chamar esse método novamente para adicionar mais operações.
A primeira solicitação AddBatchJobOperations de um job em lote precisa omitir sequence_token. Ao chamar
AddBatchJobOperations novamente para adicionar mais
operações, especifique o token de sequência recebido anteriormente no
campo sequence_token da
solicitação. Chamar o método com uma lista
mutate_operations vazia retorna um erro
BatchJobError.EMPTY_OPERATIONS, chamá-lo com qualquer
token de sequência diferente do obtido anteriormente retorna um erro
BatchJobError.INVALID_SEQUENCE_TOKEN, e
tentar adicionar operações após o início da execução do job retorna um erro
BatchJobError.CANNOT_MODIFY_JOB_AFTER_JOB_STARTS_RUNNING.
Enquanto o status do job em lote é
PENDING, sequence_token também está disponível como
next_add_sequence_token no recurso
BatchJob, que pode ser recuperado
mais tarde.
Se você estiver criando objetos dependentes, como uma campanha completa que consiste em uma nova campanha e os grupos de anúncios, anúncios e palavras-chave correspondentes, use IDs temporários para especificar um nome de recurso.
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, # 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 "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
Clique para ver o conteúdo da função de operações de build no GitHub para sua biblioteca de cliente:
Java
buildAllOperations()
C#
BuildAllOperations()
PHP
buildAllOperations()
Python
build_all_operations()
Ruby
build_all_operations()
Perl
build_all_operations
Executar o job em lote
Depois de adicionar todas as operações, você pode solicitar que a API Google Ads execute o job em lote chamando RunBatchJob nas operações enviadas.
Chamar RunBatchJob depois que o job já tiver começado a ser executado
retorna um erro
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, # 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/v${API_VERSION}/${BATCH_JOB_RESOURCE_NAME}:run" \ --header "Content-Type: application/json" \ --header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \ --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \ --data @- <<EOF {} EOF
A resposta retornada é um objeto Operation de longa duração que contém os metadados do job em lote e informações sobre o status do job.
Pesquise o status do job em lote até que ele seja concluído
Consulte o status do job em lote com o
método Operations.GetOperation no
serviço google.longrunning.Operations (separado de
BatchJobService) até que o
campo Operation.done seja true. Na API Google Ads,
Operations.GetOperation é o único método compatível com
google.longrunning.Operations (WaitOperation,
ListOperations, CancelOperation e DeleteOperation retornam
UNIMPLEMENTED):
- Bibliotecas de cliente: chame o auxiliar de sondagem ou de espera no wrapper de operação de longa duração retornado por
RunBatchJob(ou transmita o nome da operação paraOperationService::poll_until_donena biblioteca de cliente Perl baseada em REST), que sondaOperations.GetOperationaté que a operação seja concluída (ou até que o tempo limite de sondagem configurado expire; em Perl, verifique sedoneétrueno hash retornado antes de listar os resultados). No Java, mantenhaBatchJobServiceClientaberto até queOperationFuturetermine. - REST: envie uma solicitação HTTP
GETparahttps://googleads.googleapis.com/v26/OPERATION_NAME(em queOPERATION_NAMEé o nome do recursoOperation.name, formatado comocustomers/CUSTOMER_ID/operations/OPERATION_ID) com espera exponencial até que o campoOperation.donesejatrue.
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, # 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 "login-customer-id: ${MANAGER_CUSTOMER_ID}" \ --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
Como alternativa, consulte o recurso batch_job com o método
GoogleAdsService.Search ou
GoogleAdsService.SearchStream, selecionando
batch_job.status e subcampos específicos de
BatchJobMetadata (como
batch_job.metadata.estimated_completion_ratio e
batch_job.metadata.executed_operation_count) até que
batch_job.status seja DONE. Cada
Operations.GetOperation ou solicitação GAQL não paginada
conta como uma operação para sua cota diária da API. Quando você monitora
vários jobs em lote simultâneos, uma única consulta GAQL (WHERE batch_job.id IN
(...) ou WHERE batch_job.status = 'RUNNING') verifica todos eles em uma
solicitação, em vez de consultar cada operação de longa duração individualmente.
Quando Operation.done é true, a operação de longa duração
retorna uma resposta vazia sem erros por operação. Chame
ListBatchJobResults para inspecionar os resultados de operações
individuais.
Recuperar uma operação de longa duração
Se o aplicativo pesquisar jobs em lote de um processo separado ou precisar retomar
a pesquisa após uma reinicialização, recupere o nome da operação de longa duração usando
GoogleAdsService.Search ou
GoogleAdsService.SearchStream:
Consulte o recurso
batch_jobpara ler o campolong_running_operation:SELECT batch_job.id, batch_job.status, batch_job.long_running_operation FROM batch_job WHERE batch_job.id = BATCH_JOB_IDSubstitua
BATCH_JOB_IDpelo ID numérico do job em lote.Verifique se
batch_job.statuséRUNNINGouDONE(long_running_operationnão é definido enquanto o job éPENDINGporque não há operação de longa duração até queRunBatchJobseja chamado) e leia a stringlong_running_operationdo objetoBatchJobretornado.Pesquise ou inspecione a operação usando essa string de nome:
- Bibliotecas de cliente: receba o cliente de operações do seu cliente
BatchJobService(getOperationsClient()em Java e PHP,RunBatchJobOperationsClientem C#,transport.operations_clientem Python,operations_clientem Ruby ou$api_client->OperationService()em Perl) para que a autenticação do Google Ads e os cabeçalhoslogin-customer-idsejam configurados automaticamente, em vez de instanciar umOperationsClientindependente. ChameOperations.GetOperation(ouOperationService::getem Perl) para uma única verificação de status ou use o nome da operação para retomar um wrapper de operação de longa duração e pesquisar até a conclusão (runBatchJobOperationCallable().resumeFutureCallem Java,PollOnceRunBatchJobem C#,resumeOperationem PHP,google.api_core.operation.from_gapicnoOperationretornado porget_operationem Python,wait_until_done!noGapic::Operationretornado porget_operationem Ruby ounameemOperationService::poll_until_doneem Perl). - REST: envie uma solicitação HTTP
GETparahttps://googleads.googleapis.com/v26/OPERATION_NAME.
Como
OPERATION_NAMEcodifica a versão principal da API em que oBatchJobfoi criado,Operations.GetOperation(mesmo pelo endpoint RESTv26ativo) falha com um erroRequestError.UNSUPPORTED_VERSIONse essa versão foi descontinuada. Consultebatch_job.statusdiretamente comGoogleAdsService.- Bibliotecas de cliente: receba o cliente de operações do seu cliente
Entender os metadados da operação
Quando você pesquisa a operação de longa duração ou consulta o recurso
batch_job,
BatchJobMetadata fornece detalhes sobre o progresso do job
em lote:
creation_date_time: o carimbo de data/hora de quando o job em lote foi criado.start_date_time: o carimbo de data/hora de quando o job em lote começou a ser executado (preenchido quando você consultabatch_job.metadata.start_date_timecomGoogleAdsService; omitido deOperation.metadataemRunBatchJobeOperations.GetOperation).completion_date_time: o carimbo de data/hora de quando o job em lote foi concluído (presente apenas se o job estiver concluído).estimated_completion_ratio: uma estimativa da fração do job (de 0,0 a 1,0) que foi concluída.operation_count: o número total de operações no job em lote.executed_operation_count: o número de operações executadas até o momento.execution_limit_seconds: o limite superior aproximado, em segundos, de quanto tempo o job em lote pode ser executado antes de ser cancelado (preenchido quando você consultabatch_job.metadata.execution_limit_secondscomGoogleAdsServicese um limite positivo foi definido na criação do job; omitido deOperation.metadataemRunBatchJobeOperations.GetOperation).
Esses campos, especialmente estimated_completion_ratio
e as contagens de operações, podem ajudar você a avaliar o progresso do job, estimar
o tempo restante e ajustar a frequência de sondagem. Por exemplo, você pode fazer sondagens
com menos frequência quando o estimated_completion_ratio
estiver baixo e com mais frequência quando ele se aproximar de 1, 0.
Listar todos os resultados de jobs em lote
Quando o job em lote terminar, chame
ListBatchJobResults para recuperar o status e
a resposta de cada operação no job:
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}"
No ListBatchJobResultsRequest, o campo page_size assume como padrão o valor máximo de 1000 se for omitido ou definido como 0. Definir page_size como um valor maior que 1000 ou menor que 0 retorna um erro BatchJobError.INVALID_PAGE_SIZE.
Cada BatchJobResult identifica a operação correspondente
usando operation_index, o índice baseado em 0 do
MutateOperation enviado no job em lote.
- Operação bem-sucedida:
mutate_operation_responseé preenchido (oresponsecontém oresource_namedo recurso modificado, além de todos os campos mutáveis seresponse_content_typeestiver definido comoMUTABLE_RESOURCE), estatusnão está definido. - Operação com falha (ou não executada):
mutate_operation_responsenão está definido, estatuscontém os detalhes do erro da operação.
Cancelar ou remover um job em lote
A forma de interromper ou descartar um job em lote depende de
RunBatchJob ter sido chamado:
- Antes de chamar
RunBatchJobstatus: enquanto o job em lote estiver emPENDING, você poderá descartá-lo chamandoMutateBatchJobcomBatchJobOperation.remove. Chamarremovedepois que o job começa a ser executado retorna um erroBatchJobError.CAN_ONLY_REMOVE_PENDING_JOB. - Depois de chamar
RunBatchJob: não é possível cancelar manualmente um job em lote em execução (Operations.CancelOperationnão está implementado na API Google Ads e retornaUNIMPLEMENTED). Para limitar o tempo de execução de modo que um job seja cancelado automaticamente se demorar muito, definametadata.execution_limit_secondscomo um número inteiro positivo (um limite superior aproximado) ao criar o job emMutateBatchJob. Como as operações padrão em um job em lote são executadas com a falha parcial ativada (as operações em sublotes atômicos são revertidas juntas), o cancelamento automático não reverte as operações que já foram concluídas. Depois que ostatusde um job cancelado (ou interrompido) faz a transição paraDONE, a chamada deListBatchJobResultsretorna entradasBatchJobResultpara o prefixo executado (operation_index<executed_operation_count) com os resultados de execução individuais, seguidos por entradasBatchJobResultpara todas as operações não executadas restantes (operation_indexdeexecuted_operation_countaoperation_count- 1) commutate_operation_responsenão definido estatusdefinido comoABORTEDcomInternalError.INTERNAL_ERRORquando cancelado devido aexecution_limit_seconds(ou ao status de erro no nível do job se o job foi interrompido devido a um erro de execução fatal).
Tratamento de erros
O BatchJobService executa operações padrão com a
falha parcial ativada (as operações bem-sucedidas são confirmadas mesmo
que outras operações no mesmo job falhem, exceto em
sublotes atômicos) e repete automaticamente
as operações que falham devido a erros temporários. No entanto, nem todos os cenários de falha
podem ser evitados. As operações que falharam devido a erros de validação podem ser corrigidas e
reenviadas em um novo job em lote. Da mesma forma, quando um job em lote é
cancelado ou interrompido antes de concluir todas as operações, é possível
reenviar as operações não executadas (operation_index
>= executed_operation_count) junto com as operações
com falha do prefixo executado em um novo job em lote.