تدفق الاستخدام

في ما يلي خطوات استخدام المعالجة على دفعات:

إنشاء مهمة مجمّعة جديدة

لإنشاء مورد BatchJob، استخدِم MutateBatchJob. عند إنشاء عنصر BatchJob، يمكنك اختياريًا ضبط metadata.execution_limit_seconds على عدد صحيح موجب لضبط حدّ أقصى تقريبي، بالثواني، لمدة تشغيل المهمة قبل إلغائها تلقائيًا (يُرجى الاطّلاع على إرشادات الاستخدام الإضافية).

جافا

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 عند استدعاء هذه الطريقة مرة أخرى لإضافة المزيد من العمليات

يجب أن يحذف طلب AddBatchJobOperations الأول لوظيفة مجمّعة sequence_token. عند طلب AddBatchJobOperations مرة أخرى لإضافة المزيد من العمليات، حدِّد الرمز المميّز للتسلسل الذي تم الحصول عليه سابقًا في حقل sequence_token في الطلب. يؤدي استدعاء الطريقة باستخدام قائمة mutate_operations فارغة إلى عرض الخطأ BatchJobError.EMPTY_OPERATIONS، ويؤدي استدعاؤها باستخدام أي رمز تسلسل غير الرمز الذي تم الحصول عليه سابقًا إلى عرض الخطأ BatchJobError.INVALID_SEQUENCE_TOKEN، وتؤدي محاولة إضافة عمليات بعد بدء تشغيل المهمة إلى عرض الخطأ BatchJobError.CANNOT_MODIFY_JOB_AFTER_JOB_STARTS_RUNNING.

عندما تكون قيمة status لطلب الدفعة هي PENDING، يتوفّر أيضًا sequence_token كقيمة next_add_sequence_token في مورد BatchJob، والذي يمكنك استرداده لاحقًا.

إذا كنت بصدد إنشاء عناصر تابعة، مثل حملة كاملة تتألف من حملة جديدة ومجموعات إعلانية وإعلانات وكلمات رئيسية مقابلة، يمكنك استخدام معرّفات مؤقتة لتحديد اسم مورد.

جافا

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
      

انقر للاطّلاع على محتوى دالة عمليات الإنشاء في GitHub لمكتبة العميل:

تنفيذ المهمة المجمّعة

بعد إضافة جميع العمليات، يمكنك طلب تشغيل مهمة الدفعة من Google Ads API من خلال استدعاء RunBatchJob في العمليات التي تم تحميلها. يؤدي استدعاء RunBatchJob بعد بدء تشغيل المهمة إلى عرض الخطأ BatchJobError.CANNOT_MODIFY_JOB_AFTER_JOB_STARTS_RUNNING.

جافا

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):

  • مكتبات البرامج: يمكنك استدعاء أداة الاستطلاع أو أداة المساعدة في الانتظار في برنامج تضمين العمليات الطويلة الذي تعرضه RunBatchJob (أو يمكنك تمرير اسم العملية إلى OperationService::poll_until_done في مكتبة برامج Perl المستندة إلى REST)، والتي تستطلع Operations.GetOperation حتى تكتمل العملية (أو حتى تنتهي مهلة الاستطلاع التي تم ضبطها؛ في Perl، تأكَّد من أنّ done هي true في التجزئة المعروضة قبل إدراج النتائج). في Java، يجب إبقاء BatchJobServiceClient مفتوحًا إلى أن ينتهي OperationFuture.
  • REST: أرسِل طلب HTTP GET إلى https://googleads.googleapis.com/v26/OPERATION_NAME (حيث OPERATION_NAME هو اسم مورد Operation.name، بتنسيق customers/CUSTOMER_ID/operations/OPERATION_ID) مع تأخير أسي حتى يصبح الحقل Operation.done true.

جافا

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 غير مقسّم إلى صفحات كعملية واحدة ضمن الحصة اليومية لواجهة برمجة التطبيقات. وعند مراقبة مهام مجمّعة متزامنة متعددة، يتحقّق طلب بحث GAQL واحد (WHERE batch_job.id IN (...) أو WHERE batch_job.status = 'RUNNING') منها جميعًا في طلب واحد بدلاً من استطلاع كل عملية طويلة بشكل فردي.

عندما تكون قيمة Operation.done هي true، تعرض العملية الطويلة ردًا فارغًا بدون أخطاء لكل عملية. يمكنك طلب ListBatchJobResults لفحص نتائج العمليات الفردية.

استرداد عملية طويلة حالية

إذا كان تطبيقك يستطلع وظائف مجمّعة من عملية منفصلة أو يحتاج إلى استئناف الاستطلاع بعد إعادة التشغيل، يمكنك استرداد اسم العملية التي تستغرق وقتًا طويلاً باستخدام GoogleAdsService.Search أو GoogleAdsService.SearchStream:

  1. أرسِل طلب بحث إلى المورد 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 بالرقم التعريفي الرقمي لمهمة مجمّعة.

  2. تأكَّد من أنّ batch_job.status هو RUNNING أو DONE (لم يتم ضبط long_running_operation أثناء تنفيذ المهمة PENDING لأنّه لا توجد عملية طويلة الأمد حتى يتم استدعاء RunBatchJob)، واقرأ سلسلة long_running_operation من عنصر BatchJob الذي تم عرضه.

  3. يمكنك إجراء استطلاع أو فحص للعملية باستخدام سلسلة اسم العملية:

    • مكتبات العملاء: يمكنك الحصول على عميل العمليات من عميل BatchJobService (getOperationsClient() في Java وPHP، وRunBatchJobOperationsClient في C#‎، وtransport.operations_client في Python، وoperations_client في Ruby، أو $api_client->OperationService() في Perl) بحيث يتم ضبط مصادقة "إعلانات Google" وعناوين login-customer-id تلقائيًا، بدلاً من إنشاء مثيل OperationsClient مستقل. يمكنك استدعاء Operations.GetOperation (أو OperationService::get في Perl) لإجراء فحص حالة واحد، أو استخدام اسم العملية لاستئناف برنامج تضمين عملية طويلة الأمد والاستقصاء حتى اكتمالها (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 يرمّز رقم الإصدار الرئيسي لواجهة برمجة التطبيقات الذي تم فيه إنشاء BatchJob، فإنّ Operations.GetOperation (حتى من خلال نقطة نهاية REST النشطة v26) يتعذّر تنفيذه مع ظهور الخطأ 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.

عرض قائمة بجميع نتائج المهام المجمّعة

عند انتهاء مهمة الدُفعة، يمكنك استدعاء ListBatchJobResults لاسترداد الحالة والاستجابة لكل عملية في المهمة:

جافا

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، وهو الفهرس المستند إلى 0 لـ MutateOperation الذي تم تحميله في المهمة المجمّعة.

إلغاء مهمة مجمّعة أو إزالتها

تعتمد طريقة إيقاف مهمة مجمّعة أو تجاهلها على ما إذا تم استدعاء RunBatchJob:

معالجة الأخطاء

BatchJobService ينفّذ العمليات العادية مع تفعيل ميزة الفشل الجزئي (يتم تنفيذ العمليات الناجحة حتى إذا فشلت عمليات أخرى في المهمة نفسها، باستثناء الدفعات الفرعية الذرية) ويعيد تلقائيًا محاولة تنفيذ العمليات التي تفشل بسبب أخطاء عابرة. ومع ذلك، لا يمكن تجنب جميع سيناريوهات الفشل. يمكن إصلاح العمليات التي تعذّر تنفيذها بسبب أخطاء في التحقّق من الصحة وإعادة إرسالها في مهمة مجمّعة جديدة. وبالمثل، عندما يتم إلغاء أو إيقاف مهمة مجمّعة قبل إكمال جميع العمليات، يمكنك إعادة إرسال العمليات غير المنفّذة (operation_index>= executed_operation_count) مع أي عمليات تعذّر تنفيذها من البادئة المنفّذة في مهمة مجمّعة جديدة.