בקשות אצווה

במסמך הזה נסביר איך לקבץ באצווה קריאות ל-API כדי לצמצם את מספר חיבורי ה-HTTP. שהלקוח צריך לבצע.

המסמך הזה עוסק ספציפית בשליחת בקשה באצווה על ידי שליחת בקשת HTTP. אם אתם משתמשים בספריית לקוח של Google כדי לשלוח בקשה באצווה, כדאי לעיין במסמכי התיעוד של ספריית הלקוח.

סקירה כללית

כל חיבור HTTP שהלקוח יוצר מגדיל במידה מסוימת את התקורה. רשת המדיה Video 360 API תומך בקיבוץ באצווה של קריאות כדי לאפשר ללקוח לבצע מספר קריאות ל-API בבקשת HTTP אחת.

דוגמאות למצבים שבהם כדאי להשתמש בקיבוץ באצווה של קריאות:

  • אחזור משאבים אצל כמה מפרסמים.
  • יצירה או עדכון של משאבים בכמות גדולה.
  • עריכת הטירגוט בכמה פריטים.

במקרים כאלה, במקום לשלוח כל קריאה בנפרד, אפשר לקבץ את כל הקריאות בבקשת HTTP אחת. כל הבקשות הפנימיות חייבות לעבור לאותו Google API.

בבקשה באצווה אחת אפשר לכלול עד 1,000 קריאות. אם צריך לבצע יותר קריאות, תוכלו להשתמש במספר בקשות באצווה.

הערה: מערכת אצווה עבור Display & התחביר של Video 360 API זהה לזה של מערכת עיבוד אצווה של OData, אבל הסמנטיקה שונה.

פירוט לגבי בקשות באצווה

בקשה באצווה מורכבת מכמה קריאות ל-API המאוגדות לבקשת HTTP אחת, שאותה אפשר לשלוח אל ה-batchPath שצוין במסמך ה-Discovery של ה-API. נתיב ברירת המחדל הוא /batch/api_name/api_version. הקטע הזה מתאר בפירוט את התחביר של קריאות באצווה; בהמשך, יש דוגמה.

הערה: קבוצה של n בקשות מקובצות יחד נספרת כדי לחשב את מגבלת השימוש כבקשות n, ולא כבקשה אחת. הבקשה באצווה מופרדת לקבוצה של בקשות לפני העיבוד.

הפורמט של בקשה באצווה

בקשה באצווה היא בקשת HTTP רגילה יחידה שמכילה כמה קריאות ל-API של Video 360, באמצעות סוג התוכן multipart/mixed. בבקשת ה-HTTP הראשית, כל אחד מהחלקים מכיל בתוכו בקשת HTTP פנימית.

כל חלק מתחיל בכותרת HTTP ‏Content-Type: application/http משלו. אפשר להוסיף לה גם כותרת Content-ID אופציונלית. עם זאת, כותרות החלקים רק נועדו לסמן את תחילת החלק. הם נפרדים מהבקשה הפנימית. אחרי שהשרת מפרק את הבקשה באצווה לבקשות נפרדות, המערכת מתעלמת מכותרות החלקים.

הגוף של כל חלק הוא בקשת HTTP מלאה עם פועל, כתובת URL, כותרות וגוף. בקשת ה-HTTP חייבת להכיל רק את החלק של הנתיב שבכתובת ה-URL. כתובות URL מלאות אינן מותרות בבקשות באצווה.

כותרות ה-HTTP של הבקשה החיצונית המקובצת באצווה חלות על כל בקשה באצווה, מלבד כותרות Content-, כמו Content-Type. אם תציינו כותרת HTTP ספציפית בבקשה החיצונית המקובצת וגם בקריאה ספציפית, הערך של כותרת הקריאה הספציפית יבטל את הערך של כותרת הבקשה החיצונית באצווה. הכותרות של שיחות ספציפיות חלות רק על אותה שיחה.

לדוגמה, אם מציינים כותרת Authorization לשיחה ספציפית, הכותרת חלה רק על השיחה הזו. אם מציינים כותרת הרשאה בבקשה החיצונית, הכותרת תחול על כל הקריאות הנפרדות, אלא אם הן יבטלו אותה באמצעות כותרות הרשאות משלהן.

כשהשרת מקבל את הבקשה באצווה, הוא מחיל את הפרמטרים והכותרות של השאילתה החיצונית (לפי הכללים) על כל חלק, ולאחר מכן מתייחס לכל חלק כאילו היה בקשת HTTP נפרדת.

תשובה לבקשה באצווה

תגובת השרת היא תגובת HTTP רגילה יחידה עם סוג תוכן multipart/mixed. כל חלק הוא התשובה לאחת מהבקשות שבבקשה באצווה, באותו סדר כמו הבקשות.

בדומה לחלקים בבקשה, כל חלק בתשובה מכיל תגובת HTTP מלאה, כולל קוד סטטוס, כותרות וגוף. בדומה לחלקים שבבקשה, לפני כל חלק של תשובה מופיעה כותרת Content-Type שמסמנת את תחילת החלק.

אם לחלק מסוים בבקשה יש כותרת Content-ID, לחלק המתאים בתשובה יש כותרת Content-ID תואמת, עם הערך המקורי לפני המחרוזת response-, כמו בדוגמה הבאה.

הערה: השרת עשוי לבצע את הקריאות לפי סדר שאינו קבוע מראש. אל תסתמכו על כך שהן יבוצעו לפי הסדר שבו ציינתם אותן. אם רוצים להבטיח ששתי קריאות יתבצעו בסדר מסוים, אי אפשר לשלוח אותן בבקשה אחת. במקום זאת, צריך לשלוח את ההודעה הראשונה בנפרד, ואז להמתין לתשובה הראשונה לפני ששולחים את השנייה.

דוגמה

הדוגמה הבאה מציגה שימוש בקיבוץ באצווה של 'מודעות לרשת המדיה' Video 360 API

דוגמה לבקשה באצווה

POST /batch HTTP/1.1
Host: displayvideo.googleapis.com
Authorization: Bearer your_auth_code
Content-Type: multipart/mixed; boundary=batch_foobarbaz
Content-Length: total_content_length

--batch_foobarbaz
Content-Type: application/http
Content-Transfer-Encoding: binary
MIME-Version: 1.0
Content-ID: <item1:12930812@displayvideo.example.com>

PATCH /v1/advertisers/advertiser_id?updateMask=displayName&fields=advertiserId,displayName HTTP/1.1
Content-Type: application/json; charset=UTF-8
Authorization: Bearer your_auth_code

{
  "displayName": "Updated Advertiser Name"
}
--batch_foobarbaz
Content-Type: application/http
Content-Transfer-Encoding: binary
MIME-Version: 1.0
Content-ID: <item2:12930812@displayvideo.example.com>

PATCH /v1/advertisers/advertiser_id/lineItems/line_item_id?updateMask=displayName&fields=lineItemId,displayName HTTP/1.1
Content-Type: application/json; charset=UTF-8
Authorization: Bearer your_auth_code

{
  "displayName": "Updated Line Item Name"
}

--batch_foobarbaz--

דוגמה לתשובה באצווה

זוהי התשובה לבקשה לדוגמה שבקטע הקודם.

HTTP/1.1 200
Content-Length: response_total_content_length
Content-Type: multipart/mixed; boundary=batch_foobarbaz

--batch_foobarbaz
Content-Type: application/http
Content-ID: <response-item1:12930812@displayvideo.example.com>

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Content-Length: response_part_1_content_length

{
  "advertiserId": advertiser_id,
  "displayName": "Updated Advertiser Name"
}

--batch_foobarbaz
Content-Type: application/http
Content-ID: <response-item2:12930812@displayvideo.example.com>

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Content-Length: response_part_2_content_length

{
  "lineItemId": line_item_id,
  "displayName": "Updated Line Item Name"
}

--batch_foobarbaz--

שימוש בספריות לקוח

דוגמאות הקוד הבאות מדגימות איך לשלוח בקשות באצווה באמצעות ספריות הלקוח של Google APIs. מידע נוסף זמין במדריכים המתאימים למתחילים מידע על התקנת הספריות וההגדרה שלהן.

Java

Long advertiserId = advertiser-id;
List<Long> lineItemIds = Arrays.asList(line-item-id-1, line-item-id-2);

BatchRequest batch = service.batch();
JsonBatchCallback<LineItem> callback = new JsonBatchCallback<LineItem>() {
  public void onSuccess(LineItem lineItem, HttpHeaders responseHeaders) {
    System.out.printf("Line Item '%s' is now active.\n",
        lineItem.getName());
  }

  public void onFailure (GoogleJsonError error, HttpHeaders responseHeaders)
      throws IOException{
    System.out.printf("Error activating line item: %s\n", error.getMessage());
  }
};

LineItem activatedLineItem = new LineItem().setEntityStatus("ENTITY_STATUS_ACTIVE");

for (Long lineItemId: lineItemIds) {
  service.advertisers().lineItems().patch(advertiserId, lineItemId, activatedLineItem)
      .setUpdateMask("entityStatus").queue(batch, callback);
}
batch.execute();

Python

advertiser_id = advertiser-id
line_item_ids = [line-item-id-1, line-item-id-2]

def callback(request_id, response, exception):
    if exception is not None:
        print('Error activating line item "%s": %s' %
              request_id, exception)
    else:
        print('Line item "%s" is now active.' %
              response.get('name'))

batch = service.new_batch_http_request(callback=callback)

line_item_obj = {
    'entityStatus': 'ENTITY_STATUS_ACTIVE'
}

for line_item_id in line_item_ids:
    request = service.advertisers().lineItems().patch(
        advertiserId=advertiser_id,
        lineItemId=line_item_id,
        updateMask="entityStatus",
        body=line_item_obj
    )
    batch.add(request, request_id=line_item_id)

batch.execute()

PHP

$advertiserId = advertiser-id;
$lineItemIds = array(line-item-id-1, line-item-id-2);

// Enable batching on client and create current batch
$service->getClient()->setUseBatch(true);
$batch = $service->createBatch();

// Create line item with updated fields
$updatedLineItem = new Google_Service_DisplayVideo_LineItem();
$updatedLineItem->setEntityStatus('ENTITY_STATUS_ACTIVE');

// Create request parameter array with update mask
$optParams = array('updateMask' => 'entityStatus');

// Add each patch request to the batch
foreach($lineItemIds as $lineItemId) {
    $request = $this->service->advertisers_lineItems->patch(
        $advertiserId,
        $lineItemId,
        $updatedLineItem,
        $optParams
    );
    $requestId = $lineItemId;
    $batch->add($request, $requestId);
}

// Execute batch request
$results = $batch->execute();

// Iterate through results
foreach($results as $responseId => $lineItem) {
    $lineItemId = substr($responseId, strlen('response-') + 1);
    if ($lineItem instanceof Google_Service_Exception) {
        $e = $lineItem;
        printf(
            "Error activating line item '%s': %s\n",
            $lineItemId,
            $e->getMessage()
        );
    } else {
        printf("Line item '%s' is now active.\n", $lineItem->getName());
    }
}
$service->getClient()->setUseBatch(false);