استنادًا إلى نوع التطبيق الذي تنشئه، قد يكون من المفيد رصد المستخدمين أو الأجهزة المتصلة بالإنترنت بشكل نشط، ويُعرف ذلك أيضًا باسم رصد "حالة التوفّر".
على سبيل المثال، إذا كنت بصدد إنشاء تطبيق مثل شبكة اجتماعية أو نشر مجموعة من أجهزة إنترنت الأشياء، يمكنك استخدام هذه المعلومات لعرض قائمة بالأصدقاء المتوفّرين على الإنترنت والمتاحين للدردشة، أو لترتيب أجهزة إنترنت الأشياء حسب "آخر ظهور".
لا يتيح Cloud Firestore إمكانية معرفة حالة المستخدمين بشكلٍ مباشر، ولكن يمكنك الاستفادة من منتجات Firebase الأخرى لإنشاء نظام لمعرفة حالة المستخدمين.
الحل: "وظائف السحابة الإلكترونية" مع قاعدة بيانات الوقت الفعلي
لربط Cloud Firestore بميزة "حالة التوفّر" الأصلية في قاعدة بيانات Firebase Realtime Database، استخدِم "وظائف Cloud".
استخدِم قاعدة بيانات الوقت الفعلي للإبلاغ عن حالة الاتصال، ثم استخدِم الوظائف السحابية لنقل البيانات إلى Cloud Firestore.
استخدام ميزة "التواجد" في قاعدة بيانات الوقت الفعلي
أولاً، ضع في اعتبارك طريقة عمل نظام الحضور التقليدي في قاعدة بيانات الوقت الفعلي.
الويب
// Fetch the current user's ID from Firebase Authentication. var uid = firebase.auth().currentUser.uid; // Create a reference to this user's specific status node. // This is where we will store data about being online/offline. var userStatusDatabaseRef = firebase.database().ref('/status/' + uid); // We'll create two constants which we will write to // the Realtime database when this device is offline // or online. var isOfflineForDatabase = { state: 'offline', last_changed: firebase.database.ServerValue.TIMESTAMP, }; var isOnlineForDatabase = { state: 'online', last_changed: firebase.database.ServerValue.TIMESTAMP, }; // Create a reference to the special '.info/connected' path in // Realtime Database. This path returns `true` when connected // and `false` when disconnected. firebase.database().ref('.info/connected').on('value', function(snapshot) { // If we're not currently connected, don't do anything. if (snapshot.val() == false) { return; }; // If we are currently connected, then use the 'onDisconnect()' // method to add a set which will only trigger once this // client has disconnected by closing the app, // losing internet, or any other means. userStatusDatabaseRef.onDisconnect().set(isOfflineForDatabase).then(function() { // The promise returned from .onDisconnect().set() will // resolve as soon as the server acknowledges the onDisconnect() // request, NOT once we've actually disconnected: // https://firebase.google.com/docs/reference/js/firebase.database.OnDisconnect // We can now safely set ourselves as 'online' knowing that the // server will mark us as offline once we lose connection. userStatusDatabaseRef.set(isOnlineForDatabase); }); });
هذا المثال هو نظام كامل لعرض حالة الاتصال في Realtime Database. ويتعامل مع حالات انقطاع الاتصال المتعددة والأعطال وما إلى ذلك.
جارٍ الاتصال بـ "Cloud Firestore"
لتنفيذ حلّ مشابه في Cloud Firestore، استخدِم رمز قاعدة بيانات الوقت الفعلي نفسه، ثم استخدِم Cloud Functions لإبقاء قاعدة بيانات الوقت الفعلي وCloud Firestore متزامنين.
إذا لم يسبق لك إجراء ذلك، أضِف قاعدة بيانات الوقت الفعلي إلى مشروعك وتضمين حلّ حالة الحضور أعلاه.
بعد ذلك، ستتم مزامنة حالة التوفّر مع Cloud Firestore من خلال الطرق التالية:
- محليًا، إلى ذاكرة التخزين المؤقت Cloud Firestore للجهاز غير المتصل بالإنترنت، لكي يعرف التطبيق أنّ الجهاز غير متصل بالإنترنت.
- على مستوى العالم، يتم استخدام Cloud Function لكي تعرف جميع الأجهزة الأخرى التي يمكنها الوصول إلى Cloud Firestore أنّ هذا الجهاز غير متصل بالإنترنت.
لا يمكن تشغيل الوظائف المقترَحة في هذا الدليل التوجيهي في تطبيق العميل، بل يجب تفعيلها في Cloud Functions for Firebase، وهي تتطلّب منطقًا من جهة الخادم من حزمة مدير SDK في Firebase. للحصول على إرشادات مفصّلة، يُرجى الاطّلاع على مستندات Cloud Functions.
جارٍ تعديل ذاكرة التخزين المؤقت المحلية الخاصة بـ "Cloud Firestore"
لنلقِ نظرة على التغييرات المطلوبة لحلّ المشكلة الأولى، وهي تعديل ذاكرة التخزين المؤقت المحلية في Cloud Firestore.
الويب
// ... var userStatusFirestoreRef = firebase.firestore().doc('/status/' + uid); // Firestore uses a different server timestamp value, so we'll // create two more constants for Firestore state. var isOfflineForFirestore = { state: 'offline', last_changed: firebase.firestore.FieldValue.serverTimestamp(), }; var isOnlineForFirestore = { state: 'online', last_changed: firebase.firestore.FieldValue.serverTimestamp(), }; firebase.database().ref('.info/connected').on('value', function(snapshot) { if (snapshot.val() == false) { // Instead of simply returning, we'll also set Firestore's state // to 'offline'. This ensures that our Firestore cache is aware // of the switch to 'offline.' userStatusFirestoreRef.set(isOfflineForFirestore); return; }; userStatusDatabaseRef.onDisconnect().set(isOfflineForDatabase).then(function() { userStatusDatabaseRef.set(isOnlineForDatabase); // We'll also add Firestore set here for when we come online. userStatusFirestoreRef.set(isOnlineForFirestore); }); });
من خلال هذه التغييرات، تأكّدنا الآن من أنّ حالة المزامنة المحلية Cloud Firestore ستعرض دائمًا حالة الجهاز على الإنترنت أو عدم اتصاله به. وهذا يعني أنّه يمكنك الاستماع إلى مستند /status/{uid} واستخدام البيانات لتغيير واجهة المستخدم بما يتناسب مع حالة الاتصال.
الويب
userStatusFirestoreRef.onSnapshot(function(doc) { var isOnline = doc.data().state == 'online'; // ... use isOnline });
تحديث Cloud Firestore على مستوى العالم
على الرغم من أنّ تطبيقنا يعرض حالة الاتصال بالإنترنت بشكل صحيح، لن تكون هذه الحالة دقيقة في تطبيقات Cloud Firestore الأخرى بعد، لأنّ حالة "غير متصل بالإنترنت" التي نكتبها تكون محلية فقط ولن تتم مزامنتها عند استعادة الاتصال. ولحلّ هذه المشكلة، سنستخدم Cloud Function تراقب المسار status/{uid} في Realtime Database. عندما تتغيّر قيمة قاعدة بيانات الوقت الفعلي، ستتم مزامنة القيمة مع Cloud Firestore لضمان صحة حالات جميع المستخدمين.
Node.js
firebase.firestore().collection('status') .where('state', '==', 'online') .onSnapshot(function(snapshot) { snapshot.docChanges().forEach(function(change) { if (change.type === 'added') { var msg = 'User ' + change.doc.id + ' is online.'; console.log(msg); // ... } if (change.type === 'removed') { var msg = 'User ' + change.doc.id + ' is offline.'; console.log(msg); // ... } }); });
بعد نشر هذه الدالة، سيتوفّر لديك نظام كامل لتحديد الموقع الجغرافي يعمل باستخدام Cloud Firestore. في ما يلي مثال على مراقبة أي مستخدمين يتصلون بالإنترنت أو ينقطع اتصالهم به باستخدام طلب بحث where().
الويب
firebase.firestore().collection('status') .where('state', '==', 'online') .onSnapshot(function(snapshot) { snapshot.docChanges().forEach(function(change) { if (change.type === 'added') { var msg = 'User ' + change.doc.id + ' is online.'; console.log(msg); // ... } if (change.type === 'removed') { var msg = 'User ' + change.doc.id + ' is offline.'; console.log(msg); // ... } }); });
القيود
إنّ استخدام قاعدة بيانات الوقت الفعلي لإضافة ميزة "حالة التوفّر" إلى تطبيقك Cloud Firestore هو حلّ قابل للتوسّع وفعّال، ولكنّه يتضمّن بعض القيود:
- إزالة التكرار: عند الاستماع إلى التغييرات في الوقت الفعلي في Cloud Firestore، من المرجّح أن يؤدي هذا الحل إلى تشغيل تغييرات متعدّدة. وإذا أدّت هذه التغييرات إلى تشغيل أحداث أكثر من المطلوب، عليك إزالة التكرار يدويًا من أحداث Cloud Firestore.
- الاتصال: يقيس هذا التنفيذ الاتصال بقاعدة بيانات Realtime، وليس بـ Cloud Firestore. إذا كانت حالة الاتصال بكل قاعدة بيانات مختلفة، قد يعرض هذا الحل حالة حضور غير صحيحة.
- Android: على أجهزة Android، يتم قطع اتصال قاعدة بيانات الوقت الفعلي بالخادم الخلفي بعد 60 ثانية من عدم النشاط، ويُقصد بعدم النشاط عدم وجود أي متتبِّعات أحداث مفتوحة أو عمليات معلّقة. ولإبقاء الاتصال مفتوحًا، ننصحك بإضافة متتبِّع أحداث القيمة إلى مسار غير
.info/connected. على سبيل المثال، يمكنك إجراءFirebaseDatabase.getInstance().getReference((new Date()).toString()).keepSynced()في بداية كل جلسة. لمزيد من المعلومات، اطّلِع على رصد حالة الاتصال.