জাভাস্ক্রিপ্টে অফলাইন ক্ষমতা সক্রিয় করা হচ্ছে

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

উপস্থিতি পরিচালনা

রিয়েলটাইম অ্যাপ্লিকেশনগুলিতে ক্লায়েন্টরা কখন সংযোগ স্থাপন করে এবং সংযোগ বিচ্ছিন্ন করে তা শনাক্ত করা প্রায়শই দরকারি হয়। উদাহরণস্বরূপ, কোনো ব্যবহারকারীর ক্লায়েন্ট সংযোগ বিচ্ছিন্ন হলে আপনি তাকে 'অফলাইন' হিসেবে চিহ্নিত করতে চাইতে পারেন।

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

onDisconnect প্রিমিটিভ ব্যবহার করে সংযোগ বিচ্ছিন্ন হওয়ার পর ডেটা লেখার একটি সহজ উদাহরণ নিচে দেওয়া হলো:

Web

import { getDatabase, ref, onDisconnect } from "firebase/database";

const db = getDatabase();
const presenceRef = ref(db, "disconnectmessage");
// Write a string when this client loses connection
onDisconnect(presenceRef).set("I disconnected!");

Web

var presenceRef = firebase.database().ref("disconnectmessage");
// Write a string when this client loses connection
presenceRef.onDisconnect().set("I disconnected!");

অনডিসকানেক্ট কীভাবে কাজ করে

যখন আপনি একটি onDisconnect() অপারেশন স্থাপন করেন, তখন অপারেশনটি Firebase Realtime Database সার্ভারে থাকে। সার্ভার নিরাপত্তা পরীক্ষা করে নিশ্চিত করে যে ব্যবহারকারী অনুরোধ করা রাইট ইভেন্টটি সম্পাদন করতে পারবে কিনা, এবং যদি তা অবৈধ হয় তবে আপনার অ্যাপকে জানিয়ে দেয়। এরপর সার্ভার সংযোগটি পর্যবেক্ষণ করে। যদি কোনো সময়ে সংযোগের সময়সীমা শেষ হয়ে যায়, অথবা Realtime Database ক্লায়েন্ট দ্বারা সক্রিয়ভাবে বন্ধ করা হয়, তবে সার্ভার দ্বিতীয়বার নিরাপত্তা পরীক্ষা করে (অপারেশনটি এখনও বৈধ কিনা তা নিশ্চিত করার জন্য) এবং তারপর ইভেন্টটি আহ্বান করে।

আপনার অ্যাপ রাইট অপারেশনে কলব্যাকটি ব্যবহার করে নিশ্চিত করতে পারে যে onDisconnect সঠিকভাবে সংযুক্ত হয়েছে:

Web

onDisconnect(presenceRef).remove().catch((err) => {
  if (err) {
    console.error("could not establish onDisconnect event", err);
  }
});

Web

presenceRef.onDisconnect().remove((err) => {
  if (err) {
    console.error("could not establish onDisconnect event", err);
  }
});

.cancel() কল করেও একটি onDisconnect ইভেন্ট বাতিল করা যায়:

Web

const onDisconnectRef = onDisconnect(presenceRef);
onDisconnectRef.set("I disconnected");
// some time later when we change our minds
onDisconnectRef.cancel();

Web

var onDisconnectRef = presenceRef.onDisconnect();
onDisconnectRef.set("I disconnected");
// some time later when we change our minds
onDisconnectRef.cancel();

সংযোগের অবস্থা সনাক্তকরণ

উপস্থিতি-সম্পর্কিত অনেক বৈশিষ্ট্যের জন্য, আপনার অ্যাপের অনলাইন বা অফলাইন অবস্থা জানাটা দরকারি। Firebase Realtime Database /.info/connected এ একটি বিশেষ স্থান প্রদান করে, যা প্রতিবার Firebase Realtime Database ক্লায়েন্টের সংযোগের অবস্থা পরিবর্তিত হলে আপডেট করা হয়। এখানে একটি উদাহরণ দেওয়া হলো:

Web

import { getDatabase, ref, onValue } from "firebase/database";

const db = getDatabase();
const connectedRef = ref(db, ".info/connected");
onValue(connectedRef, (snap) => {
  if (snap.val() === true) {
    console.log("connected");
  } else {
    console.log("not connected");
  }
});

Web

var connectedRef = firebase.database().ref(".info/connected");
connectedRef.on("value", (snap) => {
  if (snap.val() === true) {
    console.log("connected");
  } else {
    console.log("not connected");
  }
});

/.info/connected একটি বুলিয়ান মান, যা Realtime Database ক্লায়েন্টগুলোর মধ্যে সিঙ্ক্রোনাইজড হয় না, কারণ এর মান ক্লায়েন্টের অবস্থার উপর নির্ভরশীল। অন্য কথায়, যদি একটি ক্লায়েন্ট /.info/connected false হিসেবে পড়ে, তবে এর কোনো নিশ্চয়তা নেই যে অন্য একটি ক্লায়েন্টও false-ই পড়বে।

লেটেন্সি পরিচালনা

সার্ভার টাইমস্ট্যাম্প

Firebase Realtime Database সার্ভারগুলো সার্ভারে তৈরি হওয়া টাইমস্ট্যাম্পকে ডেটা হিসেবে সন্নিবেশ করার একটি ব্যবস্থা প্রদান করে। এই বৈশিষ্ট্যটি, onDisconnect সাথে মিলিত হয়ে, একটি Realtime Database ক্লায়েন্ট কখন সংযোগ বিচ্ছিন্ন করেছে সেই সময়টি নির্ভরযোগ্যভাবে লিখে রাখার একটি সহজ উপায় প্রদান করে।

Web

import { getDatabase, ref, onDisconnect, serverTimestamp } from "firebase/database";

const db = getDatabase();
const userLastOnlineRef = ref(db, "users/joe/lastOnline");
onDisconnect(userLastOnlineRef).set(serverTimestamp());

Web

var userLastOnlineRef = firebase.database().ref("users/joe/lastOnline");
userLastOnlineRef.onDisconnect().set(firebase.database.ServerValue.TIMESTAMP);

ঘড়ির তির্যক

যদিও firebase.database.ServerValue.TIMESTAMP অনেক বেশি নির্ভুল এবং বেশিরভাগ রিড/রাইট অপারেশনের জন্য পছন্দনীয়, Firebase Realtime Database -এর সার্ভারগুলোর সাপেক্ষে ক্লায়েন্টের ঘড়ির সময়ের অসামঞ্জস্যতা অনুমান করার জন্য এটি মাঝে মাঝে কাজে আসতে পারে। সার্ভারের সময় অনুমান করার জন্য Firebase Realtime Database ক্লায়েন্টরা স্থানীয় রিপোর্ট করা সময়ের (মিলিসেকেন্ডে ইপক টাইম) সাথে যে মানটি মিলিসেকেন্ডে যোগ করে, তা পাওয়ার জন্য আপনি /.info/serverTimeOffset লোকেশনে একটি কলব্যাক সংযুক্ত করতে পারেন। মনে রাখবেন যে এই অফসেটের নির্ভুলতা নেটওয়ার্কিং ল্যাটেন্সি দ্বারা প্রভাবিত হতে পারে, এবং তাই এটি মূলত ঘড়ির সময়ের বড় (> ১ সেকেন্ড) অমিল খুঁজে বের করার জন্য উপযোগী।

Web

import { getDatabase, ref, onValue } from "firebase/database";

const db = getDatabase();
const offsetRef = ref(db, ".info/serverTimeOffset");
onValue(offsetRef, (snap) => {
  const offset = snap.val();
  const estimatedServerTimeMs = new Date().getTime() + offset;
});

Web

var offsetRef = firebase.database().ref(".info/serverTimeOffset");
offsetRef.on("value", (snap) => {
  var offset = snap.val();
  var estimatedServerTimeMs = new Date().getTime() + offset;
});

নমুনা উপস্থিতি অ্যাপ

সংযোগ বিচ্ছিন্ন করার কার্যক্রম, সংযোগের অবস্থা পর্যবেক্ষণ এবং সার্ভার টাইমস্ট্যাম্পের সমন্বয়ে আপনি একটি ব্যবহারকারীর উপস্থিতি সিস্টেম তৈরি করতে পারেন। এই সিস্টেমে, প্রতিটি ব্যবহারকারী একটি Realtime Database ক্লায়েন্ট অনলাইন আছে কি না তা নির্দেশ করার জন্য একটি ডেটাবেস অবস্থানে ডেটা সংরক্ষণ করে। ক্লায়েন্টরা অনলাইন হলে এই অবস্থানটিকে 'ট্রু' (true) এবং সংযোগ বিচ্ছিন্ন হলে একটি টাইমস্ট্যাম্প সেট করে। এই টাইমস্ট্যাম্পটি নির্দেশ করে যে প্রদত্ত ব্যবহারকারী শেষবার কখন অনলাইন ছিলেন।

মনে রাখবেন, কোনো ব্যবহারকারীকে অনলাইন হিসেবে চিহ্নিত করার আগেই আপনার অ্যাপকে সংযোগ বিচ্ছিন্ন করার অপারেশনগুলো কিউতে রাখতে হবে, যাতে সার্ভারে উভয় কমান্ড পাঠানোর আগেই ক্লায়েন্টের নেটওয়ার্ক সংযোগ বিচ্ছিন্ন হয়ে গেলে কোনো রেস কন্ডিশন তৈরি না হয়।

এখানে একটি সহজ ব্যবহারকারী উপস্থিতি সিস্টেম দেওয়া হলো:

Web

import { getDatabase, ref, onValue, push, onDisconnect, set, serverTimestamp } from "firebase/database";

// Since I can connect from multiple devices or browser tabs, we store each connection instance separately
// any time that connectionsRef's value is null (i.e. has no children) I am offline
const db = getDatabase();
const myConnectionsRef = ref(db, 'users/joe/connections');

// stores the timestamp of my last disconnect (the last time I was seen online)
const lastOnlineRef = ref(db, 'users/joe/lastOnline');

const connectedRef = ref(db, '.info/connected');
onValue(connectedRef, (snap) => {
  if (snap.val() === true) {
    // We're connected (or reconnected)! Do anything here that should happen only if online (or on reconnect)
    const con = push(myConnectionsRef);

    // When I disconnect, remove this device
    onDisconnect(con).remove();

    // Add this device to my connections list
    // this value could contain info about the device or a timestamp too
    set(con, true);

    // When I disconnect, update the last time I was seen online
    onDisconnect(lastOnlineRef).set(serverTimestamp());
  }
});

Web

// Since I can connect from multiple devices or browser tabs, we store each connection instance separately
// any time that connectionsRef's value is null (i.e. has no children) I am offline
var myConnectionsRef = firebase.database().ref('users/joe/connections');

// stores the timestamp of my last disconnect (the last time I was seen online)
var lastOnlineRef = firebase.database().ref('users/joe/lastOnline');

var connectedRef = firebase.database().ref('.info/connected');
connectedRef.on('value', (snap) => {
  if (snap.val() === true) {
    // We're connected (or reconnected)! Do anything here that should happen only if online (or on reconnect)
    var con = myConnectionsRef.push();

    // When I disconnect, remove this device
    con.onDisconnect().remove();

    // Add this device to my connections list
    // this value could contain info about the device or a timestamp too
    con.set(true);

    // When I disconnect, update the last time I was seen online
    lastOnlineRef.onDisconnect().set(firebase.database.ServerValue.TIMESTAMP);
  }
});