ব্যাচ অনুরোধ পাঠান

এই নথিটি দেখায় যে কীভাবে আপনার ক্লায়েন্টকে সংযোগ করতে হবে তা কমাতে API কলগুলিকে একসাথে ব্যাচ করতে হয়।

এই নথিটি বিশেষভাবে জাভা ক্লায়েন্ট লাইব্রেরি ব্যবহার করে একটি ব্যাচ অনুরোধ করার বিষয়ে। .NET-এর জন্য Google API ক্লায়েন্ট লাইব্রেরিতে একটি মৌলিক উদাহরণও পাওয়া যায়। Google Play EMM API-এর ব্যাচ সিস্টেম OData ব্যাচ প্রসেসিং সিস্টেমের মতো একই HTTP সিনট্যাক্স ব্যবহার করে।

ওভারভিউ

Google Play EMM API-এর মাধ্যমে আপনার ক্লায়েন্টের প্রতিটি অনুরোধের ফলে একটি নির্দিষ্ট পরিমাণ ওভারহেড হয়। Google Play EMM API ব্যাচিং সমর্থন করে, আপনার ক্লায়েন্টকে একটি একক অনুরোধে একাধিক API কল করার অনুমতি দিতে।

এখানে এমন কিছু উদাহরণ রয়েছে যেখানে আপনি ব্যাচিং ব্যবহার করতে চাইতে পারেন:

  • একটি ডোমেন সবেমাত্র নথিভুক্ত করা হয়েছে এবং এখন আপলোড করার জন্য প্রচুর ডেটা রয়েছে৷
  • আপনার অ্যাপ্লিকেশন অফলাইনে থাকাকালীন একজন ব্যবহারকারী ডেটাতে পরিবর্তন করেছেন, তাই আপনার অ্যাপ্লিকেশনটিকে সার্ভারের সাথে প্রচুর স্থানীয় ডেটা সিঙ্ক্রোনাইজ করতে হবে৷

এই ধরনের ক্ষেত্রে, প্রতিটি কল আলাদাভাবে পাঠানোর পরিবর্তে আপনি একটি একক অনুরোধে তাদের একসাথে গ্রুপ করতে পারেন। এমনকি আপনি একাধিক ব্যবহারকারীর জন্য বা একাধিক Google API-এর জন্য গ্রুপ অনুরোধ করতে পারেন।

তবে, আপনি একটি একক ব্যাচের অনুরোধে 1000টি কলের মধ্যে সীমাবদ্ধ। আপনি যদি এর চেয়ে বেশি কল করতে চান তবে একাধিক ব্যাচের অনুরোধ ব্যবহার করুন।

ব্যাচের বিবরণ

একটি ব্যাচ অনুরোধ একটি JSON-RPC অনুরোধের সাথে মিলিত একাধিক API কল নিয়ে গঠিত। এই বিভাগটি ব্যাচের অনুরোধের সিনট্যাক্সকে বিস্তারিতভাবে বর্ণনা করে, নিম্নলিখিত বিভাগে একটি উদাহরণ সহ।

দ্রষ্টব্য : একত্রে ব্যাচ করা n অনুরোধের একটি সেট আপনার ব্যবহারের সীমা n অনুরোধ হিসাবে গণনা করে, একটি অনুরোধ হিসাবে নয়। ব্যাচ অনুরোধ প্রক্রিয়াকরণের আগে অনুরোধের একটি সেট আলাদা করা হয়.

একটি ব্যাচ অনুরোধের বিন্যাস

জাভা ক্লায়েন্ট লাইব্রেরিতে প্রতিটি Google Play EMM API কলের জন্য অনুরোধ তৈরি করার জন্য কল রয়েছে। উদাহরণস্বরূপ, একটি ডিভাইসে ইনস্টল করা সমস্ত অ্যাপ তালিকাভুক্ত করতে, আপনি নিম্নলিখিতগুলি ব্যবহার করবেন:

AndroidEnterprise enterprise = ...;
InstallsListResponse response = enterprise.installs().list(enterpriseId, userId, deviceId)
  .execute();

এখানে একটি অতিরিক্ত batch() কল রয়েছে যা বেশ কয়েকটি অনুরোধ সারিবদ্ধ করতে পারে, যেমনটি এখানে দেখা গেছে:

AndroidEnterprise enterprise = ...;
BatchRequest batchRequest = enterprise.batch();
enterprise.installs().list(enterpriseId, userId, deviceId1).queue(batchRequest, callback1);
enterprise.installs().list(enterpriseId, userId, deviceId2).queue(batchRequest, callback2);
enterprise.installs().list(enterpriseId, userId, deviceId3).queue(batchRequest, callback3);
batchRequest.execute();
যখন batchRequest.execute() কল করা হয়, তখন সমস্ত সারিবদ্ধ অনুরোধগুলি একবারে JSON অ্যারে হিসাবে সার্ভারে পাঠানো হয়। সার্ভার প্রতিটি অংশে বাইরের অনুরোধের ক্যোয়ারী প্যারামিটার এবং শিরোনাম (যথাযথ হিসাবে) প্রয়োগ করে এবং তারপর প্রতিটি অংশকে এমনভাবে আচরণ করে যেন এটি একটি পৃথক JSON অনুরোধ।

একটি ব্যাচ অনুরোধের প্রতিক্রিয়া

সার্ভার প্রতিটি পৃথক অনুরোধ চালায়, এবং ফলাফলকে একটি একক অ্যারের তৈরি একক প্রতিক্রিয়াতে গোষ্ঠীভুক্ত করে। ক্লায়েন্ট লাইব্রেরি এই প্রতিক্রিয়াটিকে পৃথক প্রতিক্রিয়াগুলিতে বিভক্ত করে, এবং প্রতিটিকে queue() এ পাঠানো কলব্যাক ফাংশনে পাঠানো হয়। কলব্যাক হল একটি ইন্টারফেস যা ব্যর্থতার জন্য একটি পদ্ধতি এবং সাফল্যের জন্য একটি পদ্ধতি নির্ধারণ করে। উদাহরণস্বরূপ, callback1 নিম্নলিখিত উদাহরণ হিসাবে প্রয়োগ করা হবে:

private class InstallsCallback implements JsonBatchCallback<InstallsListResponse> {

  @Override
  public void onSuccess(InstallsListResponse response, HttpHeaders responseHeaders) {
    ...
  }

  @Override
  public void onFailure(GoogleJsonError e, HttpHeaders responseHeaders) {
    ...
  }
}

দ্রষ্টব্য : সার্ভার যেকোনো ক্রমে আপনার কলগুলি সম্পাদন করতে পারে, তাই আপনার অনুরোধে উল্লেখিত ক্রম অনুসারে ফলাফল পাওয়ার উপর নির্ভর করবেন না। আপনি যদি নিশ্চিত করতে চান যে দুটি কল একটি প্রদত্ত ক্রমে হয়, আপনি সেগুলিকে একক অনুরোধে পাঠাতে পারবেন না; পরিবর্তে, প্রথম অনুরোধ নিজেই পাঠান, এবং দ্বিতীয়টি পাঠানোর আগে একটি প্রতিক্রিয়ার জন্য অপেক্ষা করুন।

উদাহরণ ব্যাচ অনুরোধ

নিম্নলিখিত উদাহরণটি দেখায় কিভাবে একটি প্রদত্ত ব্যবহারকারীর ডিভাইসে ইনস্টল করা সমস্ত অ্যাপ তালিকাভুক্ত করা যায়। প্রথম কলগুলি এন্টারপ্রাইজ এবং ব্যবহারকারীর আইডি প্রাপ্ত করতে ব্যবহৃত হয় এবং সেই অনুযায়ী ক্রমানুসারে কার্যকর করা আবশ্যক। একবার enterprise.devices().list() দিয়ে সমস্ত ডিভাইস আইডি প্রাপ্ত হয়ে গেলে, আমরা একবারে সমস্ত ব্যবহারকারীর ডিভাইসে সমস্ত অ্যাপ্লিকেশন পুনরুদ্ধার করার জন্য একটি ব্যাচ অনুরোধ করতে পারি।

package com.google.playenterprise.example;

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.batch.BatchRequest;
import com.google.api.client.googleapis.batch.json.JsonBatchCallback;
import com.google.api.client.googleapis.json.GoogleJsonError;
import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.androidenterprise.AndroidEnterprise;
import com.google.api.services.androidenterprise.AndroidEnterprise.Installs;
import com.google.api.services.androidenterprise.AndroidEnterpriseScopes;
import com.google.api.services.androidenterprise.model.Device;
import com.google.api.services.androidenterprise.model.DevicesListResponse;
import com.google.api.services.androidenterprise.model.Enterprise;
import com.google.api.services.androidenterprise.model.Install;
import com.google.api.services.androidenterprise.model.InstallsListResponse;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * Lists all the apps installed on all devices of a given user.
 */
public class ListAllInstalls {
  private AndroidEnterprise enterprise;
  private final List<String> installList = new ArrayList<>();

  public static void main(String[] argv) throws Exception {
    if (argv.length != 2) {
      throw new IllegalArgumentException("Usage: ListAllInstalls email jsonFilename");
    } else if (!argv[0].contains("@")) {
      throw new IllegalArgumentException("First parameter should be a valid email.");
    }
    new ListAllInstalls().run(argv[0], argv[1]);
  }

  private void run(String userEmail, String jsonKeyPath) throws IOException {
    enterprise = createAndroidEnterprise(jsonKeyPath);

    // Get the enterprise id, user id, and user devices.
    String domain = userEmail.split("@")[1];
    List<Enterprise> results = enterprise.enterprises().list(domain).execute().getEnterprise();
    if (results.isEmpty()) {
      throw new RuntimeException("No enterprise found.");
    }
    String enterpriseId = results.get(0).getId();
    String userId = enterprise
        .users()
        .list(enterpriseId, userEmail)
        .execute()
        .getUser()
        .get(0)
        .getId();
    List<Device> devices = getAllDevices(enterpriseId, userId);

    // Batch all calls to get installs on all user devices.
    gatherAllInstalls(enterpriseId, userId, devices);

    for (String entry : installList) {
      // Do something.
      System.out.println(entry);
    }
  }

  private List<Device> getAllDevices(String enterpriseId, String userId) throws IOException {
    DevicesListResponse devices = enterprise.devices().list(enterpriseId, userId).execute();
    return devices.getDevice();
  }

  private void gatherAllInstalls(String enterpriseId, String userId, List<Device> devices)
      throws IOException {
    BatchRequest batchRequest = enterprise.batch();
    for (Device device : devices) {
      Installs.List list = enterprise
          .installs().list(enterpriseId, userId, device.getAndroidId());
      // Each callback can take the specifics of the associated request in its constructor.
      list.queue(batchRequest, new InstallsCallback(device.getAndroidId()));
    }
    // Executes all the queued requests and their callbacks, single-threaded.
    batchRequest.execute();
  }

  private class InstallsCallback extends JsonBatchCallback<InstallsListResponse> {
    private final String androidId;

    InstallsCallback(String androidId) {
      this.androidId = androidId;
    }

    @Override
    public void onSuccess(InstallsListResponse response, HttpHeaders responseHeaders) {
      for (Install install : response.getInstall()) {
        installList.add(androidId + "," + install.getProductId());
      }
    }

    @Override
    public void onFailure(GoogleJsonError e, HttpHeaders responseHeaders) {
      throw new RuntimeException("Error fetching a device");
    }
  }

  private AndroidEnterprise createAndroidEnterprise(String jsonKeyPath) throws IOException {
    HttpTransport httpTransport = new NetHttpTransport();
    JsonFactory jsonFactory = new JacksonFactory();

    InputStream is = new BufferedInputStream(new FileInputStream(jsonKeyPath));
    final Credential credential = GoogleCredential.fromStream(is, httpTransport, jsonFactory)
        .createScoped(AndroidEnterpriseScopes.all());

    HttpRequestInitializer httpRequestInitializer = new HttpRequestInitializer() {
      @Override
      public void initialize(HttpRequest request) throws IOException {
        credential.initialize(request);
      }
    };
    return new AndroidEnterprise.Builder(httpTransport, jsonFactory, httpRequestInitializer)
        .build();
  }
}