Pour utiliser le traitement par lot, procédez comme suit :
Créer un job par lot
Pour créer une ressource BatchJob, appelez MutateBatchJob. Lorsque vous créez l'objet BatchJob, vous pouvez éventuellement définir metadata.execution_limit_seconds sur un entier positif pour configurer une limite supérieure approximative, en secondes, de la durée d'exécution du job avant son annulation automatique (voir Conseils d'utilisation supplémentaires).
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
À ce stade du processus, l'status du job est PENDING.
Ajouter des opérations de mutation au job par lot
Ajoutez un ou plusieurs objets MutateOperation au job par lot créé à l'étape précédente en appelant AddBatchJobOperations. La réponse contient alors les éléments suivants :
total_operations: nombre total d'opérations ajoutées jusqu'à présent pour ce job.next_sequence_token: jeton de séquence à transmettre dans le champsequence_tokenlorsque vous appelez à nouveau cette méthode pour ajouter d'autres opérations.
La première requête AddBatchJobOperations d'un job par lot doit omettre sequence_token. Lorsque vous appelez à nouveau AddBatchJobOperations pour ajouter d'autres opérations, spécifiez le jeton de séquence obtenu précédemment dans le champ sequence_token de la requête. L'appel de la méthode avec une liste mutate_operations vide renvoie une erreur BatchJobError.EMPTY_OPERATIONS. L'appel de la méthode avec un jeton de séquence autre que celui obtenu précédemment renvoie une erreur BatchJobError.INVALID_SEQUENCE_TOKEN. Enfin, toute tentative d'ajout d'opérations après le démarrage du job renvoie une erreur BatchJobError.CANNOT_MODIFY_JOB_AFTER_JOB_STARTS_RUNNING.
Tant que le status du job par lot est PENDING, sequence_token est également disponible en tant que next_add_sequence_token sur la ressource BatchJob, que vous pouvez récupérer ultérieurement.
Si vous créez des objets dépendants, comme une campagne complète composée d'une nouvelle campagne et des groupes d'annonces, annonces et mots clés correspondants, vous pouvez utiliser des ID temporaires pour spécifier un nom de ressource.
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
Cliquez pour afficher le contenu de la fonction d'opérations de compilation dans GitHub pour votre bibliothèque cliente :
Java
buildAllOperations()
C#
BuildAllOperations()
PHP
buildAllOperations()
Python
build_all_operations()
Ruby
build_all_operations()
Perl
build_all_operations
Exécuter le job par lot
Une fois que vous avez ajouté toutes vos opérations, vous pouvez demander à l'API Google Ads d'exécuter le job par lot en appelant RunBatchJob sur les opérations importées.
L'appel de RunBatchJob après le démarrage du job renvoie une erreur 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
La réponse renvoyée est un objet Operation de longue durée qui contient les métadonnées de votre job par lot et des informations sur l'état du job.
Interroger l'état du job par lot jusqu'à ce qu'il soit terminé
Interrogez l'état du job par lot avec la méthode Operations.GetOperation sur le service google.longrunning.Operations (distinct de BatchJobService) jusqu'à ce que le champ Operation.done soit défini sur true. Dans l'API Google Ads, Operations.GetOperation est la seule méthode compatible avec google.longrunning.Operations (WaitOperation, ListOperations, CancelOperation et DeleteOperation renvoient UNIMPLEMENTED) :
- Bibliothèques clientes : appelez l'assistant d'interrogation ou d'attente sur le wrapper d'opération de longue durée renvoyé par
RunBatchJob(ou transmettez le nom de l'opération àOperationService::poll_until_donedans la bibliothèque cliente Perl basée sur REST), qui interrogeOperations.GetOperationjusqu'à ce que l'opération se termine (ou jusqu'à l'expiration du délai d'interrogation configuré ; en Perl, vérifiez quedoneest défini surtruesur le hachage renvoyé avant de lister les résultats). En Java, laissezBatchJobServiceClientouvert jusqu'à la fin deOperationFuture. - REST : envoyez une requête HTTP
GETàhttps://googleads.googleapis.com/v26/OPERATION_NAME(oùOPERATION_NAMEest le nom de la ressourceOperation.name, au formatcustomers/CUSTOMER_ID/operations/OPERATION_ID) avec un intervalle exponentiel entre les tentatives jusqu'à ce que le champOperation.donesoittrue.
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}" \
Vous pouvez également interroger la ressource batch_job avec la méthode GoogleAdsService.Search ou GoogleAdsService.SearchStream, en sélectionnant batch_job.status et des sous-champs BatchJobMetadata spécifiques (tels que batch_job.metadata.estimated_completion_ratio et batch_job.metadata.executed_operation_count) jusqu'à ce que batch_job.status soit DONE. Chaque requête Operations.GetOperation ou GAQL non paginée est comptabilisée comme une opération dans votre quota d'API quotidien. Lorsque vous surveillez plusieurs jobs par lot simultanés, une seule requête GAQL (WHERE batch_job.id IN
(...) ou WHERE batch_job.status = 'RUNNING') les vérifie tous en une seule requête au lieu d'interroger chaque opération de longue durée individuellement.
Lorsque Operation.done est défini sur true, l'opération de longue durée renvoie une réponse vide sans erreurs par opération. Appelez ListBatchJobResults pour inspecter les résultats des opérations individuelles.
Récupérer une opération de longue durée existante
Si votre application interroge des jobs par lot à partir d'un processus distinct ou doit reprendre l'interrogation après un redémarrage, vous pouvez récupérer le nom de l'opération de longue durée à l'aide de GoogleAdsService.Search ou GoogleAdsService.SearchStream :
Interrogez la ressource
batch_jobpour lire son champlong_running_operation:SELECT batch_job.id, batch_job.status, batch_job.long_running_operation FROM batch_job WHERE batch_job.id = BATCH_JOB_IDRemplacez
BATCH_JOB_IDpar l'ID numérique du job par lot.Vérifiez que
batch_job.statusestRUNNINGouDONE(long_running_operationn'est pas défini tant que la tâche estPENDING, car aucune opération de longue durée n'existe tant queRunBatchJobn'est pas appelé), puis lisez la chaînelong_running_operationà partir de l'objetBatchJobrenvoyé.Interrogez ou inspectez l'opération à l'aide de cette chaîne de nom d'opération :
- Bibliothèques clientes : obtenez le client d'opérations à partir de votre client
BatchJobService(getOperationsClient()en Java et PHP,RunBatchJobOperationsClienten C#,transport.operations_clienten Python,operations_clienten Ruby ou$api_client->OperationService()en Perl) afin que l'authentification Google Ads et les en-têteslogin-customer-idsoient configurés automatiquement, au lieu d'instancier unOperationsClientautonome. AppelezOperations.GetOperation(ouOperationService::geten Perl) pour une seule vérification de l'état, ou utilisez le nom de l'opération pour reprendre un wrapper d'opération de longue durée et interrogez-le jusqu'à la fin (runBatchJobOperationCallable().resumeFutureCallen Java,PollOnceRunBatchJoben C#,resumeOperationen PHP,google.api_core.operation.from_gapicsur leOperationrenvoyé parget_operationen Python,wait_until_done!sur leGapic::Operationrenvoyé parget_operationen Ruby, ounamedansOperationService::poll_until_doneen Perl). - REST : envoyez une requête HTTP
GETàhttps://googleads.googleapis.com/v26/OPERATION_NAME.
Étant donné que
OPERATION_NAMEencode la version majeure de l'API dans laquelleBatchJoba été créé,Operations.GetOperation(même via le point de terminaison RESTv26actif) échoue avec une erreurRequestError.UNSUPPORTED_VERSIONsi cette version a été abandonnée depuis. Interrogez plutôtbatch_job.statusdirectement avecGoogleAdsService.- Bibliothèques clientes : obtenez le client d'opérations à partir de votre client
Comprendre les métadonnées d'opération
Lorsque vous interrogez l'opération de longue durée ou la ressource batch_job, BatchJobMetadata fournit des détails sur la progression du job par lot :
creation_date_time: code temporel de la création du job par lot.start_date_time: code temporel du début de l'exécution du job par lot (renseigné lorsque vous interrogezbatch_job.metadata.start_date_timeavecGoogleAdsService; omis deOperation.metadatadansRunBatchJobetOperations.GetOperation).completion_date_time: code temporel de la fin du job par lot (uniquement présent si le job est terminé).estimated_completion_ratio: estimation de la fraction du job (de 0,0 à 1,0) qui a été effectuée.operation_count: nombre total d'opérations dans le job par lot.executed_operation_count: nombre d'opérations exécutées jusqu'à présent.execution_limit_seconds: limite supérieure approximative, en secondes, de la durée d'exécution du job par lot avant son annulation (renseignée lorsque vous interrogezbatch_job.metadata.execution_limit_secondsavecGoogleAdsServicesi une limite positive a été définie lors de la création du job ; omise deOperation.metadatadansRunBatchJobetOperations.GetOperation).
Ces champs, en particulier estimated_completion_ratio et le nombre d'opérations, peuvent vous aider à évaluer la progression du job, à estimer le temps restant et à ajuster la fréquence d'interrogation. Par exemple, vous pouvez interroger moins fréquemment lorsque la valeur estimated_completion_ratio est faible, et plus fréquemment lorsqu'elle approche de 1,0.
Lister tous les résultats de jobs par lot
Une fois le job par lot terminé, appelez ListBatchJobResults pour récupérer l'état et la réponse de chaque opération du 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}"
Dans ListBatchJobResultsRequest, le champ page_size est défini par défaut sur la valeur maximale de 1000 s'il est omis ou défini sur 0. Si vous définissez page_size sur une valeur supérieure à 1000 ou inférieure à 0, une erreur BatchJobError.INVALID_PAGE_SIZE est renvoyée.
Chaque BatchJobResult identifie l'opération correspondante à l'aide de operation_index, l'index de base 0 de l'MutateOperation importé dans le job par lot.
- Opération réussie :
mutate_operation_responseest renseigné (sonresponsecontient leresource_namede la ressource modifiée, ainsi que tous les champs modifiables siresponse_content_typeest défini surMUTABLE_RESOURCE) etstatusn'est pas défini. - Échec de l'opération (ou opération non exécutée) :
mutate_operation_responsen'est pas défini etstatuscontient les détails de l'erreur pour l'opération.
Annuler ou supprimer un job par lot
La façon dont vous arrêtez ou supprimez un job par lot dépend de l'appel ou non de RunBatchJob :
- Avant d'appeler
RunBatchJob: tant que le paramètrestatusdu job est défini surPENDING, vous pouvez supprimer le job par lot en appelantMutateBatchJobavecBatchJobOperation.remove. L'appel deremoveaprès le démarrage du job renvoie une erreurBatchJobError.CAN_ONLY_REMOVE_PENDING_JOB. - Après avoir appelé
RunBatchJob: vous ne pouvez pas annuler manuellement un job par lot en cours d'exécution (Operations.CancelOperationn'est pas implémenté dans l'API Google Ads et renvoieUNIMPLEMENTED). Pour limiter le temps d'exécution afin qu'un job soit annulé automatiquement s'il s'exécute trop longtemps, définissezmetadata.execution_limit_secondssur un entier positif (une limite supérieure approximative) lorsque vous créez le job dansMutateBatchJob. Étant donné que les opérations standards d'un job par lot s'exécutent avec l'option échec partiel activée (les opérations des sous-lots atomiques sont annulées ensemble), l'annulation automatique n'annule pas les opérations déjà terminées. Une fois que l'étatstatusd'un job annulé (ou abandonné) passe àDONE, l'appel deListBatchJobResultsrenvoie des entréesBatchJobResultpour le préfixe exécuté (operation_index<executed_operation_count) avec leurs résultats d'exécution individuels, suivis des entréesBatchJobResultpour toutes les opérations non exécutées restantes (operation_indexdeexecuted_operation_countàoperation_count- 1) avecmutate_operation_responsenon défini etstatusdéfini surABORTEDavecInternalError.INTERNAL_ERRORlorsqu'il est annulé en raison deexecution_limit_seconds(ou de l'état d'erreur au niveau du job si le job a été abandonné en raison d'une erreur d'exécution fatale).
Gestion des exceptions
BatchJobService exécute des opérations standards avec l'échec partiel activé (les opérations réussies sont validées même si d'autres opérations du même job échouent, sauf dans les sous-lots atomiques) et relance automatiquement les opérations qui échouent en raison d'erreurs temporaires. Cependant, tous les scénarios de défaillance ne peuvent pas être évités. Les opérations qui ont échoué en raison d'erreurs de validation peuvent être corrigées et renvoyées dans un nouveau job par lot. De même, lorsqu'un job par lot est annulé ou s'interrompt avant d'avoir terminé toutes les opérations, vous pouvez renvoyer les opérations non exécutées (operation_index >= executed_operation_count) ainsi que toutes les opérations ayant échoué à partir du préfixe exécuté dans un nouveau job par lot.