If you use FCM APIs to build send requests programmatically, you may find that, over time, you are wasting resources by sending messages to inactive devices with stale registrations. This situation can affect the message delivery data reported in the Firebase console or data exported to BigQuery , showing up as a dramatic (but not actually valid) drop in delivery rates. This guide discusses some measures you can take to help ensure efficient message targeting and valid delivery reporting.
পুরনো এবং মেয়াদোত্তীর্ণ নিবন্ধন
স্টেল রেজিস্ট্রেশনগুলো সেইসব নিষ্ক্রিয় ডিভাইসের সাথে সম্পর্কিত, যেগুলো এক মাসেরও বেশি সময় ধরে FCM এর সাথে সংযুক্ত হয়নি। সময় যত গড়ায়, ডিভাইসটির পুনরায় FCM এর সাথে সংযুক্ত হওয়ার সম্ভাবনা ততই কমে আসে। এই স্টেল রেজিস্ট্রেশনগুলোর জন্য পাঠানো মেসেজ এবং টপিক ফ্যানআউটগুলো কখনোই ডেলিভার হওয়ার সম্ভাবনা থাকে না।
বিভিন্ন কারণে একটি রেজিস্ট্রেশন অকার্যকর হয়ে যেতে পারে। উদাহরণস্বরূপ, রেজিস্ট্রেশনটি যে ডিভাইসের সাথে যুক্ত, সেটি হারিয়ে যেতে পারে, নষ্ট হয়ে যেতে পারে, অথবা সংরক্ষণে রেখে দেওয়ার পর তা ভুলে যাওয়া হতে পারে।
For Android, when a registration has been inactive for 270 days, FCM considers it expired and garbage collects it. Once a registration is expired, FCM marks it as invalid and rejects sends to it. Note that Firebase Installation IDs (FIDs) themselves are managed by the Firebase Installations service (FIS), not by FCM. In the rare case that a device connects again and the app is opened after its registration has been garbage collected, the client app registers again with FCM using the FID retrieved from FIS. Note that the FID may change; see Manage Firebase Installations for details on when FIDs are reissued.
iOS-এর মতো অন্যান্য প্ল্যাটফর্মের জন্য, FCM অন্তর্নিহিত পুশ সার্ভিসের (যেমন, APNs) উপর নির্ভর করে, যেটিতে একই রকম ২৭০-দিনের নিষ্ক্রিয়তা-ভিত্তিক মেয়াদ শেষ হওয়ার নিয়ম নেই। আমরা আপনাকে সক্রিয়ভাবে রেজিস্ট্রেশনের সতেজতা বজায় রাখতে এবং মেয়াদোত্তীর্ণ রেজিস্ট্রেশনগুলি মুছে ফেলার পরামর্শ দিই।
মৌলিক সর্বোত্তম অনুশীলন
যেসব অ্যাপ প্রোগ্রাম্যাটিকভাবে প্রেরণের অনুরোধ তৈরি করতে FCM API ব্যবহার করে, সেগুলোর ক্ষেত্রে কিছু মৌলিক নিয়ম মেনে চলা উচিত। প্রধান সেরা নিয়মগুলো হলো:
- FCM থেকে Firebase Installation ID (FID) সংগ্রহ করুন এবং আপনার অ্যাপ সার্ভারে সেগুলো সংরক্ষণ করুন। সার্ভারের একটি গুরুত্বপূর্ণ ভূমিকা হলো প্রতিটি ক্লায়েন্টের নিবন্ধিত FID-এর হিসাব রাখা এবং সক্রিয় FID-গুলোর একটি হালনাগাদ তালিকা বজায় রাখা। আমরা আপনার ডেটাবেসে একটি রেজিস্ট্রেশন টাইমস্ট্যাম্প যুক্ত করার এবং যখনই কোনো রেজিস্ট্রেশন আপলোড করা হবে, তখন তা হালনাগাদ করার জন্য দৃঢ়ভাবে সুপারিশ করছি।
- রেজিস্ট্রেশনের সতেজতা বজায় রাখুন এবং মেয়াদোত্তীর্ণ রেজিস্ট্রেশনগুলো মুছে ফেলুন। যে রেজিস্ট্রেশনগুলোকে FCM আর বৈধ বলে মনে করে না, সেগুলো মুছে ফেলার পাশাপাশি, রেজিস্ট্রেশনগুলো মেয়াদোত্তীর্ণ হয়ে যাওয়ার অন্যান্য লক্ষণগুলোও আপনি পর্যবেক্ষণ করতে পারেন এবং আগে থেকেই সেগুলো মুছে ফেলতে পারেন। এই কাজটি করার জন্য আপনার কিছু বিকল্প নিয়ে এই নির্দেশিকায় আলোচনা করা হয়েছে।
ফায়ারবেস ইনস্টলেশন আইডিগুলি পুনরুদ্ধার এবং সংরক্ষণ করুন
আপনার অ্যাপটি প্রথমবার চালু করার সময়, FCM SDK অ্যাপ ইনস্ট্যান্সটিকে FCM সাথে রেজিস্টার করে এবং একটি Firebase Installation ID (FID) ফেরত দেয়। এই আইডেন্টিফায়ারটিই আপনাকে API থেকে পাঠানো টার্গেটেড সেন্ড রিকোয়েস্টে অন্তর্ভুক্ত করতে হবে, অথবা টপিক সাবস্ক্রিপশনের জন্য ব্যবহার করতে হবে।
যখনই FID আপলোড করা হবে, আমরা দৃঢ়ভাবে সুপারিশ করছি যে আপনি এটি একটি টাইমস্ট্যাম্প সহ আপনার অ্যাপ সার্ভারে সংরক্ষণ করুন। প্রতিটি আপলোড অনুরোধে টাইমস্ট্যাম্প আপডেট করার মাধ্যমে, আপনার সার্ভার জানতে পারে কখন অ্যাপ ইনস্ট্যান্সটি শেষবার খোলা হয়েছিল এবং FCM ব্যাকএন্ডের সাথে সফলভাবে সিঙ্ক্রোনাইজ হয়েছিল।
স্বয়ংক্রিয় প্রারম্ভিকীকরণ চালু বা বন্ধ (এমনকি অসমর্থিত) আছে কিনা তার উপর নির্ভর করে, আপনাকে নিম্নলিখিতভাবে নিবন্ধন এবং আপডেটগুলি পরিচালনা করতে হবে:
- (সুপারিশকৃত) যখন অটো-ইনিশিয়ালাইজেশন সক্রিয় থাকে: SDK স্বয়ংক্রিয়ভাবে রেজিস্ট্রেশনকে সতেজ রাখে এবং পরিবর্তনগুলি পর্যবেক্ষণ করে। অ্যাপ চালু হওয়ার সময় নিয়মিত সিঙ্কের জন্য, এবং FID পরিবর্তনের সময়
onRegistered()কলব্যাকটি নিয়মিতভাবে কল করা হয়। আপনার সার্ভারে FID আপলোড করতে এবং বর্তমান টাইমস্ট্যাম্প সংরক্ষণ করতে কেবল এই কলব্যাকটি ইমপ্লিমেন্ট করুন। - When auto-initialization is disabled: The
onRegistered()callback won't be automatically invoked at start. To track registrations and keep them fresh, callregister()on app startup; for example, on Android, in the main activity'sonCreate(). A successful call triggers the FCM registration process using the FID and delivers it to youronRegistered()callback, allowing your app to upload the FID and update the timestamp on your server.
উদাহরণ: Cloud Firestore FID এবং টাইমস্ট্যাম্প সংরক্ষণ করুন।
উদাহরণস্বরূপ, আপনি Cloud Firestore ব্যবহার করে fcmRegistrations ' নামক একটি কালেকশনে FID-গুলো সংরক্ষণ করতে পারেন। কালেকশনটির প্রতিটি ডকুমেন্ট আইডি একটি ইউজার আইডির সাথে সম্পর্কিত, এবং ডকুমেন্টটিতে বর্তমান FID ও তার সর্বশেষ আপডেটের টাইমস্ট্যাম্প সংরক্ষিত থাকে। এই কোটলিন উদাহরণে দেখানো অনুযায়ী set ফাংশনটি ব্যবহার করুন:
private fun sendRegistrationToServer(installationId: String?) {
// If you're running your own server, call API to send registration details and today's date for the user
// Example shown uses Firestore
// Add FID and timestamp to Firestore for this user
val deviceFid = hashMapOf(
"installationId" to installationId,
"timestamp" to FieldValue.serverTimestamp(),
)
// Get user ID from Firebase Auth or your own server
Firebase.firestore.collection("fcmRegistrations").document("myuserid")
.set(deviceFid)
}
যখনই একটি Firebase Installation ID সফলভাবে রেজিস্টার বা আপডেট করা হয়, তখন onRegistered() কলব্যাকটি চালু হয়। FID আপলোড করতে এবং টাইমস্ট্যাম্প আপডেট করতে আপনার এই কলব্যাকটি ইমপ্লিমেন্ট করা উচিত:
override fun onRegistered(installationId: String) {
Log.d(TAG, "Registered installation ID: $installationId")
// Send the Firebase Installation ID (FID) to your app server. Your app
// server should save the FID and update the timestamp upon receipt.
sendRegistrationToServer(installationId)
}
যেসব ক্ষেত্রে স্বয়ংক্রিয় সূচনা (auto-initialization) নিষ্ক্রিয় করা থাকে, সেখানে অ্যাপ চালু হওয়ার সময় (যেমন, onCreate() ফাংশনে) register() কল করুন, যাতে onRegistered() মাধ্যমে রেজিস্ট্রেশন প্রক্রিয়া এবং FID ডেলিভারি শুরু হয়।
// Trigger manual registration if auto-initialization is turned off.
FirebaseMessaging.getInstance().register()
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
// The registration callback onRegistered() will be invoked with the current FID.
} else {
Log.w(TAG, "Failed to register with Firebase Cloud Messaging", task.exception)
}
}
নিবন্ধনের সতেজতা বজায় রাখুন এবং মেয়াদোত্তীর্ণ নিবন্ধনগুলি মুছে ফেলুন।
Determining whether a registration is fresh or stale is not always straightforward. To cover all cases, you should adopt a threshold for when you consider registrations stale. By default, FCM considers a registration to be stale if its app instance hasn't connected for a month. Any registration older than one month is likely to be an inactive device; an active device would have otherwise refreshed its registration.
আপনার ব্যবহারের ধরনের ওপর নির্ভর করে এক মাস খুব কম বা খুব বেশি হতে পারে, তাই আপনার জন্য উপযুক্ত মানদণ্ড নির্ধারণ করার দায়িত্ব আপনারই।
FCM ব্যাকএন্ড থেকে অবৈধ প্রতিক্রিয়া সনাক্ত করুন
FCM থেকে আসা অবৈধ প্রতিক্রিয়া শনাক্ত করুন এবং আপনার সিস্টেম থেকে অবৈধ বা মেয়াদোত্তীর্ণ বলে পরিচিত রেজিস্ট্রেশনগুলো মুছে দিয়ে তার জবাব দিন। HTTP v1 API-এর ক্ষেত্রে, এই ত্রুটির বার্তাগুলো নির্দেশ করতে পারে যে আপনার পাঠানো অনুরোধটি অবৈধ বা মেয়াদোত্তীর্ণ রেজিস্ট্রেশনগুলোকে লক্ষ্য করে করা হয়েছিল:
-
UNREGISTERED(HTTP 404) -
INVALID_ARGUMENT(HTTP 400)
যদি আপনি নিশ্চিত হন যে মেসেজ পেলোডটি বৈধ এবং কোনো নির্দিষ্ট রেজিস্ট্রেশনের জন্য এই প্রতিক্রিয়াগুলির মধ্যে কোনো একটি পান, তাহলে এই রেজিস্ট্রেশনের রেকর্ডটি মুছে ফেলা নিরাপদ, কারণ এটি আর কখনও বৈধ হবে না। উদাহরণস্বরূপ, Cloud Firestore থেকে অবৈধ রেজিস্ট্রেশনগুলি মুছে ফেলার জন্য, আপনি নিম্নলিখিতের মতো একটি ফাংশন ডেপ্লয় এবং রান করতে পারেন:
// Firebase Installation ID comes from the client FCM SDKs
const firebaseInstallationId = 'YOUR_FIREBASE_INSTALLATION_ID';
const message = {
data: {
// Information you want to send inside of notification
},
fid: firebaseInstallationId
};
// Send message to device with provided Firebase Installation ID
getMessaging().send(message)
.then((response) => {
// Response is a message ID string.
})
.catch((error) => {
// Delete registration for user if error code is UNREGISTERED or INVALID_ARGUMENT.
if (error.errorCode == "messaging/registration-token-not-registered") {
// If you're running your own server, call API to delete the registration for the user
// Example shown uses Firestore
// Get user ID from Firebase Auth or your own server
Firebase.firestore.collection("fcmRegistrations").document(user.uid).delete()
}
});
যদি কোনো অ্যান্ড্রয়েড ডিভাইসের রেজিস্ট্রেশন ২৭০ দিন নিষ্ক্রিয় থাকার পর মেয়াদোত্তীর্ণ হয়ে যায়, অথবা যদি কোনো ক্লায়েন্ট স্পষ্টভাবে রেজিস্ট্রেশন বাতিল করে, তাহলে FCM একটি অবৈধ প্রতিক্রিয়া ফেরত দেয়। আপনার নিজস্ব সংজ্ঞা অনুযায়ী মেয়াদোত্তীর্ণ রেজিস্ট্রেশন আরও নির্ভুলভাবে ট্র্যাক করার প্রয়োজন হলে, আপনি সক্রিয়ভাবে মেয়াদোত্তীর্ণ রেজিস্ট্রেশনগুলো মুছে ফেলতে পারেন।
নিয়মিতভাবে নিবন্ধনগুলো হালনাগাদ করুন।
Regardless of whether your registrations are based on FIDs or legacy registration tokens, your server should always update the registration timestamp in your database on every upload request. This timestamp acts as a signal for the app installation, letting the client has successfully opened the app and synced with the FCM backend. Depending on the APIs you are using, implement the appropriate strategy:
ফায়ারবেস ইনস্টলেশন আইডি এপিআই (প্রস্তাবিত)
যেসব ক্লায়েন্ট অ্যাপ FID API ব্যবহার করে, তাদের রেজিস্ট্রেশন পুনরুদ্ধার বা রিফ্রেশ করার জন্য ক্লায়েন্ট অ্যাপে পর্যায়ক্রমিক ব্যাকগ্রাউন্ড জব শিডিউল করার প্রয়োজন নেই । SDK স্বয়ংক্রিয়ভাবে অটো-ইনিশিয়ালাইজেশনের অধীনে রিফ্রেশের কাজটি করে এবং অ্যাপ চালু হওয়ার সময় নিয়মিত সিঙ্কের সময় আপনার onRegistered() কলব্যাকে নিয়মিতভাবে সঠিক বর্তমান FID সরবরাহ করে।
আপনার সার্ভার আপডেট রাখতে, "ফায়ারবেস ইনস্টলেশন আইডি পুনরুদ্ধার এবং সংরক্ষণ করুন" অংশে বিস্তারিতভাবে বর্ণিত স্টার্টআপ আপলোড কৌশলগুলি প্রয়োগ করুন:
- স্বয়ংক্রিয় প্রারম্ভিকীকরণ সক্রিয় করা হয়েছে: অ্যাপ চালু হওয়ার সময় নিয়মিত সিঙ্কের ক্ষেত্রে SDK স্বয়ংক্রিয়ভাবে আপনার সার্ভারে সর্বশেষ FID পাঠানো নিশ্চিত করে।
- স্বয়ংক্রিয় সূচনা নিষ্ক্রিয় বা সমর্থিত নয়: রেজিস্ট্রেশন প্রক্রিয়াটি জোরপূর্বক শুরু করতে এবং আপনার
onRegistered()কলব্যাকে FID ডেলিভারি চালু করতে, অ্যাপ চালু হওয়ার সময়register()কল করুন (উদাহরণস্বরূপ, অ্যান্ড্রয়েডে, প্রধান অ্যাক্টিভিটিরonCreate()ফাংশনে)।
এই কৌশলগুলি নিশ্চিত করে যে আপনার সার্ভারে সর্বদা সর্বশেষ সক্রিয় FID থাকবে এবং এটি ব্যর্থ আপলোড থেকে স্বয়ংক্রিয়ভাবে পুনরুদ্ধার করতে পারবে, যা অ্যাপ্লিকেশনটিকে অত্যন্ত স্থিতিস্থাপক করে তোলে।
বাতিল করা রেজিস্ট্রেশন টোকেন এপিআই
আপনি যদি লিগ্যাসি রেজিস্ট্রেশন টোকেন ব্যবহার করেন, তাহলে ক্লায়েন্ট SDK নিয়মিত সিঙ্কের সময় স্বয়ংক্রিয়ভাবে রিফ্রেশ পরিচালনা করে না। তাই, আমরা আপনাকে পর্যায়ক্রমে আপনার সার্ভারে সমস্ত রেজিস্ট্রেশন টোকেন পুনরুদ্ধার এবং আপডেট করার পরামর্শ দিই। এর জন্য আপনাকে যা করতে হবে তা হলো:
- আপনার ক্লায়েন্ট অ্যাপে উপযুক্ত এপিআই কল (যেমন অ্যাপল প্ল্যাটফর্মের জন্য
token(completion):অথবা অ্যান্ড্রয়েডের জন্যgetToken()) ব্যবহার করে বর্তমান টোকেনটি পুনরুদ্ধার করার জন্য অ্যাপ লজিক যোগ করুন এবং তারপর সংরক্ষণের জন্য বর্তমান টোকেনটি (একটি টাইমস্ট্যাম্প সহ) আপনার অ্যাপ সার্ভারে পাঠান। এটি একটি মাসিক কাজ হতে পারে যা সমস্ত ক্লায়েন্ট বা টোকেনকে অন্তর্ভুক্ত করার জন্য কনফিগার করা হয়েছে। - টোকেন পরিবর্তিত হয়েছে কি না, তা নির্বিশেষে নিয়মিত বিরতিতে টোকেনের টাইমস্ট্যাম্প আপডেট করার জন্য সার্ভার লজিক যোগ করুন।
WorkManager ব্যবহার করে লিগ্যাসি টোকেন আপডেট করার অ্যান্ড্রয়েড লজিকের উদাহরণের জন্য, Firebase ব্লগে ‘Managing Cloud Messaging Tokens’ দেখুন।
Whatever timing pattern you follow, make sure to update tokens periodically. An update frequency of once per month strikes a good balance between battery impact and detecting inactive registration tokens. By doing this refresh, you also ensure that any device which goes inactive will refresh its registration when it becomes active again. There is no benefit to doing the refresh more frequently than weekly.
অপ্রচলিত নিবন্ধনগুলি মুছে ফেলুন
কোনো ডিভাইসে মেসেজ পাঠানোর আগে, নিশ্চিত করুন যে ডিভাইসটির রেজিস্ট্রেশনের টাইমস্ট্যাম্পটি আপনার নির্ধারিত স্টেলনেস উইন্ডো পিরিয়ডের মধ্যে আছে। উদাহরণস্বরূপ, আপনি Cloud Functions for Firebase ব্যবহার করে একটি দৈনিক চেক চালাতে পারেন, যা নিশ্চিত করবে যে টাইমস্ট্যাম্পটি একটি নির্দিষ্ট স্টেলনেস উইন্ডো পিরিয়ডের মধ্যে আছে, যেমন const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30; এবং তারপর পুরোনো রেজিস্ট্রেশনগুলো মুছে ফেলতে পারেন।
exports.pruneRegistrations = functions.pubsub.schedule('every 24 hours').onRun(async (context) => {
// Get all documents where the timestamp exceeds is not within the past month
const staleRegistrationsResult = await admin.firestore().collection('fcmRegistrations')
.where("timestamp", "<", Date.now() - EXPIRATION_TIME)
.get();
// Delete devices with stale registrations
staleRegistrationsResult.forEach(function(doc) { doc.ref.delete(); });
});
টপিকগুলো থেকে মেয়াদোত্তীর্ণ রেজিস্ট্রেশনগুলো আনসাবস্ক্রাইব করুন।
আপনি যদি টপিক ব্যবহার করেন, তাহলে মেয়াদোত্তীর্ণ রেজিস্ট্রেশনগুলোকে তাদের সাবস্ক্রাইব করা টপিকগুলো থেকে আনসাবস্ক্রাইব করতে চাইতে পারেন। এর জন্য দুটি ধাপ অনুসরণ করতে হয়:
- যখনই ফায়ারবেস ইনস্টলেশন আইডি (FID) পরিবর্তিত হবে, আপনার অ্যাপের টপিকগুলোতে পুনরায় সাবস্ক্রাইব করা উচিত। এর ফলে, অ্যাপটি আবার সক্রিয় হলে সাবস্ক্রিপশনগুলো স্বয়ংক্রিয়ভাবে পুনরায় প্রদর্শিত হয়।
- যদি কোনো অ্যাপ ইনস্ট্যান্স এক মাস ধরে (বা আপনার নির্ধারিত নিষ্ক্রিয়তার সময়সীমা পর্যন্ত) নিষ্ক্রিয় থাকে, তাহলে আপনার উচিত ফায়ারবেস অ্যাডমিন এসডিকে ব্যবহার করে FCM ব্যাকএন্ড থেকে ফায়ারবেস ইনস্টলেশন আইডি ও টপিকের ম্যাপিং মুছে দিয়ে সেটিকে টপিকগুলো থেকে আনসাবস্ক্রাইব করা।
এই দুটি পদক্ষেপের সুবিধা হলো, আপনার ফ্যানআউটগুলো আরও দ্রুত সম্পন্ন হবে, কারণ ফ্যানআউট করার জন্য নিষ্ক্রিয় রেজিস্ট্রেশনের সংখ্যা কম থাকবে, এবং আপনার নিষ্ক্রিয় অ্যাপ ইনস্ট্যান্সগুলো পুনরায় সক্রিয় হলে স্বয়ংক্রিয়ভাবে আবার সাবস্ক্রাইব হয়ে যাবে।
ডেলিভারির সাফল্য পরিমাপ করুন
মেসেজ ডেলিভারির সবচেয়ে সঠিক চিত্র পেতে, শুধুমাত্র সক্রিয়ভাবে ব্যবহৃত অ্যাপ ইনস্ট্যান্সগুলিতেই মেসেজ পাঠানো সবচেয়ে ভালো। আপনি যদি নিয়মিতভাবে বিপুল সংখ্যক সাবস্ক্রাইবার আছে এমন টপিকে মেসেজ পাঠান, তবে এটি বিশেষভাবে গুরুত্বপূর্ণ; কারণ যদি সেই সাবস্ক্রাইবারদের একটি অংশ নিষ্ক্রিয় থাকে, তবে সময়ের সাথে সাথে আপনার ডেলিভারি পরিসংখ্যানের উপর এর প্রভাব উল্লেখযোগ্য হতে পারে।
কোনো অ্যাপ ইনস্ট্যান্সে মেসেজ পাঠানোর আগে, নিম্নলিখিত বিষয়গুলো বিবেচনা করুন:
- Google Analytics, BigQuery-তে সংগৃহীত ডেটা, বা অন্যান্য ট্র্যাকিং সংকেত কি নিবন্ধনটি সক্রিয় থাকার ইঙ্গিত দেয়?
- পূর্ববর্তী ডেলিভারির প্রচেষ্টাগুলো কি দীর্ঘ সময় ধরে ধারাবাহিকভাবে ব্যর্থ হয়েছে?
- গত এক মাসে আপনার সার্ভারগুলিতে ফায়ারবেস ইনস্টলেশন আইডি আপডেট করা হয়েছে কি?
- অ্যান্ড্রয়েড ডিভাইসগুলোর ক্ষেত্রে,
droppedDeviceInactiveএর কারণে FCM ডেটা API কি উচ্চ হারে বার্তা বিতরণে ব্যর্থতা রিপোর্ট করে?
ডেলিভারি সম্পর্কে আরও তথ্যের জন্য, ‘মেসেজ ডেলিভারি বোঝা’ দেখুন।