ক্লাউড ফাংশন সহ রিয়েলটাইম ডাটাবেস প্রসারিত করুন


Cloud Functions সাথে, আপনি ক্লায়েন্ট কোড আপডেট করার প্রয়োজন ছাড়াই Firebase Realtime Database ইভেন্টগুলি পরিচালনা করতে পারেন৷ Cloud Functions আপনাকে সম্পূর্ণ প্রশাসনিক সুবিধা সহ Realtime Database অপারেশন চালাতে দেয় এবং নিশ্চিত করে যে Realtime Database প্রতিটি পরিবর্তন পৃথকভাবে প্রক্রিয়া করা হয়েছে। আপনি DataSnapshot বা অ্যাডমিন SDK-এর মাধ্যমে Firebase Realtime Database পরিবর্তন করতে পারেন।

একটি সাধারণ জীবনচক্রে, একটি Firebase Realtime Database ফাংশন নিম্নলিখিতগুলি করে:

  1. একটি নির্দিষ্ট Realtime Database অবস্থানে পরিবর্তনের জন্য অপেক্ষা করে।
  2. কোনো ইভেন্ট ঘটলে এবং তার কার্য সম্পাদন করলে ট্রিগার করে ( Cloud Functions সাথে আমি কী করতে পারি? ব্যবহারের ক্ষেত্রে উদাহরণের জন্য দেখুন)।
  3. নির্দিষ্ট নথিতে সংরক্ষিত ডেটার একটি স্ন্যাপশট ধারণ করে এমন একটি ডেটা অবজেক্ট গ্রহণ করে।

একটি Realtime Database ফাংশন ট্রিগার করুন

functions.database দিয়ে Realtime Database ইভেন্টের জন্য নতুন ফাংশন তৈরি করুন। ফাংশনটি কখন ট্রিগার হয় তা নিয়ন্ত্রণ করতে, ইভেন্ট হ্যান্ডলারগুলির একটি নির্দিষ্ট করুন এবং Realtime Database পাথ নির্দিষ্ট করুন যেখানে এটি ইভেন্টগুলির জন্য শুনবে৷

ইভেন্ট হ্যান্ডলার সেট করুন

ফাংশনগুলি আপনাকে নির্দিষ্টতার দুটি স্তরে Realtime Database ইভেন্টগুলি পরিচালনা করতে দেয়; আপনি বিশেষভাবে শুধুমাত্র সৃষ্টি, আপডেট, বা মুছে ফেলার ইভেন্টের জন্য শুনতে পারেন, অথবা আপনি কোনো পাথের যেকোনো ধরনের পরিবর্তনের জন্য শুনতে পারেন। Cloud Functions Realtime Database জন্য এই ইভেন্ট হ্যান্ডলারদের সমর্থন করে:

  • onWrite() , যা Realtime Database ডেটা তৈরি, আপডেট করা বা মুছে ফেলার সময় ট্রিগার করে।
  • onCreate() , যা Realtime Database নতুন ডেটা তৈরি হলে ট্রিগার করে।
  • onUpdate() , যা Realtime Database ডেটা আপডেট করার সময় ট্রিগার করে।
  • onDelete() , যা Realtime Database থেকে ডেটা মুছে ফেলা হলে ট্রিগার করে।

উদাহরণ এবং পথ নির্দিষ্ট করুন

কখন এবং কোথায় আপনার ফাংশনটি ট্রিগার হবে তা নিয়ন্ত্রণ করতে, একটি পাথ নির্দিষ্ট করতে ref(path) কল করুন এবং ঐচ্ছিকভাবে instance('INSTANCE_NAME') সহ একটি Realtime Database উদাহরণ নির্দিষ্ট করুন। আপনি যদি একটি উদাহরণ নির্দিষ্ট না করেন, ফায়ারবেস প্রকল্পের জন্য ফাংশনটি ডিফল্ট Realtime Database ইনস্ট্যান্সে স্থাপন করে উদাহরণস্বরূপ:

  • ডিফল্ট Realtime Database উদাহরণ: functions.database.ref('/foo/bar')
  • "my-app-db-2" নামের উদাহরণ: functions.database.instance('my-app-db-2').ref('/foo/bar')

এই পদ্ধতিগুলি আপনার ফাংশনকে Realtime Database ইনস্ট্যান্সের মধ্যে একটি নির্দিষ্ট পথে লেখাগুলি পরিচালনা করতে নির্দেশ করে। পাথ স্পেসিফিকেশন সব লেখার সাথে মেলে যা একটি পাথকে স্পর্শ করে, এর নিচে যেকোনও লেখা সহ। আপনি যদি /foo/bar হিসাবে আপনার ফাংশনের জন্য পাথ সেট করেন তবে এটি এই উভয় অবস্থানের ইভেন্টের সাথে মিলে যায়:

 /foo/bar
 /foo/bar/baz/really/deep/path

উভয় ক্ষেত্রেই, Firebase ব্যাখ্যা করে যে ইভেন্টটি /foo/bar এ ঘটে এবং ইভেন্ট ডেটা /foo/bar এ পুরানো এবং নতুন ডেটা অন্তর্ভুক্ত করে। ইভেন্ট ডেটা বড় হলে, আপনার ডাটাবেসের রুটের কাছে একটি একক ফাংশনের পরিবর্তে গভীর পাথে একাধিক ফাংশন ব্যবহার করার কথা বিবেচনা করুন। সেরা পারফরম্যান্সের জন্য, শুধুমাত্র সম্ভাব্য গভীরতম স্তরে ডেটার অনুরোধ করুন৷

আপনি কোঁকড়া বন্ধনী দিয়ে ঘিরে রেখে ওয়াইল্ডকার্ড হিসাবে একটি পাথ উপাদান নির্দিষ্ট করতে পারেন; ref('foo/{bar}') /foo এর যেকোনো শিশুর সাথে মেলে। এই ওয়াইল্ডকার্ড পাথ উপাদানগুলির মান আপনার ফাংশনের EventContext.params অবজেক্টের মধ্যে উপলব্ধ। এই উদাহরণে, মানটি context.params.bar হিসাবে উপলব্ধ।

ওয়াইল্ডকার্ড সহ পাথগুলি একক লেখা থেকে একাধিক ইভেন্টের সাথে মেলে। একটি সন্নিবেশ

{
  "foo": {
    "hello": "world",
    "firebase": "functions"
  }
}

পাথ "/foo/{bar}" সাথে দুবার মেলে: একবার "hello": "world" এবং আবার "firebase": "functions" এর সাথে।

ইভেন্ট ডেটা পরিচালনা করুন

একটি Realtime Database ইভেন্ট পরিচালনা করার সময়, ডেটা অবজেক্টটি একটি DataSnapshotonWrite বা onUpdate ইভেন্টগুলির জন্য, প্রথম প্যারামিটার হল একটি Change বস্তু যাতে দুটি স্ন্যাপশট থাকে যা ট্রিগারিং ইভেন্টের আগে এবং পরে ডেটার অবস্থার প্রতিনিধিত্ব করে। onCreate এবং onDelete ইভেন্টগুলির জন্য, যে ডেটা অবজেক্টটি ফেরত দেওয়া হয়েছে তা তৈরি করা বা মুছে ফেলা ডেটার একটি স্ন্যাপশট।

এই উদাহরণে, ফাংশনটি নির্দিষ্ট পথের জন্য স্ন্যাপশট পুনরুদ্ধার করে, সেই অবস্থানের স্ট্রিংটিকে বড় হাতের অক্ষরে রূপান্তর করে এবং সেই পরিবর্তিত স্ট্রিংটিকে ডাটাবেসে লিখে:

// Listens for new messages added to /messages/:pushId/original and creates an
// uppercase version of the message to /messages/:pushId/uppercase
exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onCreate((snapshot, context) => {
      // Grab the current value of what was written to the Realtime Database.
      const original = snapshot.val();
      functions.logger.log('Uppercasing', context.params.pushId, original);
      const uppercase = original.toUpperCase();
      // You must return a Promise when performing asynchronous tasks inside a Functions such as
      // writing to the Firebase Realtime Database.
      // Setting an "uppercase" sibling in the Realtime Database returns a Promise.
      return snapshot.ref.parent.child('uppercase').set(uppercase);
    });

ব্যবহারকারীর প্রমাণীকরণ তথ্য অ্যাক্সেস করা হচ্ছে

EventContext.auth এবং EventContext.authType থেকে, আপনি একটি ফাংশন ট্রিগারকারী ব্যবহারকারীর জন্য অনুমতি সহ ব্যবহারকারীর তথ্য অ্যাক্সেস করতে পারেন। এটি সুরক্ষা বিধি প্রয়োগের জন্য দরকারী হতে পারে, আপনার ফাংশনকে ব্যবহারকারীর অনুমতির স্তরের উপর ভিত্তি করে বিভিন্ন ক্রিয়াকলাপ সম্পূর্ণ করার অনুমতি দেয়:

const functions = require('firebase-functions/v1');
const admin = require('firebase-admin');

exports.simpleDbFunction = functions.database.ref('/path')
    .onCreate((snap, context) => {
      if (context.authType === 'ADMIN') {
        // do something
      } else if (context.authType === 'USER') {
        console.log(snap.val(), 'written by', context.auth.uid);
      }
    });

এছাড়াও, আপনি একজন ব্যবহারকারীকে "ছদ্মবেশী" করার জন্য ব্যবহারকারীর প্রমাণীকরণ তথ্যের সুবিধা নিতে পারেন এবং ব্যবহারকারীর পক্ষে লেখার ক্রিয়াকলাপ সম্পাদন করতে পারেন। কনকারেন্সি সমস্যা রোধ করার জন্য নীচে দেখানো অ্যাপের উদাহরণটি মুছে ফেলার বিষয়টি নিশ্চিত করুন:

exports.impersonateMakeUpperCase = functions.database.ref('/messages/{pushId}/original')
    .onCreate((snap, context) => {
      const appOptions = JSON.parse(process.env.FIREBASE_CONFIG);
      appOptions.databaseAuthVariableOverride = context.auth;
      const app = admin.initializeApp(appOptions, 'app');
      const uppercase = snap.val().toUpperCase();
      const ref = snap.ref.parent.child('uppercase');

      const deleteApp = () => app.delete().catch(() => null);

      return app.database().ref(ref).set(uppercase).then(res => {
        // Deleting the app is necessary for preventing concurrency leaks
        return deleteApp().then(() => res);
      }).catch(err => {
        return deleteApp().then(() => Promise.reject(err));
      });
    });

আগের মান পড়া

Change অবজেক্টের একটি before প্রোপার্টি রয়েছে যা আপনাকে ইভেন্টের আগে Realtime Database কী সংরক্ষিত হয়েছিল তা পরিদর্শন করতে দেয়। before সম্পত্তি একটি DataSnapshot প্রদান করে যেখানে সমস্ত পদ্ধতি (উদাহরণস্বরূপ, val() এবং exists() ) পূর্ববর্তী মান উল্লেখ করে। আপনি মূল DataSnapshot ব্যবহার করে বা after প্রপার্টি পড়ে নতুন মানটি আবার পড়তে পারেন। যেকোন Change এই বৈশিষ্ট্যটি হল আরেকটি DataSnapshot যা ঘটনা ঘটার পর ডেটার অবস্থার প্রতিনিধিত্ব করে।

উদাহরণস্বরূপ, before সম্পত্তিটি নিশ্চিত করতে ব্যবহার করা যেতে পারে যে ফাংশনটি প্রথমবার তৈরি করার সময় কেবলমাত্র টেক্সট বড় হাতের হয়:

exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onWrite((change, context) => {
      // Only edit data when it is first created.
      if (change.before.exists()) {
        return null;
      }
      // Exit when the data is deleted.
      if (!change.after.exists()) {
        return null;
      }
      // Grab the current value of what was written to the Realtime Database.
      const original = change.after.val();
      console.log('Uppercasing', context.params.pushId, original);
      const uppercase = original.toUpperCase();
      // You must return a Promise when performing asynchronous tasks inside a Functions such as
      // writing to the Firebase Realtime Database.
      // Setting an "uppercase" sibling in the Realtime Database returns a Promise.
      return change.after.ref.parent.child('uppercase').set(uppercase);
    });