เตรียม Firebase Extensions สำหรับการย้ายข้อมูลไปยัง Cloud Functions

คู่มือนี้จะแสดงวิธีย้ายข้อมูลส่วนขยายจากสภาพแวดล้อม Firebase Extensions ที่เลิกใช้งานแล้วไปยังฟังก์ชันที่ผู้ใช้ ติดตั้งและทำให้ใช้งานได้ในฐานของโค้ด Cloud Functions for Firebase (รุ่นที่ 2) ของตนเอง

นี่คือเส้นทางการย้ายข้อมูลที่แนะนำ Firebase จะดูแลรายการ ส่วนขยายที่มีฟังก์ชันเทียบเท่าอย่างเป็นทางการใน npm และคู่มือนี้จะแนะนำขั้นตอนการ สร้างฟังก์ชันของคุณ

เราจะใช้ส่วนขยาย Stream Firestore to BigQuery (firestore-bigquery-export) เป็นตัวอย่างตลอดทั้งคู่มือนี้ แต่ละส่วนจะจบลงด้วยตัวอย่างการทำงาน ที่แสดงลักษณะของส่วนขยายก่อนการย้ายข้อมูลและหลังการย้ายข้อมูลในรูปแบบแพ็กเกจ @firebase/firestore-bigquery-export

ลงชื่อสมัครใช้เพื่อรับข้อมูลและความช่วยเหลือเพิ่มเติมเกี่ยวกับการย้ายข้อมูลส่วนขยาย

หากมีคำถามเกี่ยวกับวิธีย้ายข้อมูลจาก Firebase Extensions โปรด ติดต่อเราที่ firebase-extensions-migrator-support-external@google.com นอกจากนี้ เราจะส่งอีเมลถึงกลุ่มนี้เมื่ออัปเดตคู่มือด้วยข้อมูลเพิ่มเติมเกี่ยวกับการ จัดแพ็กเกจ การทดสอบ และการเผยแพร่ฟังก์ชันรุ่นที่ 2

หากต้องการเข้าร่วมกลุ่มนี้ ให้ส่งข้อความไปที่ firebase-extensions-migrator-support-external+subscribe@google.com, ซึ่งจะตอบกลับด้วยอีเมลคำขอเป็นสมาชิก คุณต้องตอบกลับอีเมลดังกล่าว ไม่ใช่คลิกปุ่ม "เข้าร่วมกลุ่มนี้"

ก่อนเริ่มต้น

คุณจะใช้ฟีเจอร์ต่อไปนี้ของ Cloud Functions เพื่อทำการย้ายข้อมูลนี้ให้เสร็จสมบูรณ์

  • การกำหนดค่าแบบมีพารามิเตอร์. พารามิเตอร์แต่ละรายการที่คุณประกาศใน extension.yaml จะกลายเป็นพารามิเตอร์ที่กำหนดไว้ในโค้ดแพ็กเกจ

  • บทบาท IAM และ API ที่จำเป็นแบบประกาศ บทบาทแต่ละบทบาทที่คุณประกาศใน extension.yaml จะกลายเป็นการเรียก requiresRole(...) และ API แต่ละรายการจะกลายเป็นการเรียก requiresAPI(...) ในโค้ดฟังก์ชัน เมื่อทำให้ใช้งานได้ Firebase CLI จะมอบบทบาทที่ประกาศไว้ให้กับบัญชีบริการรันไทม์ที่มีการจัดการ และเปิดใช้ API ที่ประกาศไว้ในนามของคุณ

  • เหตุการณ์ในวงจรของฐานของโค้ด Cloud Functions Cloud Functions ฐานของโค้ดรองรับเหตุการณ์ในวงจรที่คล้ายกับFirebase Extensionsแล้ว ประกาศการตั้งค่าเวลาติดตั้งและเวลาอัปเดตด้วยฮุกวงจร afterFirstDeploy(...) และ afterRedeploy(...) ซึ่งจะแทนที่ lifecycleEvents ที่คุณประกาศใน extension.yaml

ตรวจสอบส่วนขยาย

เริ่มต้นด้วยการ ตรวจสอบ ส่วนขยาย ซึ่งเป็นรายการที่สมบูรณ์ของทุกสิ่งที่ส่วนขยายประกาศ จัดส่ง และจัดทำเอกสาร เพื่อให้ทุกพฤติกรรมมีปลายทางที่กำหนดไว้ในฟังก์ชันรุ่นที่ 2 และไม่มีข้อมูลสูญหายในการย้ายข้อมูล

ตรวจสอบแต่ละรายการต่อไปนี้และจดบันทึกสิ่งที่คุณพบ

  • extension.yamlซึ่งประกาศพารามิเตอร์ ฟังก์ชัน เหตุการณ์ บทบาท IAM, API ที่จำเป็น, ข้อมูลลับ และฮุกวงจร

  • functions/ซึ่งมีโค้ดฟังก์ชัน การขึ้นต่อกัน การกำหนดค่าบิลด์ ทริกเกอร์ และฟังก์ชันคิวงาน

  • README.md, PREINSTALL.md และ POSTINSTALL.md ซึ่งมีขั้นตอนการตั้งค่า คำเตือน และหมายเหตุเกี่ยวกับการเรียกเก็บเงิน

  • scripts/ซึ่งมีเครื่องมือสำหรับการนำเข้า การเติมข้อมูลย้อนหลัง IAM การซ่อมแซม หรือการย้ายข้อมูล รวมถึงเครื่องมืออื่นๆ ที่คุณจัดส่งพร้อมกับส่วนขยาย

จากนั้นสำหรับแต่ละรายการใน extension.yaml ให้ตัดสินใจว่าจะวางรายการนั้นไว้ที่ใดในแพ็กเกจ npm

  • แปลงการกำหนดค่าของผู้ใช้เป็น Cloud Functions พารามิเตอร์ (ส่วนที่ 5)

  • แปลงข้อมูลลับเป็นข้อมูลลับ Cloud Functions (ส่วนที่ 6)

  • แปลงบทบาท IAM เป็นการประกาศ requiresRole(...) (ส่วนที่ 8)

  • แปลง Google API ที่จำเป็นเป็นการประกาศ requiresAPI(...) ตามความเหมาะสม (ส่วนที่ 8)

  • แปลงฮุกการติดตั้งและการอัปเดตเป็นการประกาศ afterFirstDeploy(...) และ afterRedeploy(...) (ส่วนที่ 8)

ตัวอย่างการทำงาน: Stream Firestore to BigQuery

การอ่าน firestore-bigquery-export/extension.yaml และฟังก์ชันต่างๆ จะทำให้ได้ข้อมูลต่อไปนี้

ใน extension.yaml จำนวน / ค่า ตำแหน่งที่วาง
params 25 (COLLECTION_PATH, DATASET_ID, TABLE_ID, DATASET_LOCATION, VIEW_TYPE, …) Cloud Functions พารามิเตอร์ (ส่วนที่ 5)
apis bigquery.googleapis.com requiresAPI(...) (ส่วนที่ 7)
roles bigquery.dataEditor, datastore.user, bigquery.user requiresRole(...) (ส่วนที่ 7)
resources ทริกเกอร์เหตุการณ์ 1 รายการ (fsexportbigquery) + ฟังก์ชันคิวงาน (initBigQuerySync, setupBigQuerySync) ฟังก์ชันแพ็กเกจที่ส่งออก (ส่วนที่ 3)
lifecycleEvents onInstall → initBigQuerySync; onUpdate / onConfigure → setupBigQuerySync afterFirstDeploy / afterRedeploy (ส่วนที่ 9)
scripts/ import/ (backfill), gen-schema-view/ เก็บไว้เป็นสคริปต์ (ไม่อยู่ในขอบเขตของคู่มือนี้)

ส่วนขยายไม่ได้ประกาศพารามิเตอร์ประเภทข้อมูลลับ จึงไม่มีสิ่งใดให้ย้ายข้อมูลในส่วนที่ 6 ของคู่มือนี้ ทริกเกอร์เหตุการณ์เป็นรุ่นที่ 2 อยู่แล้ว มีเพียงฟังก์ชันคิวงานเท่านั้นที่ยังคงเป็นรุ่นที่ 1 (เกี่ยวข้องในส่วนที่ 3)

อัปเดต package.json

อัปเดตไฟล์ package.json ของส่วนขยาย หากย้ายข้อมูลส่วนขยายเดียว ไฟล์นี้จะเป็น package.json ระดับราก หากย้ายข้อมูลส่วนขยายหลายรายการในที่เก็บเดียว ให้สร้างแพ็กเกจของตัวเองสำหรับส่วนขยายแต่ละรายการ

เวอร์ชัน SDK ขั้นต่ำ ประกาศ firebase-functions >= 7.3 และ firebase-admin >= 14.2.0 เป็นการขึ้นต่อกัน และประกาศ firebase-functions เวอร์ชันของคุณเป็นการขึ้นต่อกันแบบเพียร์ด้วย

{
  "name": "<package-name>",
  "version": "1.0.0",
  "main": "lib/index.js",
  "types": "lib/index.d.ts",
  "exports": {
    ".": {
      "types": "./lib/index.d.ts",
      "default": "./lib/index.js"
    }
  },
  "engines": {
    "node": ">=22"
  },
  "peerDependencies": {
    "firebase-functions": "^7.3.0"
  },
  "dependencies": {
    "firebase-functions": "^7.3.0",
    "firebase-admin": "^14.2.0"
  }
}

ประกาศ firebase-functions เป็นการขึ้นต่อกันแบบเพียร์นอกเหนือจากการขึ้นต่อกันตามปกติ เพื่อให้โปรเจ็กต์ Cloud Functions ของผู้ใช้มี SDK เวอร์ชันเดียวกับที่ใช้เขียนไลบรารีของคุณ

ตัวอย่างการทำงาน: Stream Firestore to BigQuery

ก่อน. functions/package.json ของส่วนขยายเป็นแบบส่วนตัว ตั้งชื่อรหัสส่วนขยาย และประกาศ firebase-functions เป็นทรัพยากร Dependency โดยตรง

{
  "name": "firestore-bigquery-export",
  "main": "lib/index.js",
  "private": true,
  "dependencies": {
    "@firebaseextensions/firestore-bigquery-change-tracker": "^2.0.4",
    "firebase-admin": "^14.2.0",
    "firebase-functions": "^6.3.2"
  }
}

หลัง. แพ็กเกจที่เผยแพร่ได้: ชื่อที่มีขอบเขต แผนที่การส่งออก และ firebase-functions ย้ายไปที่ peerDependencies

{
  "name": "@firebase/firestore-bigquery-export",
  "version": "0.1.0",
  "main": "lib/index.js",
  "types": "lib/index.d.ts",
  "exports": {
    ".":     { "types": "./lib/index.d.ts", "default": "./lib/index.js" },  },
  "engines": { "node": ">=22" },
  "peerDependencies": { "firebase-functions": "^7.3.0" },
  "dependencies": {
      "@firebaseextensions/firestore-bigquery-change-tracker": "^2.0.4",
      "firebase-admin": "^14.2.0",
      "firebase-functions": "^7.3.0"
    }
}

อัปเกรดฟังก์ชันจากรุ่นที่ 1 เป็นรุ่นที่ 2

หากส่วนขยายยังคงส่งออกฟังก์ชันรุ่นที่ 1 ให้แปลงแต่ละฟังก์ชันเป็นฟังก์ชันเทียบเท่ารุ่นที่ 2 นำเข้าจากโมดูล firebase-functions/... และส่งการตั้งค่ารันไทม์ในตัวเลือกฟังก์ชัน

คุณสามารถ ลดความพยายามในการเขียนใหม่ ได้ด้วยการแยกโครงสร้างเหตุการณ์ที่แก้ไขแล้วของรุ่นที่ 2 และหลีกเลี่ยงการเขียนตรรกะฟังก์ชันใหม่ เนื่องจากตอนนี้ SDK รุ่นที่ 2 แสดงพารามิเตอร์ V1 เป็นช่องในออบเจ็กต์ เหตุการณ์ ซึ่งช่วยให้คุณใช้พารามิเตอร์ที่แยกโครงสร้าง/ตั้งชื่อแล้ว และคงตรรกะทางธุรกิจ ไว้ได้โดยไม่มีการเปลี่ยนแปลง

ก่อน. รุ่นที่ 1

import * as functions from "firebase-functions/v1";

export const sync = functions.firestore
  .document("{collectionId}/{documentId}")
  .onWrite(async (change, context) => {
    await handleWrite(change.before, change.after, context.params);
  });

หลัง. รุ่นที่ 2

import { onDocumentWritten } from "firebase-functions/firestore";

export const syncV2 = onDocumentWritten(
  { document: "{collectionId}/{documentId}" },
  async ({change,context}) =>
    await handleWrite(change.before, change.after, context.params);
);

ดูรายการความแตกต่างที่ครอบคลุมระหว่างฟังก์ชันรุ่นที่ 1 และรุ่นที่ 2 ได้ที่การเปรียบเทียบเวอร์ชัน Cloud Functions

แปลงพารามิเตอร์และข้อมูลลับของส่วนขยาย

แปลงพารามิเตอร์

พารามิเตอร์แต่ละรายการที่คุณประกาศใน extension.yaml จะกลายเป็น Cloud Functions พารามิเตอร์

แปลงการอ่านสภาพแวดล้อมโดยตรง

const collectionPath = process.env.COLLECTION_PATH;

เป็นพารามิเตอร์ Cloud Functions

import { defineString } from "firebase-functions/params";
import { onDocumentWritten} from "firebase-functions/firestore";

const collectionPath = defineString("COLLECTION_PATH");

// Pass the param directly when used as a placeholder (e.g. trigger path)
export const sync = onDocumentWritten(
  { document: collectionPath },
  async (event) => {
    // Call .value() to read the string inside a handler
    const path = collectionPath.value();
    await handleWrite(path, event);
  }
);

ใช้ collectionPath.value() เพื่ออ่านสตริงภายในแฮนเดิลอร์ และใช้ collectionPath โดยตรงในตำแหน่งที่คาดว่าจะใช้ตัวยึดตำแหน่ง เช่น เส้นทางทริกเกอร์ฟังก์ชัน

Firebase CLI จะค้นหาพารามิเตอร์และอ่านค่าจาก .env, .env.projectId หรือแจ้งให้ผู้ใช้ป้อนค่าระหว่างการทำให้ใช้งานได้ ใช้ชื่อพารามิเตอร์เดิมเพื่อให้ค่าจากการติดตั้งที่มีอยู่ยังคงอยู่

คุณต้องไม่ เปลี่ยนชื่อพารามิเตอร์ที่ประกาศไว้ในโค้ดโดยเด็ดขาด การย้ายข้อมูลส่วนขยายจะเก็บค่าพารามิเตอร์ของผู้ใช้ปลายทางที่มีอยู่ไว้โดยอัตโนมัติ แต่จะทำได้ก็ต่อเมื่อชื่อไม่เปลี่ยนแปลง

ตัวอย่างการทำงาน: Stream Firestore to BigQuery ก่อน. พารามิเตอร์ที่ประกาศใน extension.yaml อ่านเป็นตัวแปรสภาพแวดล้อมดิบใน config.ts

# extension.yaml
-   param: COLLECTION_PATH
  label: Collection path
  type: string
  required: true
// functions/src/config.ts
collectionPath: process.env.COLLECTION_PATH,

หลัง. defineString 1 รายการ CLI จะค้นหาและอ่านจาก .env

// src/config.ts
import { defineString } from "firebase-functions/params";

collectionPath: defineString("COLLECTION_PATH", {
  label: "Collection path",
  // We now support "nonEmpty: true" to ensure a value other than the empty string
  // is entered, analagous to "required: true" in extensions.yaml
  input: { text: { nonEmpty: true} }
}),

ชื่อพารามิเตอร์ไม่เปลี่ยนแปลง ดังนั้น .env ที่มีอยู่จะยังคงทำงานได้

แปลงข้อมูลลับ

ใน extension.yaml คุณประกาศข้อมูลลับด้วย type: secret รันไทม์ของ Extensions จะจัดเก็บและผูกข้อมูลลับไว้เพื่อให้โค้ดส่วนขยายอ่าน process.env.PARAM_NAME ได้โดยตรง ในฐานของโค้ด Cloud Functions ทั่วไป คุณจะประกาศและผูกข้อมูลลับแต่ละรายการ อย่างชัดแจ้ง

import { defineSecret } from "firebase-functions/params";
import { onRequest } from "firebase-functions/https";

const apiKey = defineSecret("API_KEY");
export const fn = onRequest({ secrets: [apiKey] }, handler);

เมื่อย้ายข้อมูลส่วนขยายไปยังแพ็กเกจ/ชุด npm แล้ว ระบบจะจัดการการอ้างอิงข้อมูลลับในไฟล์ .env ของผู้ใช้ปลายทาง คุณต้องไม่ เปลี่ยนชื่อข้อมูลลับที่ประกาศไว้ในโค้ดโดยเด็ดขาด ระบบจะย้ายข้อมูลลับของผู้ใช้ปลายทางตามความเหมาะสมในระหว่างการย้ายข้อมูล

ตัวอย่างการทำงาน: Trigger Email From Cloud Firestore

ก่อน. MAIL_COLLECTION และ SMTP_PASSWORD อ่านเป็นตัวแปรสภาพแวดล้อมดิบใน config.ts

# extension.yaml
-   param: MAIL_COLLECTION
  label: Email documents collection
  type: string
  default: mail
  required: true

-   param: SMTP_PASSWORD
  label: SMTP password
  type: secret
// functions/src/config.ts
mailCollection: process.env.MAIL_COLLECTION,
smtpPassword: process.env.SMTP_PASSWORD,

หลัง. defineString 1 รายการและ defineSecret 1 รายการ CLI จะค้นหาทั้ง 2 รายการและอ่านจาก .env

import { defineString, defineSecret } from "firebase-functions/params";
import { onDocumentWritten } from "firebase-functions/firestore";

const mailCollection = defineString("MAIL_COLLECTION",{ label: "Email documents collection",
 default: "mail"
});

const smtpPassword = defineSecret("SMTP_PASSWORD", { label: "SMTP password" });

export const processQueue = onDocumentWritten(
  { document: `${mailCollection}/{documentId}`, secrets: [smtpPassword] },
  async (event) => {
    const collection = mailCollection.value();
    const password = smtpPassword.value();
    // ...
  }
);

ย้ายข้อมูลการเรียกคิวงานภายใน

ส่วนขยายบางรายการจะเพิ่มงานลงในคิวงาน ของตัวเอง จากภายในโค้ด ฟังก์ชันโดยใช้ Firebase Admin SDK ซึ่งแตกต่างจากการ รับ งานที่ส่ง (ครอบคลุมในส่วน อัปเกรดฟังก์ชัน และ แปลงฮุกวงจร) ในที่นี้ โค้ดของคุณคือ ผู้ผลิต ที่เรียก queue.enqueue(...)

Admin SDK เวอร์ชันก่อนหน้ากำหนดให้ Admin SDK ส่วนขยายส่งรหัสอินสแตนซ์ส่วนขยายของตัวเอง เป็นพารามิเตอร์ที่ 2 เพื่อกำหนดเป้าหมายฟังก์ชันคิวงานใน ส่วนขยายเดียวกัน ตั้งแต่ `firebase-admin` 14.2.0 เป็นต้นมา การดำเนินการนี้ไม่จำเป็นและไม่ แนะนำ ตอนนี้ Task Queue API จะกำหนดเป้าหมายคิวงานในบริบทเดียวกัน (เช่น ส่วนขยาย) โดยค่าเริ่มต้น คุณสามารถนำพารามิเตอร์นี้ออกในโค้ดได้อย่างปลอดภัยและขอแนะนำให้ดำเนินการดังกล่าว ทั้งในฐานะส่วนขยายและฟังก์ชันแบบสแตนด์อโลน การนำพารามิเตอร์นี้ออกจะช่วยให้มั่นใจได้ถึงความสามารถในการพกพาและความเข้ากันได้แบบย้อนกลับ

ส่วนอื่นๆ ทั้งหมดเกี่ยวกับการเรียก enqueue ได้แก่ เส้นทางทรัพยากรตำแหน่ง/region/ฟังก์ชัน/name เพย์โหลดของงาน และตรรกะการลองใหม่ จะยังคงเหมือนเดิม

ดูรายละเอียดเพิ่มเติมเกี่ยวกับการเพิ่มฟังก์ชันลงในคิวด้วย Cloud Tasks ได้ที่ /docs/functions/task-functions

ก่อน. ส่วนขยายรุ่นที่ 1

import { getFunctions } from "firebase-admin/functions";

const queue = getFunctions().taskQueue(
  `locations/${config.location}/functions/syncBigQuery`,
  process.env.EXT_INSTANCE_ID, // extension instance ID, injected by the runtime
);
await queue.enqueue(taskData);

หลัง. ส่วนขยายรุ่นที่ 2

import { getFunctions } from "firebase-admin/functions";
import { region } from "firebase-functions/params";

const queue = getFunctions().taskQueue(
  `locations/${region.value()}/functions/syncBigQuery`);
await queue.enqueue(taskData);

หากการเรียก enqueue กำหนดเป้าหมายฐานของโค้ดที่มีคำนำหน้า ชื่อฟังก์ชันที่ค้นพบจะมีคำนำหน้าด้วย (เช่น orders-syncBigQuery)

ประกาศ API และบทบาท IAM ที่จำเป็น

ย้ายข้อมูลข้อกำหนด IAM และ API ของส่วนขยายออกจาก extension.yaml ไปไว้ในโค้ด

import { requiresAPI, requiresRole } from "firebase-functions"

requiresAPI("bigquery.googleapis.com", "Needed to write changelog rows");
requiresRole("roles/bigquery.dataEditor");
requiresRole("roles/bigquery.user");

เมื่อใช้การรักษาความปลอดภัยแบบประกาศ Firebase CLI จะสร้างหรืออัปเดตบัญชีบริการรันไทม์ที่มีการจัดการ สำหรับฐานของโค้ด และมอบบทบาททั้งหมดที่ประกาศไว้ให้กับบัญชีดังกล่าว จัดทำเอกสารสำหรับผู้ใช้ว่าฟังก์ชันทั้งหมดในฐานของโค้ดจะทำงานด้วยบทบาทเหล่านั้น เว้นแต่ว่า API สุดท้ายจะรองรับโมเดลที่แคบกว่า

ตัวอย่างการทำงาน: Stream Firestore to BigQuery

ก่อน. ประกาศใน extension.yaml รันไทม์ของ Extensions เปิดใช้ API และมอบบทบาทให้กับบัญชีที่มีการจัดการ

apis:
  -   apiName: bigquery.googleapis.com
roles:
  -   role: bigquery.dataEditor
  -   role: datastore.user
  -   role: bigquery.user

หลัง. ประกาศในโค้ดด้วย requiresAPI และ requiresRole

import { requiresAPI, requiresRole } from "firebase-functions/";
requiresAPI("bigquery.googleapis.com",
  "Needed to write changelog rows and views");
requiresRole("roles/biguqery.dataEditor");
requiresRole("roles/datastore.user");
requiresRole("roles/bigquery.user");

แปลงฮุกวงจร

หากส่วนขยายเรียก getExtensions().runtime() เช่น setProcessingState หรือ setFatalError ให้ลบการเรียกเหล่านั้น เนื่องจากจะแสดง ข้อผิดพลาดหากเรียกจากฟังก์ชันรุ่นที่ 2 ที่ทำให้ใช้งานได้ตามปกติ ตอนนี้สถานะวงจรจะกำหนดโดย afterFirstDeploy และ afterRedeploy ในตำแหน่งที่ไม่ได้ใช้การติดตามสถานะนี้

Firebase Extensions สามารถเรียกใช้การตั้งค่าเมื่อผู้ใช้ติดตั้ง อัปเดต หรือ กำหนดค่าส่วนขยายใหม่ ในแพ็กเกจ npm ให้ประกาศการดำเนินการในวงจรที่เทียบเท่าในโค้ด

สำหรับการตั้งค่าแบบครั้งเดียว

import { afterFirstDeploy } from "firebase-functions/lifecycle";
import { onTaskDispatched } from "firebase-functions/tasks";

export const runInitialSetup = onTaskDispatched(async (request) => {
  await initializeResources(request.data);
});

afterFirstDeploy({
  task: {
    function: "runInitialSetup",
    body: {}
  }
});

สำหรับการอัปเดตการกำหนดค่าหรือโค้ด

import { afterRedeploy } from "firebase-functions/lifecycle";

afterRedeploy({
  task: {
    function: "runInitialSetup",
    body: { reconcile: true }
  }
});

ทำให้การดำเนินการในวงจรเป็นแบบ Idempotent ผู้ใช้อาจต้องเรียกใช้การดำเนินการเหล่านี้อีกครั้งด้วยตนเองหากการส่งหรือการดำเนินการล้มเหลว

firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME
firebase functions:lifecycle:run afterRedeploy CODEBASE_NAME

ตัวอย่างการทำงาน: Stream Firestore to BigQuery

ก่อน. lifecycleEvents ใน extension.yaml กำหนดโดยรันไทม์ของ Extensions

lifecycleEvents:
  onInstall:
    function: initBigQuerySync
    processingMessage: Configuring BigQuery Sync.
  onUpdate:
    function: setupBigQuerySync
    processingMessage: Configuring BigQuery Sync
  onConfigure:
    function: setupBigQuerySync
    processingMessage: Configuring BigQuery Sync

หลัง. ประกาศในโค้ด งานจะจัดสรร BigQuery เมื่อทำให้ใช้งานได้ครั้งแรก

import { afterFirstDeploy, afterRedeploy } from "firebase-functions/lifecycle";

afterFirstDeploy({ task: { function: "initBigQuerySync" } });
afterRedeploy({ task: { function: "setupBigQuerySync" } });

การจัดสรรเป็นแบบ Idempotent ดังนั้นการเรียกใช้ซ้ำจะปรับข้อมูล ชุดข้อมูล ตาราง และมุมมองให้ตรงกัน ผู้ใช้สามารถเรียกใช้ด้วยตนเองอีกครั้งด้วย firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME

จัดทำเอกสารการตั้งค่าสำหรับผู้ใช้

  • เขียน README ของแพ็กเกจที่อธิบายข้อมูลต่อไปนี้เป็นอย่างน้อย

  • ค่า .env ที่แพ็กเกจกำหนด

  • ข้อมูลลับที่แพ็กเกจกำหนดและวิธีย้ายข้อมูลค่าข้อมูลลับที่มีอยู่

  • บทบาท IAM ที่แพ็กเกจประกาศด้วย requiresRole(...)

  • Google API ที่แพ็กเกจเปิดใช้หรือกำหนด

  • ฮุกวงจรที่แพ็กเกจประกาศและวิธีเรียกใช้ฮุกเหล่านั้นอีกครั้งด้วยตนเอง

  • หมายเหตุเกี่ยวกับการเรียกเก็บเงิน

  • สิ่งที่เปลี่ยนแปลงเมื่อเทียบกับส่วนขยายเดิม

ตัวอย่างการทำงาน: Stream Firestore to BigQuery

README ของแพ็กเกจมีตาราง "สิ่งที่เปลี่ยนแปลง" ที่เฉพาะเจาะจง

ภาวะ ในฐานะส่วนขยาย ในฐานะ @firebase/firestore-bigquery-export
การกำหนดค่า พารามิเตอร์ส่วนขยาย พารามิเตอร์ฟังก์ชันผ่าน .env
IAM ได้รับอนุญาตจาก Extensions requiresRole(...) ใช้เมื่อทำให้ใช้งานได้
การจัดสรร งานวงจรโดย Extensions งาน afterFirstDeploy / afterRedeploy
ชื่อฟังก์ชัน ext-instanceId-fsexportbigquery fsexportbigquery (มีคำนำหน้าหรือไม่ก็ได้)

ทดสอบฟังก์ชันรุ่นที่ 2

ตอนนี้คุณควรมีฟังก์ชันรุ่นที่ 2 ซึ่งเมื่อทำให้ใช้งานได้แล้วจะมีลักษณะการทำงานเหมือนกับการติดตั้งส่วนขยายใหม่ ขั้นตอนสุดท้ายคือการยืนยันและแก้ไขปัญหาที่เกิดขึ้นโดยไม่ได้ตั้งใจ

ตรวจสอบว่าคุณใช้ firebase-tools >= 15.24.0 แล้ว และทำให้ฟังก์ชันรุ่นที่ 2 ที่แปลงแล้วใช้งานได้ในโปรเจ็กต์ทดสอบ ที่มีทรัพยากรที่เหมาะสมเพื่อทดสอบลักษณะการทำงานของฟังก์ชัน หากคุณตั้งค่าโปรเจ็กต์ทดสอบไว้แล้วจากการทดสอบส่วนขยาย ให้ใช้คำสั่งต่อไปนี้

firebase deploy --only functions

หลังจากป้อนคำสั่งนี้แล้ว ให้กรอกค่าพารามิเตอร์ในวิซาร์ดที่ปรากฏขึ้นในลักษณะเดียวกับที่คุณกรอกแบบฟอร์มการติดตั้งใน คอนโซลFirebaseสำหรับส่วนขยาย

ตัวอย่างการทำงาน: Stream Firestore to BigQuery

เราจะยืนยันการซิงค์ Cloud Firestore กับ BigQuery แบบต้นทางถึงปลายทาง

  1. ในคอนโซล Cloud Firestore ให้สร้างคอลเล็กชันที่คุณตั้งค่าเป็น COLLECTION_PATH (users) หากยังไม่มี
  2. สร้างเอกสารชื่อ bigquery-mirror-test ที่มีช่องใดก็ได้ที่มีค่าใดก็ได้
  3. ในคอนโซล BigQuery ให้ค้นหาตาราง Changelog ดิบ ตารางควรมีแถวเดียวที่บันทึกการสร้างเอกสาร ดังนี้
SELECT * FROM `PROJECT_ID.analytics.users_raw_changelog`
  1. ค้นหามุมมองล่าสุด ซึ่งควรแสดงเหตุการณ์การเปลี่ยนแปลงล่าสุดสำหรับ เอกสารเดียวที่มีอยู่: bigquery-mirror-test
SELECT * FROM `PROJECT_ID.analytics.users_raw_latest`
  1. ลบเอกสาร bigquery-mirror-test ใน Cloud Firestore เอกสารจะหายไปจากมุมมองล่าสุด และระบบจะเพิ่มเหตุการณ์ DELETE ลงในตาราง Changelog ดิบ

คุณสามารถตรวจสอบประวัติทั้งหมดของเอกสารเดียวได้ด้วยคำสั่งต่อไปนี้

SELECT *
   FROM `PROJECT_ID.analytics.users_raw_changelog`
   WHERE document_name = "bigquery-mirror-test"
   ORDER BY timestamp ASC

ความแตกต่างจากการทดสอบส่วนขยาย

  • ทริกเกอร์จะทำให้ใช้งานได้เป็น fsexportbigquery (มีคำนำหน้าฐานของโค้ดหรือไม่ก็ได้) ไม่ใช่ ext-&lt;instanceId&gt;-fsexportbigquery ค้นหาชื่อดังกล่าวใน Cloud Functions แดชบอร์ดและบันทึก
  • ตอนนี้โค้ดจะทำงานใน Firebase Local Emulator Suite เป็นฟังก์ชันปกติ คุณสามารถตั้งค่าพารามิเตอร์ที่จะใช้ในอีมูเลเตอร์ด้วย .env.local นอกจากนี้ คุณยังทำ Unit Test โค้ดของคุณได้โดยใช้ firebase-functions-test SDK ตามที่อธิบายไว้ใน หัวข้อการทำ Unit Test ของ Cloud Functions
  • รันไทม์ของ Extensions จะไม่กำหนดการจัดสรรอีกต่อไป หากตาราง Changelog หายไปหลังจากทำให้ใช้งานได้ ให้เรียกใช้ฟังก์ชันการตั้งค่าอีกครั้งด้วยตนเอง firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME ฟังก์ชันนี้เป็นแบบ Idempotent ดังนั้นการเรียกใช้ซ้ำจะปรับข้อมูล ชุดข้อมูล ตาราง และมุมมองให้ตรงกัน
  • ค่าพารามิเตอร์มาจาก .env ไม่ใช่แบบฟอร์มการติดตั้ง ดังนั้นการเรียกใช้ firebase deploy อีกครั้งจะไม่โต้ตอบเมื่อ .env เสร็จสมบูรณ์