I passaggi per utilizzare l'elaborazione batch sono i seguenti:
Crea un nuovo job batch
Per creare una risorsa BatchJob, chiama
MutateBatchJob. Quando crei l'oggetto BatchJob, puoi facoltativamente impostare metadata.execution_limit_seconds su un numero intero positivo per configurare un limite superiore approssimativo, in secondi, per il tempo di esecuzione del job prima che venga annullato automaticamente (consulta Indicazioni aggiuntive per l'utilizzo).
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
A questo punto del processo, lo status del job è
PENDING.
Aggiungi operazioni di modifica al job batch
Aggiungi uno o più oggetti MutateOperation al job batch creato nel passaggio precedente chiamando AddBatchJobOperations. La risposta contiene quanto segue:
total_operations: il numero totale di operazioni aggiunte finora per questo job.next_sequence_token: token di sequenza da passare nel camposequence_tokenquando chiami di nuovo questo metodo per aggiungere altre operazioni.
La prima richiesta AddBatchJobOperations per un job batch deve omettere sequence_token. Quando chiami di nuovo AddBatchJobOperations per aggiungere altre operazioni, specifica il token di sequenza ottenuto in precedenza nel campo sequence_token della richiesta. La chiamata del metodo con un elenco mutate_operations vuoto restituisce un errore BatchJobError.EMPTY_OPERATIONS, la chiamata con un token di sequenza diverso da quello ottenuto in precedenza restituisce un errore BatchJobError.INVALID_SEQUENCE_TOKEN e il tentativo di aggiungere operazioni sugli annunci dopo l'avvio del job restituisce un errore BatchJobError.CANNOT_MODIFY_JOB_AFTER_JOB_STARTS_RUNNING.
Mentre il status del job batch è
PENDING, sequence_token è disponibile anche come
next_add_sequence_token nella
risorsa BatchJob, che puoi recuperare
in un secondo momento.
Se stai creando oggetti dipendenti, ad esempio una campagna completa composta da una nuova campagna e dai relativi gruppi di annunci, annunci e parole chiave, puoi utilizzare gli ID temporanei per specificare un nome risorsa.
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
Fai clic per visualizzare i contenuti della funzione delle operazioni di build in GitHub per la tua libreria client:
Java
buildAllOperations()
C#
BuildAllOperations()
PHP
buildAllOperations()
Python
build_all_operations()
Ruby
build_all_operations()
Perl
build_all_operations
Esegui il job batch
Dopo aver aggiunto tutte le operazioni, puoi richiedere all'API Google Ads di eseguire il job batch chiamando RunBatchJob sulle operazioni caricate.
La chiamata di RunBatchJob dopo l'avvio del job restituisce un errore 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 risposta restituita è un oggetto Operation a lunga esecuzione che contiene i metadati del job batch e le informazioni sullo stato del job.
Esegui il polling dello stato del job batch fino al completamento
Esegui il polling dello stato del job batch con il metodo Operations.GetOperation sul servizio google.longrunning.Operations (separato da BatchJobService) finché il campo Operation.done non è true. Nell'API Google Ads,
Operations.GetOperation è l'unico metodo supportato su
google.longrunning.Operations (WaitOperation,
ListOperations, CancelOperation e DeleteOperation restituiscono
UNIMPLEMENTED):
- Librerie client: chiama l'helper di polling o di attesa sul wrapper dell'operazione a lunga esecuzione restituito da
RunBatchJob(o passa il nome dell'operazione aOperationService::poll_until_donenella libreria client Perl basata su REST), che esegue il polling diOperations.GetOperationfino al completamento dell'operazione (o fino alla scadenza del timeout di polling configurato; in Perl, verifica chedonesiatruenell'hash restituito prima di elencare i risultati). In Java, tieni apertoBatchJobServiceClientfino al termine diOperationFuture. - REST: invia una richiesta HTTP
GETahttps://googleads.googleapis.com/v26/OPERATION_NAME(doveOPERATION_NAMEè il nome della risorsaOperation.name, formattato comecustomers/CUSTOMER_ID/operations/OPERATION_ID) con backoff esponenziale finché il campoOperation.donenon è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, # 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}" \
In alternativa, esegui una query sulla risorsa batch_job con il metodo GoogleAdsService.Search o GoogleAdsService.SearchStream, selezionando batch_job.status e i campi secondari BatchJobMetadata specifici (come batch_job.metadata.estimated_completion_ratio e batch_job.metadata.executed_operation_count) finché batch_job.status non è DONE. Ogni richiesta Operations.GetOperation o GAQL non impaginata viene conteggiata come un'operazione ai fini della quota API giornaliera. Quando monitori più job batch contemporanei, una singola query GAQL (WHERE batch_job.id IN
(...) o WHERE batch_job.status = 'RUNNING') li controlla tutti in un'unica richiesta anziché eseguire il polling di ogni operazione a lunga esecuzione singolarmente.
Quando Operation.done è true, l'operazione a lunga esecuzione restituisce una risposta vuota senza errori per operazione. Chiama ListBatchJobResults per esaminare i risultati delle singole operazioni.
Recupera un'operazione a lunga esecuzione esistente
Se la tua applicazione esegue il polling dei job batch da un processo separato o deve riprendere il polling dopo un riavvio, puoi recuperare il nome dell'operazione a lunga esecuzione utilizzando GoogleAdsService.Search o GoogleAdsService.SearchStream:
Esegui una query sulla risorsa
batch_jobper leggerne il campolong_running_operation:SELECT batch_job.id, batch_job.status, batch_job.long_running_operation FROM batch_job WHERE batch_job.id = BATCH_JOB_IDSostituisci
BATCH_JOB_IDcon l'ID numerico del job batch.Verifica che
batch_job.statussiaRUNNINGoDONE(long_running_operationnon è impostato mentre il job èPENDINGperché non esiste alcuna operazione a lunga esecuzione finché non viene chiamatoRunBatchJob) e leggi la stringalong_running_operationdall'oggettoBatchJobrestituito.Esegui il polling o l'ispezione dell'operazione utilizzando la stringa del nome dell'operazione:
- Librerie client: ottieni il client delle operazioni dal tuo client
BatchJobService(getOperationsClient()in Java e PHP,RunBatchJobOperationsClientin C#,transport.operations_clientin Python,operations_clientin Ruby o$api_client->OperationService()in Perl) in modo che l'autenticazione Google Ads e le intestazionilogin-customer-idvengano configurate automaticamente, anziché creare un'istanza di unOperationsClientautonomo. ChiamaOperations.GetOperation(oOperationService::getin Perl) per un singolo controllo dello stato oppure utilizza il nome dell'operazione per riprendere un wrapper di un'operazione a lunga esecuzione ed esegui il polling fino al completamento (runBatchJobOperationCallable().resumeFutureCallin Java,PollOnceRunBatchJobin C#,resumeOperationin PHP,google.api_core.operation.from_gapicsuOperationrestituito daget_operationin Python,wait_until_done!suGapic::Operationrestituito daget_operationin Ruby onameinOperationService::poll_until_donein Perl). - REST: invia una richiesta HTTP
GETahttps://googleads.googleapis.com/v26/OPERATION_NAME.
Poiché
OPERATION_NAMEcodifica la versione principale dell'API in cui è stato creatoBatchJob,Operations.GetOperation(anche tramite l'endpoint RESTv26attivo) non va a buon fine e restituisce un erroreRequestError.UNSUPPORTED_VERSIONse quella versione è stata ritirata. Esegui invece query subatch_job.statusdirettamente conGoogleAdsService.- Librerie client: ottieni il client delle operazioni dal tuo client
Informazioni sui metadati delle operazioni
Quando esegui il polling dell'operazione a lunga esecuzione o esegui una query sulla risorsa batch_job, BatchJobMetadata fornisce i dettagli sull'avanzamento del job batch:
creation_date_time: il timestamp della creazione del job batch.start_date_time: il timestamp di inizio dell'esecuzione del job batch (compilato quando esegui una query subatch_job.metadata.start_date_timeconGoogleAdsService; omesso daOperation.metadatainRunBatchJobeOperations.GetOperation).completion_date_time: il timestamp del completamento del job batch (presente solo se il job è stato completato).estimated_completion_ratio: una stima della frazione del job (da 0,0 a 1,0) che è stata completata.operation_count: il numero totale di operazioni nel job batch.executed_operation_count: il numero di operazioni eseguite finora.execution_limit_seconds: Il limite superiore approssimativo, in secondi, per la durata di esecuzione del job batch prima dell'annullamento (compilato quando si esegue la query)batch_job.metadata.execution_limit_secondsconGoogleAdsServicese è stato fissato un limite positivo al momento della creazione del job; omesso daOperation.metadataInRunBatchJobEOperations.GetOperation).
Questi campi, in particolare estimated_completion_ratio
e i conteggi delle operazioni, possono aiutarti a valutare l'avanzamento del job, stimare
il tempo rimanente e regolare la frequenza di polling. Ad esempio, potresti eseguire il polling
meno frequentemente quando il valore di estimated_completion_ratio
è basso e più frequentemente quando si avvicina a 1, 0.
Elenca tutti i risultati dei job batch
Al termine del job batch, chiama
ListBatchJobResults per recuperare lo stato e
la risposta per ogni operazione del 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}"
In ListBatchJobResultsRequest, il campo page_size viene impostato per impostazione predefinita sul valore massimo di 1000 se omesso o impostato su 0. Se imposti page_size su un valore maggiore di 1000 o minore di 0, viene restituito un errore BatchJobError.INVALID_PAGE_SIZE.
Ogni BatchJobResult identifica l'operazione corrispondente utilizzando operation_index, l'indice in base 0 dell'oggetto MutateOperation caricato nel job batch.
- Operazione riuscita:
mutate_operation_responseviene compilato (il suoresponsecontiene ilresource_namedella risorsa modificata, più tutti i campi modificabili seresponse_content_typeè impostato suMUTABLE_RESOURCE) estatusnon è impostato. - Operazione non riuscita (o non eseguita):
mutate_operation_responsenon è impostato estatuscontiene i dettagli dell'errore per l'operazione.
Annulla o rimuovi un job batch
La modalità di interruzione o eliminazione di un job batch dipende dal fatto che sia stato chiamato o meno RunBatchJob:
- Prima di chiamare
RunBatchJob: Mentre lo stato del job batch èstatusÈPENDING, puoi scartare il job batch chiamandoMutateBatchJobconBatchJobOperation.remove. La chiamata diremovedopo l'avvio del job restituisce un erroreBatchJobError.CAN_ONLY_REMOVE_PENDING_JOB. - Dopo aver chiamato
RunBatchJob: non puoi annullare manualmente un job batch in esecuzione (Operations.CancelOperationnon è implementato nell'API Google Ads e restituisceUNIMPLEMENTED). Per limitare il tempo di esecuzione in modo che un job venga annullato automaticamente se viene eseguito per troppo tempo, impostametadata.execution_limit_secondssu un numero intero positivo (un limite superiore approssimativo) quando crei il job inMutateBatchJob. Poiché le operazioni standard in un job batch vengono eseguite con l'opzione Errore parziale attivata (le operazioni nei sub-batch atomici vengono sottoposte a rollback insieme), l'annullamento automatico non esegue il rollback delle operazioni già completate. Una volta che ilstatusdi un job annullato (o interrotto) passa aDONE, la chiamata aListBatchJobResultsrestituisce le vociBatchJobResultper il prefisso eseguito (operation_index<executed_operation_count) con i singoli risultati di esecuzione, seguiti dalle vociBatchJobResultper tutte le restanti operazioni non eseguite (operation_indexdaexecuted_operation_countaoperation_count- 1) conmutate_operation_responsenon impostato estatusimpostato suABORTEDconInternalError.INTERNAL_ERRORse annullato a causa diexecution_limit_seconds(o allo stato di errore a livello di job se il job è stato interrotto a causa di un errore di esecuzione irreversibile).
Gestione degli errori
BatchJobService esegue operazioni standard con l'errore parziale abilitato (le operazioni riuscite vengono eseguite anche se altre operazioni nello stesso job non vanno a buon fine, ad eccezione dei sub-batch atomici) e riprova automaticamente le operazioni che non vanno a buon fine a causa di errori temporanei. Tuttavia, non tutti gli scenari di errore
possono essere evitati. Le operazioni non riuscite a causa di errori di convalida possono essere corrette e inviate nuovamente in un nuovo job batch. Analogamente, quando un job batch viene annullato o interrotto prima di completare tutte le operazioni, puoi inviare nuovamente le operazioni non eseguite (operation_index >= executed_operation_count) insieme a eventuali operazioni non riuscite dal prefisso eseguito in un nuovo job batch.