Cloud Functions (ফার্স্ট জেনারেশন)-এর মাধ্যমে Cloud Firestore-এর কার্যকারিতা বাড়ানো

Cloud Functions-এর সাহায্যে, আপনি Node.js কোড ডেপ্লয় করতে পারবেন যাতে আপনার Cloud Firestore ডেটাবেসে পরিবর্তনের মাধ্যমে ট্রিগার হওয়া ইভেন্ট ম্যানেজ করা যায়। এর ফলে, আপনি নিজের সার্ভার না চালিয়েই অ্যাপে সহজেই সার্ভার-সাইড ফাংশনালিটি যোগ করতে পারবেন।

ব্যবহারের উদাহরণ দেখতে, আমি Cloud Functions-এর সাহায্যে কী করতে পারি? দেখুন অথবা ফাংশন স্যাম্পেল GitHub রিপোজিটরি।

Cloud Firestore ফাংশন ট্রিগার

Cloud Functions for Firebase SDK একটি functions.firestore অবজেক্ট এক্সপোর্ট করে যা আপনাকে নির্দিষ্ট Cloud Firestore ইভেন্টের সাথে যুক্ত হ্যান্ডলার তৈরি করতে দেয়।

ইভেন্টের ধরন Trigger
onCreate প্রথমবার কোনও ডকুমেন্ট লেখা হলে ট্রিগার করা হয়।
onUpdate ডকুমেন্ট আগে থেকেই থাকলে এবং কোনও ভ্যালু পরিবর্তন হলে ট্রিগার করা হয়।
onDelete ডেটা সহ কোনও ডকুমেন্ট মুছে ফেলা হলে ট্রিগার করা হয়।
onWrite onCreate, onUpdate বা onDelete ট্রিগার করা হলে ট্রিগার করা হয়।

আপনার যদি এখনও Cloud Functions for Firebase-এর জন্য কোনও প্রোজেক্ট চালু না থাকে, তাহলে শুরু করুন: আপনার প্রথম ফাংশন লিখুন এবং ডিপ্লয় করুন পড়ুন যাতে আপনার Cloud Functions for Firebase প্রোজেক্ট কনফিগার এবং সেট-আপ করতে পারেন।

Cloud Firestore-ট্রিগার করা ফাংশন লেখা হচ্ছে

ফাংশন ট্রিগার নির্দিষ্ট করুন

Cloud Firestore ট্রিগার নির্ধারণ করতে, একটি ডকুমেন্ট পাথ এবং ইভেন্টের ধরন উল্লেখ করুন:

Node.js

const functions = require('firebase-functions');

exports.myFunction = functions.firestore
  .document('my-collection/{docId}')
  .onWrite((change, context) => { /* ... */ });

ডকুমেন্ট পাথ হয় কোনও নির্দিষ্ট ডকুমেন্ট অথবা ওয়াইল্ডকার্ড প্যাটার্ন রেফারেন্স হিসেবে ব্যবহার করতে পারে।

একটি ডকুমেন্ট নির্দিষ্ট করুন

আপনি যদি কোনও নির্দিষ্ট ডকুমেন্টে যেকোনও পরিবর্তনের জন্য কোনও ইভেন্ট ট্রিগার করতে চান, তাহলে আপনি নিম্নলিখিত ফাংশনটি ব্যবহার করতে পারেন।

Node.js

// Listen for any change on document `marie` in collection `users`
exports.myFunctionName = functions.firestore
    .document('users/marie').onWrite((change, context) => {
      // ... Your code here
    });

ওয়াইল্ডকার্ড ব্যবহার করে ডকুমেন্টের একটি গ্রুপ নির্দিষ্ট করুন

আপনি যদি কোনও ডকুমেন্টের গ্রুপে ট্রিগার অ্যাটাচ করতে চান, যেমন কোনও নির্দিষ্ট কালেকশনের কোনও ডকুমেন্ট, তাহলে ডকুমেন্ট আইডির জায়গায় {wildcard} ব্যবহার করুন:

Node.js

// 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-এ স্টোর করা হয়। স্পষ্ট কালেকশন বা ডকুমেন্ট আইডি প্রতিস্থাপন করার জন্য আপনি যত খুশি ওয়াইল্ডকার্ড নির্ধারণ করতে পারেন, যেমন:

Node.js

// 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 কল করে:

Node.js

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-এ কল করে যদি কোনও ব্যবহারকারী তার প্রোফাইল পরিবর্তন করেন:

Node.js

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 কল করে:

Node.js

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() ফাংশন ব্যবহার করে Cloud Firestore ডকুমেন্টের সব পরিবর্তন শুনতে পারবেন। এই উদাহরণ ফাংশন modifyUser-এ কল করে যদি কোনও ব্যবহারকারী তৈরি, আপডেট বা মুছে ফেলা হয়:

Node.js

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 অ্যাডমিন SDK ব্যবহার করে আপনার ডেটাবেসের অন্যান্য অংশ অ্যাক্সেস করতে পারবেন।

ইভেন্ট ডেটা

রিডিং ডেটা

কোনও ফাংশন ট্রিগার করা হলে, আপনি হয়ত আপডেট করা হয়েছে এমন কোনও ডকুমেন্ট থেকে ডেটা পেতে চাইবেন অথবা আপডেট করার আগে ডেটা পেতে চাইবেন। আপনি change.before.data() ব্যবহার করে আগের ডেটা পেতে পারেন, যার মধ্যে আপডেট করার আগে ডকুমেন্টের স্ন্যাপশট থাকে। একইভাবে, change.after.data()-এ আপডেট করার পরে ডকুমেন্ট স্ন্যাপশট স্টেট থাকে।

Node.js

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 ফাংশন ব্যবহার করতে পারেন:

Node.js

// 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');

রাইটিং ডেটা

প্রতিটি ফাংশন ইনভোকেশন আপনার Cloud Firestore ডেটাবেসের নির্দিষ্ট ডকুমেন্টের সাথে যুক্ত। আপনার ফাংশনে ফেরত আসা স্ন্যাপশটের ref প্রপার্টিতে আপনি সেই ডকুমেন্ট DocumentReference হিসেবে অ্যাক্সেস করতে পারবেন।

এই DocumentReference Cloud Firestore Node.js SDK থেকে আসে এবং এতে update(), set() ও remove()-এর মতো পদ্ধতি অন্তর্ভুক্ত থাকে যাতে আপনি সহজেই ফাংশন ট্রিগার করা ডকুমেন্ট পরিবর্তন করতে পারেন।

Node.js

// 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 ব্যবহার করে রিড ও রাইট করতে পারবেন:

Node.js

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 Functions-এর জন্য Cloud Firestore ট্রিগারের ক্ষেত্রে নিম্নলিখিত সীমাবদ্ধতাগুলি মনে রাখবেন:

  • Cloud Functions (ফার্স্ট জেনারেশন) Firestore নেটিভ মোডে আগে থেকে থাকা "(ডিফল্ট)" ডেটাবেসকে পূর্বশর্ত হিসেবে ব্যবহার করে। এটি Cloud Firestore নামের ডেটাবেস বা Datastore মোড সাপোর্ট করে না। এই ধরনের ক্ষেত্রে ইভেন্ট কনফিগার করতে Cloud Functions (২য় জেনারেশন) ব্যবহার করুন।
  • Cloud Functions এবং Cloud Firestore ট্রিগার সহ ক্রস প্রোজেক্ট সেট-আপের ক্ষেত্রে সীমাবদ্ধতা আছে। Cloud Firestore ট্রিগার সেট-আপ করতে, Cloud Functions একই প্রোজেক্টে থাকতে হবে।
  • অর্ডার করার বিষয়ে কোনও গ্যারেন্টি দেওয়া হয় না। দ্রুত পরিবর্তন করলে অপ্রত্যাশিত ক্রমে ফাংশন ইনভোকেশন ট্রিগার হতে পারে।
  • ইভেন্ট অন্তত একবার ডেলিভার করা হয়, তবে একটি ইভেন্টের ফলে একাধিক ফাংশন ইনভোকেশন হতে পারে। একবার-মাত্র মেকানিক্সের উপর নির্ভর করা এড়িয়ে চলুন এবং আইডেমপোটেন্ট ফাংশন লিখুন।
  • Datastore মোডে Cloud Firestore-এর জন্য Cloud Functions (২য় জেনারেশন) প্রয়োজন। Cloud Functions (ফার্স্ট জেনারেশন) Datastore মোড কাজ করে না।
  • একটি ট্রিগার একটি ডেটাবেসের সাথে যুক্ত থাকে। আপনি একাধিক ডেটাবেসের সাথে মেলে এমন ট্রিগার তৈরি করতে পারবেন না।
  • কোনও ডেটাবেস মুছে দিলে, সেই ডেটাবেসের জন্য কোনও ট্রিগার অটোমেটিক মুছে যায় না। ট্রিগার ইভেন্ট ডেলিভার করা বন্ধ করে দেয়, তবে আপনি ট্রিগার মুছে না দেওয়া পর্যন্ত এটি থেকে যায়।
  • কোনও ম্যাচ করা ইভেন্ট সর্বাধিক অনুরোধের সাইজ অতিক্রম করলে, ইভেন্টটি হয়ত Cloud Functions (ফার্স্ট জেনারেশন)-এ ডেলিভার করা হবে না।
    • অনুরোধের সাইজের কারণে যেসব ইভেন্ট ডেলিভার করা হয়নি সেগুলি প্ল্যাটফর্ম লগে লগ করা হয় এবং প্রোজেক্টের জন্য লগ ব্যবহারের ক্ষেত্রে গণনা করা হয়।
    • আপনি Logs Explorer-এ "ফার্স্ট জেনারেশনের জন্য সাইজ সীমা অতিক্রম করার কারণে ইভেন্ট Cloud ফাংশনে ডেলিভার করা যাচ্ছে না..." মেসেজ সহ error গুরুত্বের এই লগগুলি খুঁজে পেতে পারেন। আপনি functionName ফিল্ডের অধীনে ফাংশনের নাম খুঁজে পেতে পারেন। যদি receiveTimestamp ফিল্ডটি এখনও এক ঘণ্টার মধ্যে থাকে, তাহলে আপনি টাইমস্ট্যাম্পের আগে এবং পরে স্ন্যাপশট সহ প্রশ্ন করা ডকুমেন্টটি পড়ে প্রকৃত ইভেন্ট কন্টেন্ট অনুমান করতে পারেন।
    • এই ধরনের ছন্দ এড়াতে, আপনি এগুলি করতে পারেন:
      • মাইগ্রেট করে Cloud Functions (সেকেন্ড জেনারেশন)-এ আপগ্রেড করুন
      • ডকুমেন্টের সাইজ কমানো
      • প্রশ্ন থেকে Cloud Functions মুছে দিন
    • আপনি বাদ দেওয়া ব্যবহার করে লগিং বন্ধ করতে পারেন তবে মনে রাখবেন যে আপত্তিকর ইভেন্টগুলি এখনও ডেলিভার করা হবে না।