Cloud Firestore ট্রিগার (ফার্স্ট জেনারেশন)

Cloud Functions-এর সাহায্যে, আপনি ক্লায়েন্ট কোড আপডেট করার প্রয়োজন ছাড়াই Cloud Firestore-এ ইভেন্ট ম্যানেজ করতে পারবেন। আপনি ডকুমেন্ট স্ন্যাপশট ইন্টারফেস বা Admin SDK-এর মাধ্যমে Cloud Firestore-এ পরিবর্তন করতে পারবেন।

সাধারণ লাইফসাইকেলে, Cloud Firestore ফাংশন নিম্নলিখিত কাজগুলি করে:

  1. নির্দিষ্ট ডকুমেন্টে পরিবর্তনের জন্য অপেক্ষা করে।
  2. কোনও ইভেন্ট ঘটলে ট্রিগার হয় এবং নিজের কাজ করে।
  3. নির্দিষ্ট ডকুমেন্টে সেভ করা ডেটার স্ন্যাপশট থাকা ডেটা অবজেক্ট পায়। ইভেন্ট লেখার বা আপডেট করার জন্য, ডেটা অবজেক্টে দুটি স্ন্যাপশট থাকে যা ট্রিগার করা ইভেন্টের আগে ও পরে ডেটার অবস্থা দেখায়।

Firestore ইনস্ট্যান্সের লোকেশন ও ফাংশনের লোকেশনের মধ্যবর্তী দূরত্ব উল্লেখযোগ্য নেটওয়ার্ক লেটেন্সি তৈরি করতে পারে। পারফর্ম্যান্স অপ্টিমাইজ করতে, প্রযোজ্য হলে ফাংশন লোকেশন নির্দিষ্ট করার কথা বিবেচনা করুন।

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 Admin 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 (2nd gen) ব্যবহার করুন।
  • Cloud Functions এবং Cloud Firestore ট্রিগার সহ ক্রস প্রজেক্ট সেট-আপ একটি সীমাবদ্ধতা। Cloud Firestore ট্রিগার Cloud Functions সেট-আপ করতে, সেটি একই প্রোজেক্টে থাকতে হবে।
  • অর্ডার করার ব্যাপারে কোনও গ্যারেন্টি নেই। দ্রুত পরিবর্তন হলে, অপ্রত্যাশিত ক্রমে ফাংশন ইনভোকেশন ট্রিগার হতে পারে।
  • ইভেন্ট অন্তত একবার ডেলিভার করা হয়, কিন্তু একটি ইভেন্টের ফলে একাধিক ফাংশন ইনভোকেশন হতে পারে। "ঠিক একবার" মেকানিজমের উপর নির্ভর করা এড়িয়ে চলুন এবং আইডেমপোটেন্ট ফাংশন লিখুন।
  • Cloud Firestore Datastore মোডে Cloud Functions (2nd gen) প্রয়োজন। Cloud Functions (ফার্স্ট জেনারেশন) Datastore মোডে কাজ করে না।
  • একটি ট্রিগার একটি ডেটাবেসের সাথে যুক্ত থাকে। আপনি এমন কোনও ট্রিগার তৈরি করতে পারবেন না যা একাধিক ডেটাবেসের সাথে ম্যাচ করে।
  • কোনও ডেটাবেস মুছে দিলে, সেই ডেটাবেসের জন্য কোনও ট্রিগার অটোমেটিক মুছে যায় না। ট্রিগার মুছে না দেওয়া পর্যন্ত ট্রিগার ইভেন্ট ডেলিভার করা বন্ধ করে দেয়, কিন্তু সেটি থেকে যায়।
  • ম্যাচ করা ইভেন্ট অনুরোধের সর্বাধিক সাইজ-এর থেকে বড় হলে, Cloud Functions (1st gen)-এ ইভেন্ট ডেলিভার করা নাও হতে পারে।
    • অনুরোধের সাইজ বড় হওয়ার কারণে ডেলিভার করা যায়নি এমন ইভেন্ট প্ল্যাটফর্ম লগে লগ করা হয় এবং প্রজেক্টের জন্য লগ ব্যবহারের মধ্যে গণনা করা হয়।
    • আপনি এই লগগুলি, লগ এক্সপ্লোরারে "1st gen-এর জন্য নির্ধারিত সীমা অতিক্রম করার কারণে ইভেন্ট ক্লাউড ফাংশনে ডেলিভার করা যাচ্ছে না..." মেসেজ সহ error গুরুত্বের সাথে দেখতে পাবেন। আপনি functionName ফিল্ডের মধ্যে ফাংশনের নাম দেখতে পাবেন। যদি receiveTimestamp ফিল্ডটি এখনও এক ঘণ্টার মধ্যে থাকে, তাহলে আপনি টাইমস্ট্যাম্পের আগে ও পরে স্ন্যাপশট সহ প্রশ্নযুক্ত ডকুমেন্টটি পড়ে আসল ইভেন্ট কন্টেন্ট সম্পর্কে জানতে পারবেন।
    • এই ধরনের ক্যাডেন্স এড়াতে, আপনি:
      • Cloud Functions (2nd gen)-এ মাইগ্রেট ও আপগ্রেড করা
      • ডকুমেন্টের সাইজ কমানো
      • যে Cloud Functions নিয়ে প্রশ্ন উঠেছে সেটি মুছে দিন
    • আপনি বাদ দেওয়া ব্যবহার করে লগিং বন্ধ করতে পারেন তবে মনে রাখবেন যে সমস্যা সৃষ্টিকারী ইভেন্টগুলি এখনও ডেলিভার করা হবে না।