التخزين المؤقت باستخدام Firebase

يحتوي Looker Studio على نظام ذاكرة تخزين مؤقت خاص للتقارير. عند إنشاء أداة الربط، يمكنك تنفيذ ذاكرة تخزين مؤقت مخصّصة لتسهيل إنشاء التقارير بشكل أسرع وتجنُّب حدود المعدّل لكل طلب في واجهة برمجة التطبيقات.

على سبيل المثال، أنت بصدد إنشاء أداة ربط توفّر بيانات الطقس السابقة خلال الأيام السبعة الماضية لرمز بريدي محدّد. أصبح الموصّل الخاص بك شائعًا جدًا، ولكن واجهة برمجة التطبيقات الخارجية التي تجلب منها البيانات لديها حدود صارمة على معدّل الطلبات. تعدّل واجهة برمجة التطبيقات بياناتها مرة واحدة فقط في اليوم، لذا ليس من الضروري استرداد البيانات نفسها عدة مرات خلال اليوم لرمز بريدي معيّن. باستخدام دليل الحلول هذا، يمكنك تنفيذ ذاكرة تخزين مؤقت يومية لكل رمز بريدي.

المتطلبات

  • قاعدة بيانات Firebase في الوقت الفعلي إذا لم يكن لديك إذن بالوصول إلى مشروع، أنشئ مشروعًا على Google Cloud Platform (GCP) واتّبِع دليل بدء الاستخدام لإنشاء مثيل خاص بك من قاعدة بيانات Firebase Realtime Database.
  • حساب خدمة Google Cloud Platform (GCP) لقراءة البيانات وكتابتها من "قاعدة بيانات Firebase في الوقت الفعلي"
  • أداة ربط من إنشاء المنتدى تجلب البيانات من مصدر.

القيود

  • لا يمكن استخدام هذا الحلّ مع خدمات Looker Studio المتقدّمة. عند استخدام الخدمات المتقدّمة في Looker Studio، لن يتمكّن رمز موصّل البيانات في Apps Script من الوصول إلى البيانات. وبالتالي، لا يمكنك تخزين البيانات مؤقتًا باستخدام Apps Script.
  • لا يمكن لمحرّري التقارير ومشاهديه إعادة ضبط ذاكرة التخزين المؤقت المحدّدة هذه.

الحل

تنفيذ حساب خدمة

  1. أنشئ حساب خدمة في مشروعك على Google Cloud.
  2. تأكَّد من أنّ حساب الخدمة هذا لديه إذن وصول إلى BigQuery في مشروع السحابة الإلكترونية.
    • أدوار "إدارة الهوية وإمكانية الوصول" (IAM) المطلوبة: Firebase Admin
  3. نزِّل ملف JSON للحصول على مفاتيح حسابات الخدمة. خزِّن محتوى الملف في مواقع النص البرمجي لمشروع الموصل. بعد إضافة المفاتيح، يجب أن تبدو على النحو التالي في واجهة مستخدم Apps Script:
    حفظ مفاتيح حساب الخدمة في "مواقع النص البرمجي"
  4. أدرِج مكتبة OAuth2 لبرمجة التطبيقات في مشروعك على "برمجة التطبيقات".
  5. نفِّذ رمز OAuth2 المطلوب لحساب الخدمة:
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'
    ]);
}

تنفيذ الرمز البرمجي للقراءة والكتابة من Firebase

ستستخدم Firebase Database REST API للقراءة والكتابة في قاعدة بيانات Firebase Realtime. ينفّذ الرمز التالي الطرق اللازمة للوصول إلى واجهة برمجة التطبيقات هذه.

تنفيذ getData()

يجب أن يبدو هيكل رمز getData() الحالي بدون التخزين المؤقت على النحو التالي:

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
  };
}

لاستخدام التخزين المؤقت في رمز getData()، اتّبِع الخطوات التالية:

  1. تحديد "الجزء" أو "الوحدة" من البيانات التي يجب تخزينها مؤقتًا
  2. أنشئ مفتاحًا فريدًا لتخزين الحدّ الأدنى من وحدات البيانات في ذاكرة التخزين المؤقت.
    في مثال التنفيذ، يتم استخدام zipcode من configparams كمفتاح.
    اختياري: بالنسبة إلى ذاكرة التخزين المؤقت لكل مستخدم، أنشئ مفتاحًا مركّبًا باستخدام المفتاح الأساسي وهوية المستخدم. مثال على التنفيذ:
    js var baseKey = getBaseKey(request); var userEmail = Session.getEffectiveUser().getEmail(); var hasheduserEmail = getHashedValue(userEmail); var compositeKey = baseKey + hasheduserEmail;

  3. في حال توفّر بيانات مخزَّنة مؤقتًا، تحقَّق ممّا إذا كانت حديثة.
    في المثال، يتم حفظ البيانات المخزّنة مؤقتًا لرمز بريدي محدّد مع التاريخ الحالي. عند استرجاع البيانات من ذاكرة التخزين المؤقت، يتم التحقّق من تاريخ ذاكرة التخزين المؤقت مقارنةً بالتاريخ الحالي.

    var cacheForZipcode = {
      data: <data being cached>,
      ymd: <current date in YYYYMMDD format>
    }
    
  4. في حال عدم توفّر بيانات مخزَّنة مؤقتًا أو إذا كانت البيانات المخزَّنة مؤقتًا قديمة، يمكنك جلب البيانات من المصدر وتخزينها مؤقتًا.

في المثال التالي، يتضمّن main.js الرمز getData() مع تفعيل التخزين المؤقت.

مثال على الرمز

مراجع إضافية

يسهّل Chrome UX Connector إنشاء لوحة بيانات استنادًا إلى جدول BigQuery يبلغ حجمه 20 غيغابايت تقريبًا، وذلك لآلاف المستخدمين. يستخدم هذا الموصل قاعدة بيانات Firebase في الوقت الفعلي بالإضافة إلى خدمة التخزين المؤقت في "برمجة تطبيقات Google" لاتّباع نهج التخزين المؤقت ذي الطبقتين. يمكنك الاطّلاع على الرمز لمعرفة تفاصيل التنفيذ.