Cache com o Firebase

O Looker Studio tem o próprio sistema de cache para relatórios. Ao criar seu conector, você pode implementar um cache personalizado para otimizar relatórios e evitar as limitações de taxa de APR.

Por exemplo, você está criando um conector que fornece dados meteorológicos históricos nos últimos sete dias para um CEP específico. Seu conector está ficando muito usados, mas a API externa da qual você está buscando os dados tem uma taxa limites. A API só atualiza seus dados diariamente, portanto, para um CEP específico, há não é preciso buscar os mesmos dados várias vezes em um dia. Usar este é possível implementar um cache diário para cada CEP.

Requisitos

  • Um Firebase Realtime Database. Se você não tem acesso a um, crie um projeto do Google Cloud Platform (GCP) e siga o guia de primeiros passos para criar sua própria instância do Firebase Realtime Database.
  • Uma conta de serviço do GCP para ler e gravar dados do Firebase Realtime no seu banco de dados.
  • Um conector da comunidade que busca dados de uma origem.

Limitações

  • Esta solução não pode ser usada com os serviços avançados do Looker Studio. Quando usar o Advanced Services do Looker Studio, o código do conector em apps; O script não tem acesso aos dados. Portanto, não é possível armazenar os dados usando o Apps Script.
  • Editores e visualizadores de relatórios não podem redefinir esse cache específico.

Solução

Implementar uma conta de serviço

  1. Crie uma conta de serviço no seu projeto do Google Cloud.
  2. Essa conta precisa ter acesso ao BigQuery no projeto do Google Cloud.
    • Papéis de gerenciamento de identidade e acesso (IAM) necessários: Firebase Admin
  3. Faça o download do arquivo JSON para usar as chaves das contas de serviço. Armazene o conteúdo do arquivo nas propriedades de script do projeto do seu conector. Depois de adicionar o valor-chave serão semelhantes a esta na interface do Apps Script:
    Salvar chaves de conta de serviço nas propriedades de script
  4. Inclua a biblioteca OAuth2 para Apps Script no seu projeto do Apps Script.
  5. Implemente o código OAuth2 necessário para a conta de serviço:
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 o código para ler e gravar no Firebase

Você usará a API REST do Firebase Database para ler e gravar no Firebase Realtime Database. O código a seguir implementa os métodos necessários para acessar essa API.

Implementar o código getData()

A estrutura do seu código getData() atual sem armazenamento em cache terá esta aparência:

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 usar o armazenamento em cache no seu código getData(), siga estas etapas:

  1. Defina a "unidade" ou o "bloco" de dados que será armazenado em cache.
  2. Crie uma chave exclusiva para armazenar a unidade mínima de dados em cache.
    No exemplo de implementação, o zipcode de configparams está sendo usado como chave.
    Opcional: para o cache por usuário, crie uma chave composta de chave-base e identidade do usuário. Exemplo de implementação:
    js var baseKey = getBaseKey(request); var userEmail = Session.getEffectiveUser().getEmail(); var hasheduserEmail = getHashedValue(userEmail); var compositeKey = baseKey + hasheduserEmail;

  3. Se houver dados armazenados em cache, verifique se ele é recente.
    No exemplo, os dados armazenados em cache para um CEP específico são salvos com a data atual. Quando os dados são recuperados do cache, a data para o cache é comparada à data atual.

    var cacheForZipcode = {
      data: <data being cached>,
      ymd: <current date in YYYYMMDD format>
    }
    
  4. Se os dados em cache não existirem ou não forem atualizados, faça a busca dos dados da origem e armazená-los em cache.

No exemplo a seguir, main.js inclui o código getData() com armazenamento em cache. implementado.

Exemplo de código

Outros recursos

O conector da UX no Chrome permite que milhares de usuários utilizem um painel com base em uma tabela do BigQuery com aproximadamente 20 GB. Esse conector usa o Firebase Realtime Database com o serviço de cache do Apps Script para armazenamento em cache em duas camadas. Veja o código para saber mais sobre a implementação.