בנה נוכחות ב-Cloud Firestore

בהתאם לסוג האפליקציה שאתה בונה, ייתכן שיהיה שימושי לזהות אילו מהמשתמשים או המכשירים שלך מחוברים באופן פעיל - הידוע גם כזיהוי "נוכחות".

לדוגמה, אם אתה בונה אפליקציה כמו רשת חברתית או פורס צי של מכשירי IoT, תוכל להשתמש במידע זה כדי להציג רשימה של חברים מקוונים וחופשיים לצ'אט, או למיין את מכשירי ה-IoT שלך לפי "נראה לאחרונה" ."

Cloud Firestore לא תומך בנוכחות באופן מקורי, אבל אתה יכול למנף מוצרים אחרים של Firebase כדי לבנות מערכת נוכחות.

פתרון: פונקציות ענן עם מסד נתונים בזמן אמת

כדי לחבר את Cloud Firestore לתכונת הנוכחות המקורית של Firebase Realtime Database, השתמש ב-Cloud Functions.

השתמש במסד נתונים בזמן אמת כדי לדווח על מצב חיבור, ולאחר מכן השתמש בפונקציות הענן כדי לשקף את הנתונים האלה לתוך 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);
    });
});

דוגמה זו היא מערכת נוכחות של מסד נתונים בזמן אמת. הוא מטפל במספר ניתוקים, קריסות וכן הלאה.

מתחבר ל-Cloud Firestore

כדי ליישם פתרון דומה ב-Cloud Firestore, השתמש באותו קוד של מסד נתונים בזמן אמת, ולאחר מכן השתמש בפונקציות הענן כדי לשמור על סנכרון בין מסד הנתונים של Realtime ו-Cloud Firestore.

אם עדיין לא עשית זאת, הוסף את מסד נתונים בזמן אמת לפרויקט שלך וכלול את פתרון הנוכחות לעיל.

לאחר מכן תסנכרן את מצב הנוכחות עם Cloud Firestore באמצעות השיטות הבאות:

  1. באופן מקומי, למטמון Cloud Firestore של המכשיר הלא מקוון, כך שהאפליקציה תדע שהוא במצב לא מקוון.
  2. באופן גלובלי, שימוש בפונקציית ענן כך שכל המכשירים האחרים שניגשים ל-Cloud Firestore יודעים שהמכשיר הספציפי הזה לא מקוון.

עדכון המטמון המקומי של 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 עדיין מכיוון שכתיבת הסטטוס "לא מקוון" שלנו היא מקומית בלבד ולא יסונכרן כאשר החיבור ישוחזר. כדי להתמודד עם זה, נשתמש בפונקציית ענן אשר צופה בנתיב 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 שלך ​​ניתן להרחבה ויעיל, אך יש לו כמה מגבלות:

  • Debouncing - בעת האזנה לשינויים בזמן אמת ב-Cloud Firestore, סביר להניח שהפתרון הזה יפעיל שינויים מרובים. אם השינויים האלה מפעילים יותר אירועים ממה שאתה רוצה, בטל ידנית את אירועי Cloud Firestore.
  • קישוריות - יישום זה מודד קישוריות למסד נתונים בזמן אמת, לא ל-Cloud Firestore. אם מצב החיבור לכל מסד נתונים אינו זהה, פתרון זה עשוי לדווח על מצב נוכחות שגוי.
  • אנדרואיד - באנדרואיד, מסד הנתונים בזמן אמת מתנתק מהקצה האחורי לאחר 60 שניות של חוסר פעילות. חוסר פעילות פירושה ללא מאזינים פתוחים או פעולות ממתינות. כדי לשמור על החיבור פתוח, אנו ממליצים להוסיף מאזין אירועי ערך לנתיב מלבד .info/connected . לדוגמה, אתה יכול לעשות FirebaseDatabase.getInstance().getReference((new Date()).toString()).keepSynced() בתחילת כל הפעלה. למידע נוסף, ראה זיהוי מצב חיבור .