Implementar una caché personalizada para un conector con Firebase Realtime Database

Data Studio tiene su propio sistema de caché para generar informes. Cuando crees tu conector, puedes implementar una caché personalizada para conseguir que los informes sean más rápidos y evitar que se apliquen los límites de frecuencia de la API.

Supongamos que creas un conector que proporciona un historial de datos meteorológicos de los últimos 7 días, correspondientes a un código postal concreto. El conector se utiliza mucho, pero la API externa de la que obtienes los datos tiene unos límites de frecuencia estrictos. La API actualiza sus datos una sola vez al día, por lo que no es necesario obtener los mismos datos de un código postal varias veces en un mismo día. Con esta guía de soluciones, puedes implementar una caché diaria por cada código postal.

Requisitos

  • Firebase Realtime Database. Si no tienes acceso, crea un proyecto de Google Cloud Platform (GCP) y sigue las instrucciones de la sección Comenzar de la guía para crear tu propia instancia de Firebase Realtime Database.
  • Una cuenta de servicio de GCP para leer y escribir datos de Firebase Realtime Database.
  • Un conector comunitario que obtenga datos de una fuente.

Limitaciones

  • Esta solución no se puede usar con los servicios avanzados de Data Studio. Cuando utilizas los servicios avanzados de Data Studio, el código del conector en Apps Script no tiene acceso a los datos, por lo que no puedes almacenarlos en caché mediante Apps Script.
  • Los editores y lectores de los informes no pueden borrar esta caché.

Solución

Implementar una cuenta de servicio

  1. Crea una cuenta de servicio en el proyecto de Google Cloud.
  2. Asegúrate de que esa cuenta de servicio tenga acceso a BigQuery en el proyecto de Cloud.
    • Funciones de gestión de identidades y accesos necesarias: Firebase Admin
  3. Descarga el archivo JSON para obtener las claves de las cuentas de servicio. Guarda el contenido del archivo en las propiedades de la secuencia de comandos del proyecto de tu conector. Después de añadir las claves, quedará más o menos así en la interfaz de Apps Script:
    Guardar claves de cuentas de servicio en propiedades de la secuencia de comandos
  4. Incluye la biblioteca OAuth2 de Apps Script en tu proyecto de Apps Script.
  5. Implementa el código OAuth2 necesario de la cuenta de servicio:
firestore-cache/src/firebase.js
var SERVICE_ACCOUNT_CREDS = 'SERVICE_ACCOUNT_CREDS';
var SERVICE_ACCOUNT_KEY = 'private_key';
var SERVICE_ACCOUNT_EMAIL = 'client_email';
var BILLING_PROJECT_ID = 'project_id';

var scriptProperties = PropertiesService.getScriptProperties();

/**
 * Copy the entire credentials JSON file from creating a service account in GCP.
 * Service account should have `Firebase Admin` IAM role.
 */
function getServiceAccountCreds() {
  return JSON.parse(scriptProperties.getProperty(SERVICE_ACCOUNT_CREDS));
}

function getOauthService() {
  var serviceAccountCreds = getServiceAccountCreds();
  var serviceAccountKey = serviceAccountCreds[SERVICE_ACCOUNT_KEY];
  var serviceAccountEmail = serviceAccountCreds[SERVICE_ACCOUNT_EMAIL];

  return OAuth2.createService('FirebaseCache')
    .setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
    .setTokenUrl('https://accounts.google.com/o/oauth2/token')
    .setPrivateKey(serviceAccountKey)
    .setIssuer(serviceAccountEmail)
    .setPropertyStore(scriptProperties)
    .setCache(CacheService.getScriptCache())
    .setScope([
      'https://www.googleapis.com/auth/userinfo.email',
      'https://www.googleapis.com/auth/firebase.database'
    ]);
}

Implementar código para leer y escribir en Firebase

Tendrás que utilizar la API REST de Firebase Database para leer y escribir en una base de datos de Firebase Realtime Database. El siguiente código implementa los métodos necesarios para acceder a esta API.

Implementar getData()

El código getData() sin almacenamiento en caché debería tener una estructura similar a esta:

firestore-cache/src/without-caching.js
/*
 * This file is only to demonstrate how the `getData()` fucntion would look
 * like without the Firebase Realtime Database caching. It is not a part of
 * the connector code and should not be included in Apps Script / Clasp.
 */

function getData(request) {
  var requestedFields = getFields().forIds(
    request.fields.map(function(field) {
      return field.name;
    })
  );

  var fetchedData = fetchAndParseData(request);
  var data = getFormattedData(fetchedData, requestedFields);

  return {
    schema: requestedFields.build(),
    rows: data
  };
}

Para utilizar el almacenamiento en caché en el código getData(), sigue estos pasos:

  1. Determina el "bloque" o la "unidad" de datos que se debe almacenar en caché.
  2. Crea una clave única para almacenar en caché la unidad mínima de datos.
    En el ejemplo de implementación, se utiliza zipcode desde configparams como clave.
    (Opcional): Si la caché es de usuario, crea una clave compuesta con la clave base y la identidad de usuario. Ejemplo de implementación:
    js var baseKey = getBaseKey(request); var userEmail = Session.getEffectiveUser().getEmail(); var hasheduserEmail = getHashedValue(userEmail); var compositeKey = baseKey + hasheduserEmail;

  3. Si hay datos almacenados en caché, comprueba que la caché esté actualizada.
    En el ejemplo, los datos almacenados en caché de un código postal se guardan con la fecha actual. Cuando se recuperan los datos de la caché, se aplica la fecha actual.

    var cacheForZipcode = {
      data: <data being cached>,
      ymd: <current date in YYYYMMDD format>
    }
    
  4. Si no hay datos almacenados en caché o no están actualizados, tendrás que obtenerlos de la fuente y almacenarlos en caché.

En el ejemplo siguiente, main.js incluye el código getData() con el almacenamiento en caché implementado.

Código de ejemplo

Otros recursos

El conector de Chrome UX proporciona a miles de usuarios un panel de control basado en una tabla de BigQuery de aproximadamente 20 GB. Este conector usa Firebase Realtime Database junto con el servicio de almacenamiento en caché de Apps Script para ofrecer una arquitectura de caché de doble capa. Consulta el código para obtener más detalles acerca de la implementación.