คู่มือนี้จะแสดงวิธีย้ายข้อมูลส่วนขยายจากสภาพแวดล้อม Firebase Extensions ที่เลิกใช้งานแล้วไปยังฟังก์ชันที่ผู้ใช้ติดตั้งและทำให้ใช้งานได้ใน Cloud Functions ของตนเองสำหรับฐานของโค้ด Firebase (รุ่นที่ 2)
นี่คือเส้นทางการย้ายข้อมูลที่แนะนำ Firebase จะดูแลรายการ ส่วนขยายที่มีแพ็กเกจ npm อย่างเป็นทางการที่เทียบเท่ากัน โดยคู่มือนี้จะแนะนำขั้นตอน การสร้างส่วนขยายของคุณ
ในคู่มือนี้ เราจะใช้ส่วนขยายสตรีม Firestore ไปยัง 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 แล้ว ประกาศการตั้งค่าเวลาติดตั้งและเวลาอัปเดตด้วย Hook วงจรของแอป
afterFirstDeploy(...)และafterRedeploy(...)ซึ่งจะแทนที่lifecycleEventsที่คุณประกาศในextension.yaml
จัดทำรายการส่วนขยาย
เริ่มต้นด้วยการทำรายการส่วนขยายของคุณ ซึ่งเป็นรายการทั้งหมด ที่ส่วนขยายประกาศ จัดส่ง และจัดทำเอกสาร เพื่อให้ทุกลักษณะการทำงานมี ปลายทางที่กำหนดไว้ในฟังก์ชันรุ่นที่ 2 และไม่มีข้อมูลใดสูญหายใน การย้ายข้อมูล
ตรวจสอบแต่ละรายการต่อไปนี้และจดบันทึกสิ่งที่คุณพบ
extension.yamlซึ่งประกาศพารามิเตอร์ ฟังก์ชัน เหตุการณ์ บทบาท IAM, API ที่จำเป็น, Secret และฮุควงจรfunctions/ซึ่งมีโค้ดฟังก์ชัน ทรัพยากร Dependency การกำหนดค่าบิลด์ ทริกเกอร์ และฟังก์ชันคิวงานREADME.md,PREINSTALL.mdและPOSTINSTALL.mdซึ่งมีขั้นตอนการตั้งค่า คำเตือน และหมายเหตุการเรียกเก็บเงินscripts/ซึ่งมีเครื่องมือสำหรับการนำเข้า การแสดงโฆษณาสำรอง IAM การซ่อม หรือการย้ายข้อมูล และเครื่องมืออื่นๆ ที่คุณจัดส่งพร้อมกับส่วนขยาย
จากนั้นสำหรับแต่ละรายการใน
extension.yaml ให้ตัดสินใจว่าจะวางรายการนั้นไว้ที่ใดในแพ็กเกจ npm
แปลงการกำหนดค่าผู้ใช้เป็นพารามิเตอร์ Cloud Functions (ส่วนที่ 5)
แปลงข้อมูลลับเป็น Cloud Functions secrets (ส่วน 6)
แปลงบทบาท IAM เป็น
requiresRole(...)ประกาศ (ส่วนที่ 8)แปลง Google API ที่จำเป็นเป็น
requiresAPI(...)ประกาศตามความเหมาะสม (ส่วนที่ 8)แปลง Hook การติดตั้งและการอัปเดตเป็นการประกาศ
afterFirstDeploy(...)และafterRedeploy(...)(ส่วนที่ 8)
ตัวอย่างการทำงาน: สตรีม Firestore ไปยัง BigQuery
การอ่าน firestore-bigquery-export/extension.yaml และฟังก์ชันจะสร้างข้อมูลต่อไปนี้
| ใน extension.yaml | จำนวน / มูลค่า | ตำแหน่งที่ข้อมูลจะไป |
|---|---|---|
| พารามิเตอร์ | 25 (COLLECTION_PATH, DATASET_ID, TABLE_ID, DATASET_LOCATION, VIEW_TYPE, …) | Cloud Functions params (section 5) |
| API | bigquery.googleapis.com | requiresAPI(...) (ส่วนที่ 7) |
| บทบาท | bigquery.dataEditor, datastore.user, bigquery.user | requiresRole(...) (ส่วนที่ 7) |
| ทรัพยากร | ทริกเกอร์เหตุการณ์ 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 เป็นทรัพยากร Dependency ประกาศเวอร์ชัน 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 เป็นทรัพยากร Dependency แบบเพียร์นอกเหนือจากทรัพยากร Dependency ปกติ เพื่อให้โปรเจ็กต์ Cloud Functions ของผู้ใช้มี SDK เวอร์ชันเดียวกับที่ใช้เขียนไลบรารีของคุณ
ตัวอย่างการทำงาน: สตรีม Firestore ไปยัง BigQuery
ก่อน ฟังก์ชัน/package.json ของส่วนขยายเป็นแบบส่วนตัว โดยจะตั้งชื่อ รหัสส่วนขยาย และประกาศ firebase-functions เป็นการขึ้นต่อกันโดยตรง
{
"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
param
แปลงการอ่านสภาพแวดล้อมโดยตรง
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, .envprojectId หรือแจ้งให้ผู้ใช้ทราบระหว่างการติดตั้งใช้งาน ใช้ชื่อพารามิเตอร์เดิมเพื่อให้ค่าจากการติดตั้งที่มีอยู่ยังคงอยู่
คุณไม่ควรเปลี่ยนชื่อพารามิเตอร์ที่ประกาศไว้ในโค้ด โดยเด็ดขาด การย้ายข้อมูลส่วนขยายจะเก็บค่าพารามิเตอร์ของผู้ใช้ปลายทางที่มีอยู่ โดยอัตโนมัติ แต่จะทำได้ก็ต่อเมื่อชื่อไม่เปลี่ยนแปลง
ตัวอย่างการทำงาน: สตรีม Firestore ไปยัง 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 รายการเดียว 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 รันไทม์ของส่วนขยาย จะจัดเก็บและเชื่อมโยงตัวแปรเหล่านี้เพื่อให้โค้ดส่วนขยายอ่าน process.env.PARAM_NAME ได้โดยตรง ในCloud Functionsฐานของโค้ดทั่วไป คุณจะประกาศและเชื่อมโยงแต่ละ Secret อย่างชัดเจน
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 ของผู้ใช้ปลายทาง คุณไม่ควรเปลี่ยนชื่อลับที่ประกาศไว้ในโค้ดโดยเด็ดขาด ในระหว่างการย้ายข้อมูล
ระบบจะย้ายข้อมูลลับของผู้ใช้ปลายทางตามนั้น
ตัวอย่างการทำงาน: อีเมลทริกเกอร์จาก 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 เวอร์ชันก่อนหน้ากำหนดให้ส่วนขยายต้องส่งรหัสอินสแตนซ์ของส่วนขยายของตนเองเป็นพารามิเตอร์ที่ 2 เพื่อกำหนดเป้าหมายฟังก์ชัน Task Queue ในส่วนขยายเดียวกัน ตั้งแต่ `firebase-admin` 14.2.0 เป็นต้นไป คุณไม่จำเป็นต้องดำเนินการนี้และเราไม่แนะนำให้ทำ ตอนนี้ Task Queue API จะกำหนดเป้าหมายเป็นคิวของงานในบริบทเดียวกัน (เช่น ส่วนขยาย) โดยค่าเริ่มต้น เราขอแนะนำให้คุณนำพารามิเตอร์นี้ออกจากโค้ดทั้งในรูปแบบส่วนขยายและฟังก์ชันแบบสแตนด์อโลน การนำพารามิเตอร์นี้ออกจะช่วยให้มั่นใจได้ถึงความสามารถในการพกพาและความเข้ากันได้ในอนาคต
ส่วนอื่นๆ ทั้งหมดเกี่ยวกับการเรียก enqueue ไม่ว่าจะเป็นเส้นทางทรัพยากร locations/region/functions/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";
const queue = getFunctions().taskQueue(
`locations/${process.env.FUNCTION_REGION}/functions/syncBigQuery`);
await queue.enqueue(taskData);
หากการเรียก enqueue มุ่งเป้าไปที่ฐานของโค้ดที่มีคำนำหน้า ชื่อฟังก์ชันที่ค้นพบ จะมีคำนำหน้าด้วย (เช่น orders-syncBigQuery)
ประกาศ API และบทบาท IAM ที่จำเป็น
ย้ายข้อกำหนด IAM และ API ของส่วนขยายออกจาก extension.yaml ไปยัง code:
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 สุดท้ายจะรองรับโมเดลที่แคบกว่า
ตัวอย่างการทำงาน: สตรีม Firestore ไปยัง BigQuery
ก่อน ประกาศใน extension.yaml โดยรันไทม์ของส่วนขยายจะเปิดใช้ 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
ตัวอย่างการทำงาน: สตรีม Firestore ไปยัง BigQuery
ก่อน lifecycleEvents ใน extension.yaml ซึ่งขับเคลื่อนโดยรันไทม์ของส่วนขยาย
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 ที่แพ็กเกจเปิดใช้หรือต้องใช้
Hook วงจรการใช้งานที่แพ็กเกจประกาศและวิธีเรียกใช้ซ้ำด้วยตนเอง
หมายเหตุเกี่ยวกับการเรียกเก็บเงิน
มีการเปลี่ยนแปลงอะไรบ้างเมื่อเทียบกับส่วนขยายเดิม
ตัวอย่างการทำงาน: สตรีม Firestore ไปยัง BigQuery
README ของแพ็กเกจจะแสดงตาราง "สิ่งที่เปลี่ยนแปลง" ที่ชัดเจน
| ข้อกังวล | เป็นส่วนขยาย | เป็น @firebase/firestore-bigquery-export |
|---|---|---|
| การกำหนดค่า | พารามิเตอร์ส่วนขยาย | พารามิเตอร์ของฟังก์ชันผ่าน .env |
| IAM | ได้รับจากส่วนขยาย | requiresRole(...) ใช้เมื่อติดตั้งใช้งาน |
| การจัดสรร | งานวงจรลูกค้าตามส่วนขยาย | งาน afterFirstDeploy / afterRedeploy |
| ชื่อฟังก์ชัน | ext-instanceId-fsexportbigquery | fsexportbigquery (มีคำนำหน้าหรือไม่ก็ได้) |
ทดสอบฟังก์ชันรุ่นที่ 2
ตอนนี้คุณควรมีฟังก์ชันรุ่นที่ 2 ซึ่งเมื่อนำไปใช้งานแล้วจะทำงาน เหมือนกับการติดตั้งส่วนขยายใหม่ทุกประการ ขั้นตอนสุดท้ายคือการยืนยัน และแก้ไขปัญหาที่เกิดขึ้นโดยไม่ตั้งใจระหว่างทาง
ตรวจสอบว่าคุณใช้
firebase-tools
>= 15.25.1 และทําการติดตั้งใช้งานฟังก์ชันรุ่นที่ 2 ที่แปลงแล้วในโปรเจ็กต์ทดสอบ
พร้อมทรัพยากรที่เหมาะสมเพื่อทดสอบลักษณะการทํางาน หากคุณมีโปรเจ็กต์ทดสอบที่ตั้งค่าไว้แล้วจากการทดสอบส่วนขยาย ให้ใช้คำสั่งต่อไปนี้
firebase deploy --only functions
หลังจากป้อนคำสั่งนี้ ให้กรอกวิซาร์ดที่ปรากฏขึ้นซึ่งจะแจ้งให้คุณป้อนค่าพารามิเตอร์ในลักษณะเดียวกับที่คุณกรอกแบบฟอร์มการติดตั้งในคอนโซล Firebase สำหรับส่วนขยาย
ตัวอย่างการทำงาน: สตรีม Firestore ไปยัง BigQuery
เราจะยืนยันการซิงค์Cloud FirestoreกับBigQueryตั้งแต่ต้นทางถึงปลายทางดังนี้
- ในCloud Firestoreคอนโซล ให้สร้างคอลเล็กชันที่คุณตั้งค่าเป็น COLLECTION_PATH (users) หากยังไม่มี
- สร้างเอกสารชื่อ bigquery-mirror-test ที่มีฟิลด์ที่มีค่าใดก็ได้
- ในBigQueryคอนโซล ให้ค้นหาตารางบันทึกการเปลี่ยนแปลงดิบ โดยควรมีแถวเดียวที่บันทึกการสร้างเอกสาร ดังนี้
SELECT * FROM `PROJECT_ID.analytics.users_raw_changelog`
- ค้นหามุมมองล่าสุด ซึ่งควรแสดงเหตุการณ์การเปลี่ยนแปลงล่าสุดสำหรับ
เอกสารเดียวที่มีอยู่:
bigquery-mirror-test
SELECT * FROM `PROJECT_ID.analytics.users_raw_latest`
- ลบเอกสาร
bigquery-mirror-testใน Cloud Firestore โดยจะหายไปจากมุมมองล่าสุด และระบบจะต่อท้ายเหตุการณ์DELETEเข้ากับตารางบันทึกการเปลี่ยนแปลงดิบ
คุณตรวจสอบประวัติทั้งหมดของเอกสารเดียวได้โดยทำดังนี้
SELECT *
FROM `PROJECT_ID.analytics.users_raw_changelog`
WHERE document_name = "bigquery-mirror-test"
ORDER BY timestamp ASC
ความแตกต่างจากการทดสอบส่วนขยาย
- ทริกเกอร์จะทําการติดตั้งใช้งานเป็น
fsexportbigquery(อาจมีคำนำหน้าเป็นฐานของโค้ด) ไม่ใช่ext-<instanceId>-fsexportbigqueryมองหาชื่อนั้นใน Cloud Functions แดชบอร์ดและบันทึก - ตอนนี้โค้ดจะทำงานใน Firebase Local Emulator Suite เหมือนฟังก์ชันปกติ
คุณสามารถตั้งค่าพารามิเตอร์เพื่อใช้ในโปรแกรมจำลองด้วย
.env.localนอกจากนี้ คุณยังทำ Unit Test โค้ดได้โดยใช้ SDK firebase-functions-test ตามที่อธิบายไว้ในการทำ Unit Test ของ Cloud Functions - การจัดสรรไม่ได้ขับเคลื่อนโดยรันไทม์ของส่วนขยายอีกต่อไป หากตารางบันทึกการเปลี่ยนแปลง
หายไปหลังจากที่ติดตั้งใช้งาน ให้เรียกใช้การตั้งค่าอีกครั้งด้วยตนเอง:
firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAMEงานนี้เป็น ไอดีมโปเตนต์ ดังนั้นการเรียกใช้ซ้ำจะทำให้ชุดข้อมูล ตาราง และมุมมองสอดคล้องกัน - ค่าพารามิเตอร์มาจาก
.envไม่ใช่แบบฟอร์มการติดตั้ง ดังนั้นการเรียกใช้ซ้ำ ของfirebase deployจะไม่ใช่แบบอินเทอร์แอกทีฟเมื่อ.envเสร็จสมบูรณ์