এই নির্দেশিকাটি আপনাকে দেখাবে কীভাবে আপনার এক্সটেনশনগুলিকে অপ্রচলিত Firebase Extensions পরিবেশ থেকে এমন একটি ফাংশনে স্থানান্তর করবেন, যা আপনার ব্যবহারকারীরা তাদের নিজস্ব Cloud Functions for Firebase (2nd gen) কোডবেসে ইনস্টল ও স্থাপন করতে পারে।
এটিই প্রস্তাবিত মাইগ্রেশন পথ। Firebase তার অফিসিয়াল এনপিএম সমতুল্য এক্সটেনশনগুলির একটি তালিকা বজায় রাখবে; এই নির্দেশিকাটি আপনাকে আপনার নিজেরটি তৈরি করার প্রক্রিয়াটি ধাপে ধাপে দেখাবে।
এই নির্দেশিকা জুড়ে, Stream Firestore to BigQuery এক্সটেনশনটি (firestore-bigquery-export) একটি উদাহরণ হিসেবে ব্যবহার করা হয়েছে। প্রতিটি বিভাগের শেষে একটি সমাধান করা উদাহরণ রয়েছে, যা দেখায় যে মাইগ্রেশনের আগে এক্সটেনশনটি কেমন ছিল এবং @firebase/firestore-bigquery-export প্যাকেজ হিসেবে মাইগ্রেশনের পরে এটি এখন কেমন দেখতে হয়েছে।
এক্সটেনশন মাইগ্রেট করার বিষয়ে আরও তথ্য ও সাহায্য পেতে সাইন আপ করুন।
Firebase Extensions থেকে মাইগ্রেট করার পদ্ধতি সম্পর্কে আপনার কোনো প্রশ্ন থাকলে, আপনি firebase-extensions-migrator-support-external@google.com এই ঠিকানায় আমাদের সাথে যোগাযোগ করতে পারেন। আপনার ২য় প্রজন্মের ফাংশনগুলোর প্যাকেজিং, টেস্টিং এবং ডিস্ট্রিবিউশন বিষয়ে আরও তথ্য দিয়ে আমরা যখন গাইডটি আপডেট করব, তখন এই গ্রুপেও ইমেল করব।
এই গ্রুপে যোগ দিতে, firebase-extensions-migrator-support-external+subscribe@google.com- এ একটি বার্তা পাঠান, যার উত্তরে একটি সদস্যপদ অনুরোধের ইমেল পাঠানো হবে। আপনাকে অবশ্যই সেই ইমেলের উত্তর দিতে হবে, "এই গ্রুপে যোগ দিন" বোতামে ক্লিক করা যাবে না।
শুরু করার আগে
এই মাইগ্রেশনটি সম্পন্ন করতে, আপনি Cloud Functions এর নিম্নলিখিত বৈশিষ্ট্যগুলো ব্যবহার করবেন:
প্যারামিটারযুক্ত কনফিগারেশন ।
extension.yamlএ আপনি যে প্রতিটি 'param' ঘোষণা করেন, তা আপনার প্যাকেজ কোডে একটি সংজ্ঞায়িত প্যারামিটার হয়ে যায়।ডিক্লারেটিভ IAM রোল এবং প্রয়োজনীয় API।
extension.yamlএ আপনার ঘোষিত প্রতিটি রোল আপনার ফাংশন কোডে একটিrequiresRole(...)কলে এবং প্রতিটি API একটিrequiresAPI(...)কলে পরিণত হয়। ডিপ্লয় করার সময়, Firebase CLI আপনার পক্ষ থেকে একটি ম্যানেজড রানটাইম সার্ভিস অ্যাকাউন্টে ঘোষিত রোলগুলো প্রদান করে এবং ঘোষিত API-গুলো সক্রিয় করে।Cloud Functions কোডবেসের জন্য লাইফসাইকেল ইভেন্ট। Cloud Functions কোডবেস এখন Firebase Extensions অনুরূপ লাইফসাইকেল ইভেন্ট সমর্থন করে।
afterFirstDeploy(...)এবংafterRedeploy(...)লাইফসাইকেল হুক ব্যবহার করে ইনস্টল-টাইম এবং আপডেট-টাইম সেটআপ ঘোষণা করুন। এগুলিextension.yamlএ আপনার ঘোষিতlifecycleEventsপ্রতিস্থাপন করে।
এক্সটেনশনের তালিকা তৈরি করুন
আপনার এক্সটেনশনটির একটি সম্পূর্ণ তালিকা তৈরি করার মাধ্যমে শুরু করুন: এক্সটেনশনটি যা কিছু ঘোষণা করে, সরবরাহ করে এবং নথিভুক্ত করে, তার একটি পূর্ণাঙ্গ তালিকা তৈরি করুন, যাতে দ্বিতীয় প্রজন্মের ফাংশনে প্রতিটি আচরণের একটি নির্দিষ্ট গন্তব্য থাকে এবং মাইগ্রেশনের সময় কিছুই হারিয়ে না যায়।
নিচের প্রতিটি বিষয় পর্যালোচনা করুন এবং আপনি যা খুঁজে পান তা লিপিবদ্ধ করুন:
extension.yaml, যা আপনার প্যারামিটার, ফাংশন, ইভেন্ট, IAM রোল, প্রয়োজনীয় API, সিক্রেট এবং লাইফসাইকেল হুক ঘোষণা করে।functions/ফোল্ডারে আপনার ফাংশন কোড, ডিপেন্ডেন্সি, বিল্ড কনফিগারেশন, ট্রিগার এবং টাস্ক কিউ ফাংশনগুলো থাকে।README.md,PREINSTALL.md, এবংPOSTINSTALL.md, যেগুলিতে সেটআপের ধাপ, সতর্কতা এবং বিলিং সংক্রান্ত নোট রয়েছে।scripts/ফোল্ডারে যেকোনো ইম্পোর্ট, ব্যাকফিল, আইএএম, রিপেয়ার বা মাইগ্রেশন ইউটিলিটি এবং এক্সটেনশনটির সাথে আপনি সরবরাহ করা অন্য যেকোনো টুলিং থাকে।
তারপর, extension.yaml এর প্রতিটি আইটেমের জন্য, npm প্যাকেজে সেটি কোথায় যাবে তা স্থির করুন:
ব্যবহারকারীর কনফিগারেশনকে Cloud Functions প্যারামিটারে রূপান্তর করুন (অনুচ্ছেদ ৫)।
সিক্রেটগুলোকে Cloud Functions সিক্রেটে রূপান্তর করুন (অনুচ্ছেদ ৬)।
IAM রোলগুলিকে
requiresRole(...)ডিক্লারেশনে রূপান্তর করুন (অনুচ্ছেদ ৮)।প্রয়োজন অনুযায়ী প্রয়োজনীয় Google API-গুলোকে
requiresAPI(...)ডিক্লারেশনে রূপান্তর করুন (অনুচ্ছেদ ৮)।install এবং update হুকগুলিকে
afterFirstDeploy(...)এবংafterRedeploy(...)ডিক্লারেশনে রূপান্তর করুন (অনুচ্ছেদ ৮)।
কার্যকরী উদাহরণ: ফায়ারস্টোর থেকে BigQuery ডেটা স্ট্রিম করা
firestore-bigquery-export/extension.yaml এবং functions/ ফাইলগুলো পড়লে এই ইনভেন্টরি পাওয়া যায়:
| extension.yaml-এ | গণনা / মান | যেখানে এটা যায় |
|---|---|---|
| প্যারামিটার | ২৫ (সংগ্রহের পথ, ডেটাসেট আইডি, টেবিল আইডি, ডেটাসেটের অবস্থান, দেখার ধরণ, …) | Cloud Functions প্যারামিটার (বিভাগ ৫) |
| এপিস | bigquery.googleapis.com | requiresAPI(...) (অনুচ্ছেদ ৭) |
| ভূমিকা | bigquery.dataEditor, datastore.user, bigquery.user | ভূমিকা প্রয়োজন(...) (অনুচ্ছেদ ৭) |
| সম্পদ | ১টি ইভেন্ট ট্রিগার (fsexportbigquery) + টাস্ক কিউ ফাংশন (initBigQuerySync, setupBigQuerySync) | রপ্তানিকৃত প্যাকেজ ফাংশন (বিভাগ ৩) |
| জীবনচক্র ইভেন্ট | onInstall → initBigQuerySync; onUpdate / onConfigure → setupBigQuerySync | afterFirstDeploy / afterRedeploy (ধারা ৯) |
| স্ক্রিপ্ট/ | আমদানি/ (ব্যাকফিল), জেন-স্কিমা-ভিউ/ | স্ক্রিপ্ট হিসেবে রাখা হয়েছে (এখানে আলোচনার আওতার বাইরে) |
এক্সটেনশনটি কোনো type: secret প্যারামিটার ঘোষণা করে না, তাই এই গাইডের ৬ নং বিভাগে মাইগ্রেট করার মতো কিছু নেই। ইভেন্ট ট্রিগারটি ইতিমধ্যেই ২য় প্রজন্মের; শুধুমাত্র টাস্ক কিউ ফাংশনগুলো এখনও ১ম প্রজন্মের (যা ৩ নং বিভাগে প্রাসঙ্গিক)।
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 ভার্সনটি থাকে যা দিয়ে আপনার লাইব্রেরিটি লেখা হয়েছিল।
কার্যকরী উদাহরণ: ফায়ারস্টোর থেকে BigQuery ডেটা স্ট্রিম করা
পূর্বে। এক্সটেনশনটির functions/package.json ফাইলটি private, এতে এক্সটেনশন আইডি-র নাম উল্লেখ করা আছে, এবং 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"
}
}
১ম প্রজন্ম থেকে ২য় প্রজন্মে ফাংশন আপগ্রেড করুন
আপনার এক্সটেনশনটি যদি এখনও প্রথম প্রজন্মের ফাংশন এক্সপোর্ট করে, তবে প্রতিটি ফাংশনকে তার দ্বিতীয় প্রজন্মের সমতুল্য ফাংশনে রূপান্তর করুন। firebase-functions/... মডিউল থেকে ইম্পোর্ট করুন এবং ফাংশন অপশনে রানটাইম সেটিংস পাস করুন।
দ্বিতীয় প্রজন্মের প্যাচ করা ইভেন্ট ডিস্ট্রাকচারিং ব্যবহার করে আপনি কোড পুনর্লিখনের প্রচেষ্টা কমাতে পারেন এবং আপনার ফাংশন লজিক পুনরায় লেখা এড়াতে পারেন, কারণ দ্বিতীয় প্রজন্মের SDK এখন V1 প্যারামিটারগুলোকে ইভেন্ট অবজেক্টের ফিল্ড হিসেবে প্রকাশ করে, যা আপনাকে ডিস্ট্রাকচার্ড/নামযুক্ত প্যারামিটার ব্যবহার করতে এবং আপনার বিজনেস লজিক অপরিবর্তিত রাখতে সাহায্য করে।
পূর্বে। প্রথম প্রজন্ম:
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);
});
পরে। দ্বিতীয় প্রজন্ম:
import { onDocumentWritten } from "firebase-functions/firestore";
export const syncV2 = onDocumentWritten(
{ document: "{collectionId}/{documentId}" },
async ({change,context}) =>
await handleWrite(change.before, change.after, context.params);
);
১ম প্রজন্ম এবং ২য় প্রজন্মের ফাংশনগুলোর মধ্যে পার্থক্যের একটি বিশদ তালিকার জন্য 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, projectId থেকে সেগুলোর মান পড়ে নেয়, অথবা ডিপ্লয় করার সময় আপনার ব্যবহারকারীদের কাছে জানতে চায়। প্যারামিটারের নামগুলো একই রাখুন, যাতে বিদ্যমান ইনস্টলেশনের মানগুলো স্থানান্তরিত হয়।
এটা গুরুত্বপূর্ণ যে আপনি আপনার কোডে ঘোষিত প্যারামিটারের নামগুলো কোনোভাবেই পরিবর্তন করবেন না । এক্সটেনশন মাইগ্রেশন স্বয়ংক্রিয়ভাবে বিদ্যমান এন্ড-ইউজার প্যারামিটারের মান সংরক্ষণ করবে, কিন্তু শুধুমাত্র তখনই যখন নামগুলো অপরিবর্তিত থাকবে।
কার্যকৃত উদাহরণ: পূর্বে 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 কোডবেসে, আপনি প্রতিটি সিক্রেট স্পষ্টভাবে ডিক্লেয়ার এবং বাইন্ড করেন:
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 থেকে ইমেল ট্রিগার করা
পূর্বে, config.ts-এ MAIL_COLLECTION এবং SMTP_PASSWORD সরাসরি এনভায়রনমেন্ট ভেরিয়েবল হিসেবে পঠিত হতো:
# 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 এবং একটি defineSecret ; CLI উভয়কেই খুঁজে বের করে এবং .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 ব্যবহার করে নিজস্ব টাস্ক কিউতে কাজ যুক্ত করে। এটি ডিসপ্যাচ করা টাস্ক গ্রহণ করার থেকে ভিন্ন (যা Upgrade functions এবং Convert lifecycle hooks সেকশনে আলোচনা করা হয়েছে)। এখানে আপনার কোড হলো প্রডিউসার , যা queue.enqueue(...) ফাংশনটিকে কল করে।
Admin SDK এর পূর্ববর্তী সংস্করণগুলিতে, একই এক্সটেনশনের মধ্যে থাকা কোনো টাস্ক কিউ ফাংশনকে টার্গেট করার জন্য এক্সটেনশনগুলিকে তাদের নিজস্ব এক্সটেনশন ইনস্ট্যান্স আইডি দ্বিতীয় প্যারামিটার হিসেবে পাস করতে হতো। `firebase-admin` 14.2.0 সংস্করণ থেকে এটি আর প্রয়োজনীয় বা সুপারিশকৃত নয়। টাস্ক কিউ এপিআই এখন ডিফল্টরূপে একই কনটেক্সটের (যেমন এক্সটেনশন) মধ্যে থাকা টাস্ক কিউগুলিকে টার্গেট করবে। আপনার কোড থেকে এক্সটেনশন এবং স্বতন্ত্র ফাংশন উভয় ক্ষেত্রেই এই প্যারামিটারটি সরিয়ে ফেলা নিরাপদ এবং উৎসাহিত করা হয়। এই প্যারামিটারটি সরিয়ে ফেললে পোর্টেবিলিটি এবং ফরোয়ার্ড কম্প্যাটিবিলিটি নিশ্চিত হয়।
এনকিউ কল সম্পর্কিত বাকি সবকিছু — যেমন লোকেশন/ region /ফাংশন/ name রিসোর্স পাথ, টাস্ক পেলোড এবং আপনার রিট্রাই লজিক — একই থাকে।
Cloud Tasks ব্যবহার করে ফাংশন এনকিউ করার বিষয়ে আরও বিস্তারিত জানতে /docs/functions/task-functions দেখুন।
পূর্বে। প্রথম প্রজন্মের সম্প্রসারণ
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);
পরে। দ্বিতীয় প্রজন্মের সম্প্রসারণ
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);
আপনার এনকিউ কলটি যদি কোনো প্রিফিক্সযুক্ত কোডবেসকে টার্গেট করে, তাহলে আবিষ্কৃত ফাংশনের নামের আগেও একটি প্রিফিক্স যুক্ত হয় (উদাহরণস্বরূপ, 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 আরও সংকীর্ণ কোনো মডেল সমর্থন করে।
কার্যকরী উদাহরণ: ফায়ারস্টোর থেকে BigQuery ডেটা স্ট্রিম করা
পূর্বে, extension.yaml-এ ঘোষিত; এক্সটেনশন রানটাইম এপিআইটি সক্রিয় করেছিল এবং একটি পরিচালিত অ্যাকাউন্টে ভূমিকাগুলো প্রদান করেছিল:
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 , তাহলে সেই কলগুলো মুছে ফেলুন, কারণ একটি স্বাভাবিকভাবে ডেপ্লয় করা ২য় প্রজন্মের ফাংশন থেকে কল করা হলে সেগুলো একটি এরর দেবে। লাইফসাইকেল স্টেট এখন 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 }
}
});
আপনার লাইফসাইকেল অ্যাকশনগুলোকে আইডম্পোটেন্ট করুন। ডিসপ্যাচ বা এক্সিকিউশন ব্যর্থ হলে আপনার ব্যবহারকারীদের সেগুলোকে ম্যানুয়ালি পুনরায় চালানোর প্রয়োজন হতে পারে:
firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME
firebase functions:lifecycle:run afterRedeploy CODEBASE_NAME
কার্যকরী উদাহরণ: ফায়ারস্টোর থেকে BigQuery ডেটা স্ট্রিম করা
পূর্বে extension.yaml এ lifecycleEvents , যা এক্সটেনশন রানটাইম দ্বারা চালিত হতো:
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" } });
প্রোভিশনিং আইডম্পোটেন্ট, তাই পুনরায় চালালে ডেটাসেট, টেবিল এবং ভিউগুলো সামঞ্জস্যপূর্ণ হয়ে যায়। ব্যবহারকারীরা `firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME` কমান্ডটি ব্যবহার করে ম্যানুয়ালি পুনরায় চালাতে পারেন।
আপনার ব্যবহারকারীদের জন্য ডকুমেন্ট সেটআপ
একটি প্যাকেজ
READMEলিখুন যা ন্যূনতম নিম্নলিখিত বিষয়গুলো ব্যাখ্যা করে:প্যাকেজটির জন্য প্রয়োজনীয়
.envভ্যালুগুলো।প্যাকেজটির জন্য প্রয়োজনীয় গোপনীয় তথ্য এবং বিদ্যমান গোপনীয় মানগুলো কীভাবে স্থানান্তর করতে হয়।
প্যাকেজটি
requiresRole(...)দিয়ে যে IAM রোলগুলো ঘোষণা করে।প্যাকেজটি যে গুগল এপিআইগুলো সক্ষম করে বা যার জন্য প্রয়োজন হয়।
প্যাকেজটি যে লাইফসাইকেল হুকগুলো ঘোষণা করে, এবং কীভাবে সেগুলো ম্যানুয়ালি পুনরায় চালানো যায়।
বিলিং নোট।
মূল সম্প্রসারণের তুলনায় কী পরিবর্তন হয়েছে?
কার্যকরী উদাহরণ: ফায়ারস্টোর থেকে BigQuery ডেটা স্ট্রিম করা
প্যাকেজের README-তে একটি সুনির্দিষ্ট 'কী পরিবর্তন হয়েছে' টেবিল থাকে:
| উদ্বেগ | সম্প্রসারণ হিসাবে | @firebase/firestore-bigquery-export হিসাবে |
|---|---|---|
| কনফিগারেশন | এক্সটেনশন প্যারামিটার | .env এর মাধ্যমে ফাংশনের প্যারামিটারসমূহ |
| আইএএম | এক্সটেনশন দ্বারা মঞ্জুর করা হয়েছে | requiresRole(...), যা deploy-এর সময় প্রয়োগ করা হয় |
| সরবরাহ | এক্সটেনশন দ্বারা লাইফসাইকেল টাস্ক | afterFirstDeploy / afterRedeploy টাস্ক |
| ফাংশনের নাম | ext- instanceId -fsexportbigquery | fsexportbigquery (ঐচ্ছিকভাবে উপসর্গযুক্ত) |
আপনার ২য় প্রজন্মের ফাংশন পরীক্ষা করুন
এখন আপনার কাছে একটি দ্বিতীয় প্রজন্মের ফাংশন থাকা উচিত, যা স্থাপন করা হলে আপনার এক্সটেনশনের একটি নতুন ইনস্টলেশনের মতোই আচরণ করবে। শেষ ধাপটি হলো এই প্রক্রিয়ার মধ্যে দুর্ঘটনাবশত সৃষ্ট যেকোনো সমস্যা যাচাই করা এবং সমাধান করা।
নিশ্চিত করুন যে আপনি firebase-tools >= 15.24.0 ব্যবহার করছেন, এবং এর আচরণ পরীক্ষা করার জন্য আপনার রূপান্তরিত ২য় প্রজন্মের ফাংশনটিকে উপযুক্ত রিসোর্সসহ একটি টেস্ট প্রজেক্টে ডেপ্লয় করুন। যদি আপনার এক্সটেনশন পরীক্ষা করার জন্য আগে থেকেই একটি টেস্ট প্রজেক্ট সেটআপ করা থাকে, তাহলে এই কমান্ডটি ব্যবহার করুন:
firebase deploy --only functions
এই কমান্ডটি প্রবেশ করানোর পর, এক্সটেনশনটির জন্য Firebase কনসোলে ইনস্টলেশন ফর্মটি যেভাবে পূরণ করেছিলেন, ঠিক সেইভাবেই প্যারামিটার ভ্যালুগুলোর জন্য আসা উইজার্ডটি পূরণ করুন।
কার্যকরী উদাহরণ: ফায়ারস্টোর থেকে BigQuery ডেটা স্ট্রিম করা
আমরা Cloud Firestore থেকে BigQuery -তে সম্পূর্ণ সিঙ্ক প্রক্রিয়াটি যাচাই করি:
- Cloud Firestore কনসোলে, আপনার সেট করা COLLECTION_PATH (users) কালেকশনটি তৈরি করুন, যদি সেটি আগে থেকে বিদ্যমান না থাকে।
- bigquery-mirror-test নামে একটি ডকুমেন্ট তৈরি করুন, যাতে যেকোনো ফিল্ডের যেকোনো মান থাকবে।
- BigQuery কনসোলে, মূল changelog টেবিলটি কোয়েরি করুন। এতে ডকুমেন্ট তৈরির বিবরণসহ একটিমাত্র সারি থাকা উচিত:
SELECT * FROM `PROJECT_ID.analytics.users_raw_changelog`
- সর্বশেষ ভিউটি কোয়েরি করুন, যা উপস্থিত একমাত্র ডকুমেন্টটির জন্য সর্বশেষ পরিবর্তন ইভেন্টটি ফেরত দেবে:
bigquery-mirror-test
SELECT * FROM `PROJECT_ID.analytics.users_raw_latest`
- Cloud Firestore
bigquery-mirror-testডকুমেন্টটি ডিলিট করুন। এটি লেটেস্ট ভিউ থেকে অদৃশ্য হয়ে যাবে এবং র' চেঞ্জলগ টেবিলে একটি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ব্যবহার করে এমুলেটরে ব্যবহারের জন্য প্যারামিটারগুলোর মান নির্ধারণ করতে পারেন। এছাড়াও, Cloud Functions ইউনিট টেস্টিং অংশে বর্ণিত পদ্ধতি অনুযায়ী আপনি firebase-functions-test SDK ব্যবহার করে আপনার কোডের ইউনিট টেস্ট করতে পারেন। - প্রোভিশনিং এখন আর এক্সটেনশনস রানটাইম দ্বারা চালিত হয় না। ডিপ্লয়ের পর যদি চেঞ্জলগ টেবিলটি অনুপস্থিত থাকে, তাহলে সেটআপ টাস্কটি ম্যানুয়ালি পুনরায় চালান:
firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME। টাস্কটি আইডম্পোটেন্ট, তাই এটি পুনরায় চালালে ডেটাসেট, টেবিল এবং ভিউগুলো রিকনসাইল হয়ে যায়। - প্যারামিটারের মানগুলো ইনস্টলেশন ফর্মের পরিবর্তে
.envফাইল থেকে আসে, তাই.envফাইলের কাজ শেষ হয়ে গেলেfirebase deployপুনরায় চালালে তা আর ইন্টারেক্টিভ থাকে না।