כדי להשתמש בעיבוד ברצף:
יצירת משימה חדשה באצווה
כדי ליצור משאב מסוג BatchJob, צריך להפעיל את השיטה MutateBatchJob. כשיוצרים את האובייקט BatchJob, אפשר להגדיר את metadata.execution_limit_seconds כמספר שלם חיובי כדי לקבוע גבול עליון משוער, בשניות, למשך הזמן שהמשימה יכולה לפעול לפני שהיא תבוטל באופן אוטומטי (ראו הנחיות שימוש נוספות).
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
בשלב הזה בתהליך, הערך של status של המשימה הוא PENDING.
הוספת פעולות מוטציה למשימה באצווה
מוסיפים אובייקט MutateOperation אחד או יותר למשימה באצווה שנוצרה בשלב הקודם, על ידי קריאה ל-AddBatchJobOperations. התשובה תכיל את הפרטים הבאים:
-
total_operations: המספר הכולל של הפעולות שנוספו עד עכשיו למשימה הזו. -
next_sequence_token: אסימון רצף שצריך להעביר בשדהsequence_tokenכשקוראים שוב ל-method הזה כדי להוסיף עוד פעולות.
בבקשה הראשונה של AddBatchJobOperations עבור batch job, צריך להשמיט את sequence_token. כשקוראים שוב ל-AddBatchJobOperations כדי להוסיף עוד פעולות, מציינים את אסימון הרצף שהתקבל קודם בשדה sequence_token של הבקשה. קריאה ל-method עם רשימת mutate_operations ריקה מחזירה שגיאת BatchJobError.EMPTY_OPERATIONS, קריאה ל-method עם אסימון רצף אחר מזה שהתקבל קודם מחזירה שגיאת BatchJobError.INVALID_SEQUENCE_TOKEN, וניסיון להוסיף פעולות אחרי שהמשימה מתחילה לפעול מחזיר שגיאת BatchJobError.CANNOT_MODIFY_JOB_AFTER_JOB_STARTS_RUNNING.
כשהשדה status של משימה באצווה הוא PENDING, השדה sequence_token זמין גם בתור next_add_sequence_token במשאב BatchJob, ואפשר לאחזר אותו מאוחר יותר.
אם אתם יוצרים אובייקטים תלויים, כמו קמפיין שלם שמורכב מקמפיין חדש וקבוצות של מודעות, מודעות ומילות מפתח תואמות, אתם יכולים להשתמש במזהים זמניים כדי לציין שם משאב.
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
כדי לראות את התוכן של הפונקציה של פעולות ה-build ב-GitHub לספריית הלקוח, לוחצים על:
Java
buildAllOperations()
C#
BuildAllOperations()
PHP
buildAllOperations()
Python
build_all_operations()
Ruby
build_all_operations()
Perl
build_all_operations
הרצת המשימה באצווה
אחרי שמוסיפים את כל הפעולות, אפשר לבקש מ-Google Ads API להריץ את משימת ה-Batch על ידי קריאה ל-RunBatchJob בפעולות שהועלו.
אם קוראים ל-RunBatchJob אחרי שהמשימה כבר התחילה לפעול, מוחזרת השגיאה 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
התשובה שמוחזרת היא אובייקט Operation שפועל לאורך זמן, שמכיל את המטא-נתונים של המשימה באצווה ומידע על סטטוס המשימה.
דוגמים את הסטטוס של המשימה באצווה עד שהיא מסתיימת
מבצעים דגימה של סטטוס משימת האצווה באמצעות השיטה Operations.GetOperation בשירות google.longrunning.Operations (בנפרד מ-BatchJobService) עד שהערך בשדה Operation.done הוא true. ב-Google Ads API, Operations.GetOperation היא השיטה היחידה שנתמכת ב-google.longrunning.Operations (WaitOperation, ListOperations, CancelOperation ו-DeleteOperation מחזירות UNIMPLEMENTED):
- ספריות לקוח: קוראים לפונקציית העזר של הסקר או ההמתנה ב-wrapper של הפעולה הממושכת שמוחזר על ידי
RunBatchJob(או מעבירים את שם הפעולה אלOperationService::poll_until_doneבספריית הלקוח של Perl שמבוססת על REST), שמבצעת סקר שלOperations.GetOperationעד שהפעולה מסתיימת (או עד שפג הזמן הקצוב לתפוגה של הסקר שהוגדר. ב-Perl, צריך לוודא שהערך שלdoneהואtrueב-hash שמוחזר לפני שמציגים את התוצאות). ב-Java, צריך להשאיר אתBatchJobServiceClientפתוח עד לסיום שלOperationFuture. - REST: שולחים בקשת HTTP
GETאלhttps://googleads.googleapis.com/v26/OPERATION_NAME(כאשרOPERATION_NAMEהוא שם המשאבOperation.name, בפורמטcustomers/CUSTOMER_ID/operations/OPERATION_ID) עם השהיה מעריכית לפני ניסיון חוזר (exponential backoff) עד שהשדהOperation.doneהוא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}" \
לחלופין, אפשר לשלוח שאילתה למשאב batch_job באמצעות השיטה GoogleAdsService.Search או GoogleAdsService.SearchStream, לבחור את batch_job.status ושדות משנה ספציפיים של BatchJobMetadata (כמו batch_job.metadata.estimated_completion_ratio ו-batch_job.metadata.executed_operation_count) עד שהערך של batch_job.status יהיה DONE. כל בקשת Operations.GetOperation או בקשת GAQL ללא חלוקה לדפים נספרת כפעולה אחת במסגרת מכסת ה-API היומית. כשמנטרים כמה משימות אצווה בו-זמנית, שאילתת GAQL אחת (WHERE batch_job.id IN
(...) או WHERE batch_job.status = 'RUNNING') בודקת את כולן בבקשה אחת, במקום לדגום כל פעולה ממושכת בנפרד.
כשהערך של Operation.done הוא true, הפעולה הממושכת מחזירה תשובה ריקה בלי שגיאות לכל פעולה. צריך להפעיל את ListBatchJobResults כדי לבדוק את התוצאות של כל פעולה בנפרד.
אחזור של פעולה ממושכת קיימת
אם האפליקציה שלכם דוגמת משימות באצווה מתהליך נפרד או צריכה להמשיך את הדגימה אחרי הפעלה מחדש, אתם יכולים לאחזר את שם הפעולה הממושכת באמצעות GoogleAdsService.Search או GoogleAdsService.SearchStream:
שולחים שאילתה למשאב
batch_jobכדי לקרוא את השדהlong_running_operation:SELECT batch_job.id, batch_job.status, batch_job.long_running_operation FROM batch_job WHERE batch_job.id = BATCH_JOB_IDמחליפים את
BATCH_JOB_IDבמזהה המספרי של המשימה באצווה.מוודאים שהערך של
batch_job.statusהואRUNNINGאוDONE(הערך שלlong_running_operationלא מוגדר כשהמשימה היאPENDINGכי אין פעולה ממושכת עד שקוראים ל-RunBatchJob), וקוראים את המחרוזתlong_running_operationמהאובייקטBatchJobשמוחזר.כדי לבדוק את הפעולה, משתמשים במחרוזת של שם הפעולה:
- ספריות לקוח: מקבלים את לקוח הפעולות מלקוח
BatchJobService(getOperationsClient()ב-Java וב-PHP,RunBatchJobOperationsClientב-C#,transport.operations_clientב-Python,operations_clientב-Ruby או$api_client->OperationService()ב-Perl) כדי שהאימות של Google Ads וכותרותlogin-customer-idיוגדרו באופן אוטומטי, במקום ליצור מופע שלOperationsClientעצמאי. קוראים ל-Operations.GetOperation(או ל-OperationService::getב-Perl) לבדיקת סטטוס יחידה, או משתמשים בשם הפעולה כדי להמשיך wrapper של פעולה ממושכת ולבצע סקר עד להשלמה (runBatchJobOperationCallable().resumeFutureCallב-Java,PollOnceRunBatchJobב-C#,resumeOperationב-PHP,google.api_core.operation.from_gapicב-Operationשמוחזר על ידיget_operationב-Python,wait_until_done!ב-Gapic::Operationשמוחזר על ידיget_operationב-Ruby, אוnameב-OperationService::poll_until_doneב-Perl). - REST: שולחים בקשת HTTP
GETאלhttps://googleads.googleapis.com/v26/OPERATION_NAME.
השדה
OPERATION_NAMEמקודד את הגרסה הראשית של ה-API שבה נוצרBatchJob, ולכן הפעולהOperations.GetOperation(אפילו דרך נקודת הקצה הפעילה שלv26REST) נכשלת עם השגיאהRequestError.UNSUPPORTED_VERSIONאם הגרסה הזו הוצאה משימוש מאז. במקום זאת, אפשר לשלוח שאילתה ל-batch_job.statusישירות באמצעותGoogleAdsService.- ספריות לקוח: מקבלים את לקוח הפעולות מלקוח
הסבר על המטא-נתונים של הפעולה
כשדוגמים את הפעולה הממושכת או שולחים שאילתה למשאב batch_job, BatchJobMetadata מספק פרטים על התקדמות המשימה באצווה:
-
creation_date_time: חותמת הזמן של יצירת המשימה באצווה. -
start_date_time: חותמת הזמן שבה התחילה ההרצה של ה-משימה באצווה (מאוכלסת כששולחים שאילתה ל-batch_job.metadata.start_date_timeעםGoogleAdsService, מושמטת מ-Operation.metadataב-RunBatchJobוב-Operations.GetOperation). -
completion_date_time: חותמת הזמן שבה הסתיימה המשימה באצווה (מופיעה רק אם המשימה הסתיימה). -
estimated_completion_ratio: הערכה של החלק מהמשימה (מ-0.0 עד 1.0) שהושלם. -
operation_count: המספר הכולל של הפעולות במשימה באצווה. -
executed_operation_count: מספר הפעולות שבוצעו עד עכשיו. -
execution_limit_seconds: הגבול העליון המשוער, בשניות, למשך הזמן שבו יכולה לפעול משימה באצווה לפני שהיא מבוטלת (מאוכלס כששולחים שאילתה ל-batch_job.metadata.execution_limit_secondsעםGoogleAdsServiceאם הוגדרה מגבלה חיובית בזמן יצירת המשימה; מושמט מ-Operation.metadataב-RunBatchJobוב-Operations.GetOperation).
השדות האלה, במיוחד estimated_completion_ratio ומספרי הפעולות, יכולים לעזור לכם להעריך את התקדמות המשימה, להעריך את הזמן שנותר ולשנות את תדירות הסקרים. לדוגמה, אפשר לבצע דגימה בתדירות נמוכה יותר כשהערך של estimated_completion_ratio נמוך, ובתדירות גבוהה יותר כשהוא מתקרב ל-1.0.
הצגת כל התוצאות של משימות באצווה
כשה-batch job מסתיים, מפעילים את ListBatchJobResults כדי לאחזר את הסטטוס והתגובה של כל פעולה ב-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}"
ב-ListBatchJobResultsRequest, ערך ברירת המחדל של השדה page_size הוא הערך המקסימלי של 1000 אם משמיטים אותו או מגדירים אותו כ-0. אם מגדירים ל-page_size ערך שגדול מ-1000 או קטן מ-0, תוחזר השגיאה BatchJobError.INVALID_PAGE_SIZE.
כל BatchJobResult מזהה את הפעולה המתאימה באמצעות operation_index, האינדקס מבוסס-האפס של MutateOperation שהועלה במשימה באצווה.
- פעולה מוצלחת:
השדה
mutate_operation_responseמאוכלס (השדהresponseמכיל את השדהresource_nameשל המשאב שעבר מוטציה, וגם את כל השדות שניתנים לשינוי אםresponse_content_typeמוגדר כ-MUTABLE_RESOURCE), והשדהstatusלא מוגדר. - פעולה שנכשלה (או שלא בוצעה):
mutate_operation_responseלא מוגדר, ו-statusמכיל את פרטי השגיאה של הפעולה.
ביטול או הסרה של משימה באצווה
האופן שבו עוצרים או מבטלים משימה באצווה תלוי בשאלה אם בוצעה קריאה ל-RunBatchJob:
- לפני שקוראים ל-
RunBatchJob: כשהערך שלstatusשל המשימה הואPENDING, אפשר לבטל את המשימה באצווה על ידי קריאה ל-MutateBatchJobעםBatchJobOperation.remove. אם תפעילו אתremoveאחרי שהמשימה התחילה, תקבלו את השגיאהBatchJobError.CAN_ONLY_REMOVE_PENDING_JOB. - אחרי שמפעילים את
RunBatchJob: אי אפשר לבטל באופן ידני משימה פעילה באצווה (Operations.CancelOperationלא מוטמעת ב-Google Ads API ומחזירה את הערךUNIMPLEMENTED). כדי להגביל את זמן הביצוע כך שהמשימה תתבטל באופן אוטומטי אם היא פועלת יותר מדי זמן, צריך להגדיר אתmetadata.execution_limit_secondsכמספר שלם חיובי (גבול עליון משוער) כשיוצרים את המשימה ב-MutateBatchJob. מכיוון שפעולות רגילות ב-משימה באצווה מופעלות עם כשל חלקי (פעולות ב-atomic sub-batches מגולגלות אחורה ביחד), ביטול אוטומטי לא מגלגל אחורה פעולות שכבר הושלמו. אחרי שהשדהstatusשל משימה שבוטלה (או הופסקה) עובר לערךDONE, קריאה ל-ListBatchJobResultsמחזירה רשומות שלBatchJobResultלתחילית שבוצעה (operation_index<executed_operation_count) עם תוצאות הביצוע הנפרדות שלהן, ואחריהן רשומות שלBatchJobResultלכל הפעולות הנותרות שלא בוצעו (operation_indexמ-executed_operation_countעדoperation_count- 1) עםmutate_operation_responseלא מוגדר ו-statusמוגדר ל-ABORTEDעםInternalError.INTERNAL_ERRORכשבוטלה בגללexecution_limit_seconds(או לסטטוס השגיאה ברמת המשימה אם המשימה הופסקה בגלל שגיאת ביצוע חמורה).
טיפול בשגיאות
BatchJobService מבצע פעולות רגילות כשמופעלת האפשרות כשל חלקי (פעולות שהצליחו נשמרות גם אם פעולות אחרות באותו ג'וב נכשלות, חוץ מתת-אצוות אטומיות), ומנסה באופן אוטומטי לבצע שוב פעולות שנכשלו בגלל שגיאות זמניות. עם זאת, לא תמיד אפשר למנוע תרחישי כשל. אם פעולות נכשלו בגלל שגיאות אימות, אפשר לתקן אותן ולשלוח אותן מחדש במשימה חדשה באצווה. באופן דומה, אם משימה באצווה מבוטלת או מופסקת לפני שכל הפעולות הושלמו, אפשר לשלוח מחדש את הפעולות שלא בוצעו (operation_index >= executed_operation_count) יחד עם כל הפעולות שנכשלו מהתחילית שבוצעה במשימה חדשה באצווה.