Créer des requêtes HTTP par lot pour Data Catalog

Chaque connexion HTTP effectuée par votre application entraîne une certaine surcharge. Les requêtes de l'API Data Catalog acceptent les requêtes par lot, ce qui vous permet de combiner plusieurs appels d'API en une seule requête HTTP. Vous pouvez utiliser des requêtes HTTP par lot si vous avez de nombreuses petites requêtes à effectuer et que vous souhaitez minimiser la surcharge. Notez que le traitement par lot réduit la surcharge, mais que les requêtes au sein d'un lot sont toujours comptabilisées comme requêtes multiples dans le cadre des quotas de l'API.

Pour obtenir des informations génériques sur l'utilisation des requêtes HTTP par lot avec Google Cloud, consultez la documentation du client Python de l'API Google.

Créer des requêtes HTTP par lot en Python

Pour créer ou manipuler des entrées dans Data Catalog à l'aide de requêtes par lot, vous devez d'abord rechercher les entrées que vous souhaitez modifier à l'aide de catalog.search() ou entries.lookup().

Ensuite, procédez comme suit pour créer une requête HTTP par lot à l'aide de l'API Google Python :

  1. Créez un objet BatchHttpRequest en appelant new_batch_http_request() ou avec le constructeur BatchHttpRequest(). Vous pouvez transmettre un rappel, qui sera appelé en réponse à chaque requête.
  2. Appelez add() sur l'objet BatchHttpRequest pour chaque requête que vous souhaitez exécuter. Si vous avez transmis un rappel lors de la création de votre objet BatchHttpRequest, chaque add() peut inclure des paramètres à transmettre au rappel.
  3. Après avoir ajouté les requêtes, appelez execute() sur l'objet BatchHttpRequest pour les exécuter. La fonction execute() est bloquée jusqu'à ce que tous les rappels aient été appelés.

Les requêtes dans un objet BatchHttpRequest peuvent être exécutées en parallèle. Il n'existe aucune garantie quant à l'ordre d'exécution. Cela signifie que les requêtes d'un même lot ne doivent pas dépendre les unes des autres. Par exemple, vous ne devez pas créer EntryGroup et Entry lui appartenant dans la même requête, car la création de Entry peut s'exécuter avant la création de EntryGroup (ce qui cause l'échec de l'exécution).

Requêtes par lot avec des points de terminaison régionaux

Lorsque vous utilisez des requêtes par lot HTTP avec des points de terminaison d'API régionaux Data Catalog, toutes les requêtes API d'un lot doivent appartenir à la même région. Lors de l'exécution du lot, vous devez appeler le point de terminaison régional approprié. Par exemple, si vos ressources sont dans us-central1, appelez https://us-central1-datacatalog.googleapis.com/batch.

API indépendantes de la région

Les API indépendantes des régions (telles que catalog.lookup() et entries.search()) peuvent être regroupées, mais ne doivent pas être regroupées avec des API dépendantes de la région. Pour les API indépendantes de la région, utilisez le point de terminaison : https://datacatalog.googleapis.com/batch.

Exemple

Cet exemple d'application Python montre comment utiliser une requête HTTP par lot pour créer plusieurs tags à partir d'un modèle de tag à l'aide de l'API Data Catalog.

 
from googleapiclient.discovery import build
from googleapiclient.http import BatchHttpRequest
from oauth2client.service_account import ServiceAccountCredentials
import uuid

#-------------------------------------------------------------#
# 0. Helper and initialization logic
#-------------------------------------------------------------#

# Set the environment configuration.
service_key_file_location = '[SA_PATH]'

project_id = '[MY_PROJECT_ID]'

# Helper container to store results.
class DataContainer:
    def __init__(self):
        self.data = {}

    def callback(self, request_id, response, exception):
        if exception is not None:
            print('request_id: {}, exception: {}'.format(request_id, str(exception)))
            pass
        else:
            print(request_id)
            self.data[request_id] = response


# Helper function to build the Discovery Service config.
def get_service(api_name, api_version, scopes, key_file_location):
    """
    Get a service that communicates to a Google API.

    Args:
        api_name: The name of the API to connect to.
        api_version: The API version to connect to.
        scopes: A list auth scopes to authorize for the application.
        key_file_location: The path to a valid service account JSON key file.

    Returns:
        A service that is connected to the specified API.
    """
    credentials = ServiceAccountCredentials.from_json_keyfile_name(
        key_file_location, scopes=scopes)

    # Build the service object.
    service = build(api_name, api_version, credentials=credentials)

    return service

# Helper function to create a UUID for each request
def generated_uui():
    return str(uuid.uuid4())

def create_batch_request(callback):
    # For more info on supported regions
    # check: https://cloud.google.com/data-catalog/docs/concepts/regions

    region='us-datacatalog.googleapis.com'

    return BatchHttpRequest(batch_uri='https://{}/batch'.format(region), callback=callback)

container = DataContainer()

# Scope to set up the Discovery Service config.
scope = 'https://www.googleapis.com/auth/cloud-platform'

# Create service.
service = get_service(
    api_name='datacatalog',
    api_version='v1',
    scopes=[scope],
    key_file_location=service_key_file_location)

# Create the batch request config.
batch = create_batch_request(container.callback)

#-------------------------------------------------------------#
# 1. Start by fetching a list of entries using search call
#-------------------------------------------------------------#

# Create the search request body.
# This example searches for all BigQuery tables in a project.
search_request_body = {
  'query': 'type=TABLE system=BIGQUERY',
  'scope': {'includeProjectIds': [project_id]}
}

# Generated a unique ID for the request.
request_id = generated_uui()

# Add the request to the batch client.
batch.add(service.catalog().search(body=search_request_body), request_id=request_id)

# Execute the batch request.
batch.execute()

# Uncomment to verify the full response from search.
# print(container.data)

response = container.data[request_id]

results = response['results']

first_table = results[0]

# Verify that a first table is present.
print(first_table)

second_table = results[1]

# Verify that a second table is present
print(second_table)

#-------------------------------------------------------------------#
# 2. Send the batch request to attach tags over the entire result set
#-------------------------------------------------------------------#

# Create a new container
container = DataContainer()

# Create a new batch request
batch = create_batch_request(container.callback)

# Set the template name config
template_name = 'projects/[MY_PROJECT_ID]/locations/[MY-LOCATION]/tagTemplates/[MY-TEMPLATE-NAME]'

for result in results:
    # Generated a unique id for request.
    request_id = generated_uui()

    # Add the entry name as the tag parent.
    parent=result['relativeResourceName']

    # Create the tag request body.
    create_tag_request_body = {
      'template': template_name,
       # CHANGE for your template field values.
      'fields': {'etl_score': {'doubleValue': 0.5}}
    }

    # Add requests to the batch client.
    batch.add(service.projects().locations().
              entryGroups().entries().tags().
              create(body=create_tag_request_body,
                     parent=parent),
              request_id=request_id)

# Execute the batch request.

# Since the Batch Client works with regions
# If you receive [HttpError 400 errors]
# 1. Verify the region you used to create the Batch client
# 2. Verify the region where the Entry is located.
# 3. verify the region of the parent tag template used by the tag.

batch.execute()

# Uncomment to verify the full response from tag creation.
# print(container)