Cloud Firestore'da varlık oluşturun

Geliştirdiğiniz uygulamanın türüne bağlı olarak, etkin olarak çevrimiçi olduğunu, diğer bir deyişle "varlığı algılamak" olarak da bilinen kullanıcılarınızı veya cihazlarınızı tespit etmek faydalı olabilir.

Örneğin, sosyal ağ gibi bir uygulama oluşturuyorsanız veya bir grup IoT cihazı dağıtıyorsanız bu bilgileri kullanarak hem online hem de sohbet etmek serbest olan arkadaşlarınızın listesini gösterebilir veya IoT cihazlarınızı "son görülme zamanı"na göre sıralayabilirsiniz.

Cloud Firestore, varlık gösterme özelliğini yerel olarak desteklemez ancak varlık sistemi oluşturmak için diğer Firebase ürünlerinden yararlanabilirsiniz.

Çözüm: Cloud Functions with Realtime Database

Cloud Firestore'u Firebase Realtime Database'in yerel varlık özelliğine bağlamak için Cloud Functions'ı kullanın.

Bağlantı durumunu raporlamak için Realtime Database'i, ardından bu verileri Cloud Firestore'a yansıtmak için Cloud Functions'ı kullanın.

Realtime Database'de varlık kullanma

Öncelikle geleneksel varlık durumunun Realtime Database'de nasıl çalıştığını düşünün.

Web

// 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);
    });
});

Bu örnek, eksiksiz bir Realtime Database varlık sistemidir. Birden fazla bağlantı kesilmesi, çökme gibi durumların üstesinden gelir.

Cloud Firestore'a Bağlanma

Cloud Firestore'da benzer bir çözümü uygulamak için aynı Realtime Database kodunu kullanın. Ardından Realtime Database ile Cloud Firestore'u senkronize halde tutmak için Cloud Functions'ı kullanın.

Henüz yapmadıysanız projenize Realtime Database'i ekleyin ve yukarıdaki varlık çözümü çözümünü dahil edin.

Ardından, varlık durumunu aşağıdaki yöntemleri kullanarak Cloud Firestore ile senkronize edin:

  1. Yerel olarak, uygulamanın çevrimdışı olduğunu bilmesi için çevrimdışı cihazın Cloud Firestore önbelleğine.
  2. Global olarak, Cloud Firestore'a erişen tüm cihazların bu cihazın çevrimdışı olduğunu bilmesi için Cloud Functions işlevi kullanılır.

Cloud Firestore'un yerel önbelleğini güncelleme

İlk sorunu (Cloud Firestore'un yerel önbelleğini güncelleme) gerçekleştirmek için gereken değişikliklere bakalım.

Web

// ...
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);
    });
});

Bu değişikliklerle birlikte yerel Cloud Firestore durumunun her zaman cihazın online/çevrimdışı durumunu yansıtmasını sağladık. Bu sayede /status/{uid} belgesini dinleyebilir ve verileri kullanıcı arayüzünüzdeki bağlantı durumunu yansıtacak şekilde değiştirebilirsiniz.

Web

userStatusFirestoreRef.onSnapshot(function(doc) {
    var isOnline = doc.data().state == 'online';
    // ... use isOnline
});

Cloud Firestore genel olarak güncelleniyor

Uygulamamız internetteki varlığı doğru bir şekilde kendisine bildirse de "çevrimdışı" durum yazma işlemimiz yalnızca yerel düzeyde olduğundan ve bağlantı tekrar kurulduğunda senkronize edilmeyecektir. Bu nedenle, bu durum henüz diğer Cloud Firestore uygulamalarında doğru olmayabilir. Buna karşılık, Realtime Database'de status/{uid} yolunu izleyen bir Cloud Functions işlevi kullanacağız. Realtime Database değeri değiştiğinde değer Cloud Firestore ile senkronize edilir. Böylece tüm kullanıcıların durumları doğru olur.

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);
                // ...
            }
        });
    });

Bu işlevi dağıttıktan sonra Cloud Firestore ile çalışan eksiksiz bir varlık sisteminiz olur. Aşağıda, where() sorgusu kullanarak internete giren veya çevrimdışı olan tüm kullanıcılar için izleme örneği verilmiştir.

Web

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);
                // ...
            }
        });
    });

Sınırlamalar

Cloud Firestore uygulamanıza varlık eklemek için Realtime Database'i kullanmak ölçeklenebilir ve etkilidir ancak bazı sınırlamaları vardır:

  • Azaltma: Cloud Firestore'da gerçek zamanlı değişiklikleri dinlerken bu çözüm muhtemelen birçok değişikliği tetikleyebilir. Bu değişiklikler istediğinizden daha fazla etkinliği tetiklerse Cloud Firestore etkinliklerinin sayısını manuel olarak azaltın.
  • Bağlantı: Bu uygulama Cloud Firestore ile değil, Realtime Database bağlantısını ölçer. Her bir veritabanıyla bağlantı durumu aynı değilse bu çözüm yanlış varlık durumu bildirebilir.
  • Android: Android'de, 60 saniye boyunca hiçbir işlem yapılmazsa Realtime Database'in arka uçla bağlantısı kesilir. Etkin olmama, açık dinleyicilerin veya beklemedeki işlemlerin olmadığı anlamına gelir. Bağlantıyı açık tutmak için .info/connected dışındaki bir yola değer etkinliği işleyici eklemenizi öneririz. Örneğin, her oturumun başında FirebaseDatabase.getInstance().getReference((new Date()).toString()).keepSynced() yapabilirsiniz. Daha fazla bilgi için Bağlantı Durumunu Algılama konusuna bakın.