Cloud Functions ব্যবহার করে, ক্লায়েন্ট কোড আপডেট করার প্রয়োজন ছাড়াই আপনি ক্লাউড ফায়ারস্টোরের ইভেন্টগুলো পরিচালনা করতে পারেন। আপনি ডকুমেন্ট স্ন্যাপশট ইন্টারফেস অথবা অ্যাডমিন এসডিকে (Admin SDK) -এর মাধ্যমে ক্লাউড ফায়ারস্টোরে পরিবর্তন আনতে পারেন।
একটি সাধারণ জীবনচক্রে, একটি ক্লাউড ফায়ারস্টোর ফাংশন নিম্নলিখিত কাজগুলো করে থাকে:
- একটি নির্দিষ্ট নথিতে পরিবর্তনের জন্য অপেক্ষা করে।
- কোনো ঘটনা ঘটলে এটি সক্রিয় হয় এবং এর কাজগুলো সম্পাদন করে।
- একটি ডেটা অবজেক্ট গ্রহণ করে, যাতে নির্দিষ্ট ডকুমেন্টে সংরক্ষিত ডেটার একটি স্ন্যাপশট থাকে। রাইট বা আপডেট ইভেন্টের ক্ষেত্রে, ডেটা অবজেক্টটিতে দুটি স্ন্যাপশট থাকে যা ট্রিগারিং ইভেন্টের আগে ও পরের ডেটার অবস্থাকে উপস্থাপন করে।
ফায়ারস্টোর ইনস্ট্যান্সের অবস্থান এবং ফাংশনের অবস্থানের মধ্যে দূরত্বের কারণে উল্লেখযোগ্য নেটওয়ার্ক লেটেন্সি তৈরি হতে পারে। পারফরম্যান্স অপ্টিমাইজ করার জন্য, যেখানে প্রযোজ্য সেখানে ফাংশনের অবস্থান নির্দিষ্ট করে দেওয়ার কথা বিবেচনা করুন।
ক্লাউড ফায়ারস্টোর ফাংশন ট্রিগার
Cloud Functions for Firebase SDK একটি functions.firestore অবজেক্ট এক্সপোর্ট করে, যা আপনাকে নির্দিষ্ট Cloud Firestore ইভেন্টের সাথে যুক্ত হ্যান্ডলার তৈরি করার সুযোগ দেয়।
| ইভেন্টের ধরণ | ট্রিগার |
|---|---|
onCreate | কোনো ডকুমেন্টে প্রথমবারের মতো কিছু লেখা হলে এটি সক্রিয় হয়। |
onUpdate | যখন কোনো ডকুমেন্ট আগে থেকেই বিদ্যমান থাকে এবং তার কোনো মান পরিবর্তিত হয়, তখন এটি সক্রিয় হয়। |
onDelete | ডেটা সহ কোনো ডকুমেন্ট মুছে ফেলা হলে এটি সক্রিয় হয়। |
onWrite | যখন onCreate , onUpdate বা onDelete ট্রিগার হয়, তখন এটিও ট্রিগার হয়। |
আপনার প্রজেক্টে যদি এখনও Cloud Functions for Firebase সক্রিয় করা না থাকে, তাহলে আপনার Cloud Functions for Firebase প্রজেক্টটি কনফিগার ও সেট আপ করার জন্য "Get Started: Write and Deploy Your First Functions" পড়ুন।
ক্লাউড ফায়ারস্টোর-ট্রিগারড ফাংশন লেখা
একটি ফাংশন ট্রিগার সংজ্ঞায়িত করুন
একটি ক্লাউড ফায়ারস্টোর ট্রিগার নির্ধারণ করতে, একটি ডকুমেন্ট পাথ এবং একটি ইভেন্ট টাইপ নির্দিষ্ট করুন:
নোড.জেএস
const functions = require('firebase-functions');
exports.myFunction = functions.firestore
.document('my-collection/{docId}')
.onWrite((change, context) => { /* ... */ });
ডকুমেন্ট পাথ কোনো নির্দিষ্ট ডকুমেন্ট অথবা ওয়াইল্ডকার্ড প্যাটার্নকে নির্দেশ করতে পারে।
একটি একক নথি নির্দিষ্ট করুন
যদি আপনি কোনো নির্দিষ্ট ডকুমেন্টের যেকোনো পরিবর্তনের জন্য একটি ইভেন্ট ট্রিগার করতে চান, তাহলে আপনি নিম্নলিখিত ফাংশনটি ব্যবহার করতে পারেন।
নোড.জেএস
// Listen for any change on document `marie` in collection `users` exports.myFunctionName = functions.firestore .document('users/marie').onWrite((change, context) => { // ... Your code here });
ওয়াইল্ডকার্ড ব্যবহার করে নথির একটি গোষ্ঠী নির্দিষ্ট করুন
যদি আপনি একদল ডকুমেন্টের সাথে, যেমন কোনো নির্দিষ্ট কালেকশনের যেকোনো ডকুমেন্টের সাথে, একটি ট্রিগার সংযুক্ত করতে চান, তাহলে ডকুমেন্ট আইডির পরিবর্তে একটি {wildcard} ব্যবহার করুন:
নোড.জেএস
// Listen for changes in all documents in the 'users' collection exports.useWildcard = functions.firestore .document('users/{userId}') .onWrite((change, context) => { // If we set `/users/marie` to {name: "Marie"} then // context.params.userId == "marie" // ... and ... // change.after.data() == {name: "Marie"} });
এই উদাহরণে, যখন users যেকোনো ডকুমেন্টের যেকোনো ফিল্ড পরিবর্তন করা হয়, তখন তা userId নামক একটি ওয়াইল্ডকার্ডের সাথে মিলে যায়।
যদি users কোনো ডকুমেন্টের সাব-কালেকশন থাকে এবং সেই সাব-কালেকশনগুলোর কোনো একটির ডকুমেন্টের কোনো ফিল্ড পরিবর্তন করা হয়, তাহলে userId ওয়াইল্ডকার্ডটি সক্রিয় হয় না ।
ডকুমেন্ট পাথ থেকে ওয়াইল্ডকার্ড ম্যাচগুলো বের করে context.params এ সংরক্ষণ করা হয়। আপনি সুনির্দিষ্ট কালেকশন বা ডকুমেন্ট আইডির পরিবর্তে আপনার পছন্দমতো যত খুশি ওয়াইল্ডকার্ড ব্যবহার করতে পারেন, উদাহরণস্বরূপ:
নোড.জেএস
// Listen for changes in all documents in the 'users' collection and all subcollections exports.useMultipleWildcards = functions.firestore .document('users/{userId}/{messageCollectionId}/{messageId}') .onWrite((change, context) => { // If we set `/users/marie/incoming_messages/134` to {body: "Hello"} then // context.params.userId == "marie"; // context.params.messageCollectionId == "incoming_messages"; // context.params.messageId == "134"; // ... and ... // change.after.data() == {body: "Hello"} });
ইভেন্ট ট্রিগার
নতুন ডকুমেন্ট তৈরি হলে একটি ফাংশন চালু করুন।
কোনো কালেকশনে নতুন ডকুমেন্ট তৈরি হওয়ার সাথে সাথে ফাংশনটি চালু করার জন্য আপনি ওয়াইল্ডকার্ডসহ একটি onCreate() হ্যান্ডলার ব্যবহার করতে পারেন। এই উদাহরণ ফাংশনটি প্রতিবার নতুন ব্যবহারকারীর প্রোফাইল যোগ করার সময় createUser কল করে:
নোড.জেএস
exports.createUser = functions.firestore .document('users/{userId}') .onCreate((snap, context) => { // Get an object representing the document // e.g. {'name': 'Marie', 'age': 66} const newValue = snap.data(); // access a particular field as you would any JS property const name = newValue.name; // perform desired operations ... });
যখন কোনো ডকুমেন্ট আপডেট করা হয় তখন একটি ফাংশন ট্রিগার করুন।
আপনি ওয়াইল্ডকার্ড সহ onUpdate() ফাংশন ব্যবহার করে কোনো ডকুমেন্ট আপডেট হলে একটি ফাংশন চালু করার জন্যও ট্রিগার করতে পারেন। এই উদাহরণ ফাংশনটি কোনো ব্যবহারকারী তার প্রোফাইল পরিবর্তন করলে updateUser কল করে:
নোড.জেএস
exports.updateUser = functions.firestore .document('users/{userId}') .onUpdate((change, context) => { // Get an object representing the document // e.g. {'name': 'Marie', 'age': 66} const newValue = change.after.data(); // ...or the previous value before this update const previousValue = change.before.data(); // access a particular field as you would any JS property const name = newValue.name; // perform desired operations ... });
যখন কোনো ডকুমেন্ট মুছে ফেলা হয় তখন একটি ফাংশন সক্রিয় করুন।
আপনি ওয়াইল্ডকার্ড সহ onDelete() ফাংশন ব্যবহার করে কোনো ডকুমেন্ট ডিলিট করার সময়েও একটি ফাংশন ট্রিগার করতে পারেন। এই উদাহরণ ফাংশনটি কোনো ব্যবহারকারী তার ইউজার প্রোফাইল ডিলিট করলে deleteUser কল করে:
নোড.জেএস
exports.deleteUser = functions.firestore .document('users/{userID}') .onDelete((snap, context) => { // Get an object representing the document prior to deletion // e.g. {'name': 'Marie', 'age': 66} const deletedValue = snap.data(); // perform desired operations ... });
একটি ডকুমেন্টের সমস্ত পরিবর্তনের জন্য একটি ফাংশন সক্রিয় করুন।
কোন ধরনের ইভেন্ট ফায়ার হচ্ছে তা নিয়ে যদি আপনার কোনো মাথাব্যথা না থাকে, তাহলে আপনি ওয়াইল্ডকার্ডসহ onWrite() ফাংশন ব্যবহার করে একটি ক্লাউড ফায়ারস্টোর ডকুমেন্টের সমস্ত পরিবর্তন শুনতে পারেন। এই উদাহরণ ফাংশনটি কোনো ব্যবহারকারী তৈরি, আপডেট বা ডিলিট করা হলে modifyUser কল করে:
নোড.জেএস
exports.modifyUser = functions.firestore .document('users/{userID}') .onWrite((change, context) => { // Get an object with the current document value. // If the document does not exist, it has been deleted. const document = change.after.exists ? change.after.data() : null; // Get an object with the previous document value (for update or delete) const oldDocument = change.before.data(); // perform desired operations ... });
ডেটা পড়া এবং লেখা
যখন কোনো ফাংশন ট্রিগার হয়, তখন এটি ইভেন্ট-সম্পর্কিত ডেটার একটি স্ন্যাপশট প্রদান করে। আপনি এই স্ন্যাপশটটি ব্যবহার করে ইভেন্টটি ট্রিগার করা ডকুমেন্ট থেকে ডেটা পড়তে বা তাতে লিখতে পারেন, অথবা আপনার ডাটাবেসের অন্যান্য অংশ অ্যাক্সেস করার জন্য Firebase Admin SDK ব্যবহার করতে পারেন।
ইভেন্ট ডেটা
ডেটা পড়া
যখন কোনো ফাংশন ট্রিগার হয়, তখন আপনার আপডেট হওয়া কোনো ডকুমেন্ট থেকে ডেটা অথবা আপডেটের আগের ডেটা পাওয়ার প্রয়োজন হতে পারে। আপনি change.before.data() ব্যবহার করে আগের ডেটা পেতে পারেন, যাতে আপডেটের আগের ডকুমেন্ট স্ন্যাপশটটি থাকে। একইভাবে, change.after.data() আপডেটের পরের ডকুমেন্ট স্ন্যাপশট অবস্থাটি থাকে।
নোড.জেএস
exports.updateUser2 = functions.firestore .document('users/{userId}') .onUpdate((change, context) => { // Get an object representing the current document const newValue = change.after.data(); // ...or the previous value before this update const previousValue = change.before.data(); });
আপনি অন্য যেকোনো অবজেক্টের মতোই প্রোপার্টিগুলো অ্যাক্সেস করতে পারেন। বিকল্পভাবে, নির্দিষ্ট ফিল্ড অ্যাক্সেস করার জন্য আপনি get ফাংশনটি ব্যবহার করতে পারেন:
নোড.জেএস
// Fetch data using standard accessors const age = snap.data().age; const name = snap.data()['name']; // Fetch data using built in accessor const experience = snap.get('experience');
ডেটা লেখা
প্রতিটি ফাংশন আহ্বান আপনার ক্লাউড ফায়ারস্টোর ডেটাবেসের একটি নির্দিষ্ট ডকুমেন্টের সাথে যুক্ত থাকে। আপনার ফাংশনে ফেরত আসা স্ন্যাপশটের ref প্রপার্টিতে আপনি DocumentReference হিসেবে সেই ডকুমেন্টটি অ্যাক্সেস করতে পারেন।
এই DocumentReference Cloud Firestore Node.js SDK থেকে এসেছে এবং এতে update() , set() , ও remove() এর মতো মেথড অন্তর্ভুক্ত রয়েছে, যার ফলে আপনি যে ডকুমেন্টটি ফাংশনটি ট্রিগার করেছে, সেটিকে সহজেই পরিবর্তন করতে পারবেন।
নোড.জেএস
// Listen for updates to any `user` document. exports.countNameChanges = functions.firestore .document('users/{userId}') .onUpdate((change, context) => { // Retrieve the current and previous value const data = change.after.data(); const previousData = change.before.data(); // We'll only update if the name has changed. // This is crucial to prevent infinite loops. if (data.name == previousData.name) { return null; } // Retrieve the current count of name changes let count = data.name_change_count; if (!count) { count = 0; } // Then return a promise of a set operation to update the count return change.after.ref.set({ name_change_count: count + 1 }, {merge: true}); });
ট্রিগার ইভেন্টের বাইরের ডেটা
Cloud Functions একটি বিশ্বস্ত পরিবেশে চলে, যার অর্থ হলো এগুলো আপনার প্রোজেক্টে একটি সার্ভিস অ্যাকাউন্ট হিসেবে অনুমোদিত। আপনি Firebase Admin SDK ব্যবহার করে রিড এবং রাইট অপারেশন করতে পারেন।
নোড.জেএস
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
exports.writeToFirestore = functions.firestore
.document('some/doc')
.onWrite((change, context) => {
db.doc('some/otherdoc').set({ ... });
});
সীমাবদ্ধতা
ক্লাউড ফাংশনের জন্য Cloud Firestore ট্রিগারের ক্ষেত্রে নিম্নলিখিত সীমাবদ্ধতাগুলো লক্ষ্য করুন:
- Cloud Functions (১ম জেনারেশন) ব্যবহারের জন্য ফায়ারস্টোর নেটিভ মোডে একটি বিদ্যমান "(ডিফল্ট)" ডেটাবেস থাকা আবশ্যক। এটি Cloud Firestore নেমড ডেটাবেস বা ডেটাস্টোর মোড সমর্থন করে না। এই ধরনের ক্ষেত্রে ইভেন্ট কনফিগার করার জন্য অনুগ্রহ করে Cloud Functions (২য় জেনারেশন) ব্যবহার করুন।
- Cloud Functions এবং Cloud Firestore ট্রিগারের ক্ষেত্রে ক্রস-প্রজেক্ট সেটআপ একটি সীমাবদ্ধতা। Cloud Firestore ট্রিগার সেটআপ করার জন্য Cloud Functions অবশ্যই একই প্রজেক্টে থাকতে হবে।
- ক্রম নিশ্চিত নয়। দ্রুত পরিবর্তনের ফলে ফাংশনগুলো অপ্রত্যাশিত ক্রমে চালু হতে পারে।
- ইভেন্টগুলো অন্তত একবার ডেলিভার করা হয়, কিন্তু একটিমাত্র ইভেন্টের ফলে একাধিকবার ফাংশন কল হতে পারে। এক্স্যাক্টলি-ওয়ান্স মেকানিক্সের উপর নির্ভর করা পরিহার করুন এবং আইডম্পোটেন্ট ফাংশন লিখুন।
- ডেটাস্টোর মোডে Cloud Firestore ব্যবহার করতে Cloud Functions (২য় জেনারেশন) প্রয়োজন। Cloud Functions (১ম জেনারেশন) ডেটাস্টোর মোড সমর্থন করে না।
- একটি ট্রিগার একটিমাত্র ডেটাবেসের সাথে যুক্ত থাকে। আপনি একাধিক ডেটাবেসের সাথে মেলে এমন ট্রিগার তৈরি করতে পারবেন না।
- একটি ডাটাবেস মুছে ফেললে সেই ডাটাবেসের কোনো ট্রিগার স্বয়ংক্রিয়ভাবে মুছে যায় না। ট্রিগারটি ইভেন্ট পাঠানো বন্ধ করে দেয়, কিন্তু আপনি ট্রিগারটি মুছে না ফেলা পর্যন্ত এর অস্তিত্ব বজায় থাকে।
- যদি কোনো মিলে যাওয়া ইভেন্ট সর্বোচ্চ অনুরোধের আকার অতিক্রম করে, তাহলে ইভেন্টটি Cloud Functions (১ম প্রজন্ম)-এ সরবরাহ নাও করা হতে পারে।
- অনুরোধের আকারের কারণে যে ইভেন্টগুলো ডেলিভারি করা হয় না, সেগুলো প্ল্যাটফর্ম লগে নথিভুক্ত করা হয় এবং প্রজেক্টের লগ ব্যবহারের হিসাবে গণনা করা হয়।
- আপনি এই লগগুলি লগস এক্সপ্লোরারে "Event cannot deliver to Cloud function due to size exceeding the limit for 1st gen..." এই
errorসিভিয়ারিটি মেসেজ সহ খুঁজে পাবেন। আপনিfunctionNameফিল্ডের অধীনে ফাংশনের নামটি খুঁজে পাবেন। যদিreceiveTimestampফিল্ডটি এখন থেকে এক ঘণ্টার মধ্যে থাকে, তাহলে আপনি টাইমস্ট্যাম্পের আগের এবং পরের একটি স্ন্যাপশট দিয়ে সংশ্লিষ্ট ডকুমেন্টটি পড়ে প্রকৃত ইভেন্টের বিষয়বস্তু অনুমান করতে পারবেন। - এই ধরনের ছন্দ এড়াতে, আপনি যা করতে পারেন:
- Cloud Functions (২য় প্রজন্ম)-এ মাইগ্রেট এবং আপগ্রেড করুন
- ডকুমেন্টটির আকার ছোট করুন
- প্রশ্নোক্ত Cloud Functions মুছে ফেলুন
- আপনি এক্সক্লুশন ব্যবহার করে লগিং বন্ধ করতে পারেন, কিন্তু মনে রাখবেন যে আপত্তিকর ইভেন্টগুলো তখনও ডেলিভার করা হবে না।