Как я могу эффективно управлять количеством наблюдателей / слушателей в документе в Firebase? - PullRequest
0 голосов
/ 23 января 2020

Допустим, у меня есть коллекция документов в Cloud Firestore. Я хочу, чтобы люди наблюдали за этими документами, но я не хочу, чтобы более 100 человек наблюдали за одним и тем же документом в любой момент времени. Как мне эффективно отследить это?

Сначала я думал отслеживать количество наблюдателей / слушателей, управляя массивом идентификаторов пользователей в каждом документе. По сути, пользователи должны добавлять свои идентификаторы в этот массив перед наблюдением / прослушиванием (или быть отвергнутыми, если этот массив слишком велик) и удалять свои идентификаторы из этого массива, когда они останавливаются. Проблема с этим заключается в том, что я не могу просто остановить выход пользователя, если не удастся вызвать удаление этого идентификатора из массива. Что, если они каким-то образом завершат работу приложения, и вызов для удаления их идентификатора не будет go через?

Есть ли более разумное решение этой проблемы? Может ли это быть решено с помощью базы данных в реальном времени или облачных функций? Спасибо!

Ответы [ 2 ]

0 голосов
/ 25 января 2020

РЕШИТЬ! Большое спасибо Renaud Tarne c за его оригинальный комментарий, ссылающийся на документацию, которую я еще не видел. Мне не хватало ключевого слова "присутствие" в моих поисках в Google. Пожалуйста, поддержите его комментарий, если вы найдете этот ответ полезным!

РЕШЕНИЕ: Использование https://firebase.google.com/docs/firestore/solutions/presence

SWIFT:

var connectionReference: DatabaseReference = Database.database().reference(withPath: ".info/connected")
var personalReference: DatabaseReference?
var connectionIssued: Bool = false
func connect(room: String) {
    // Remove any existing observations to ensure only one exists.
    connectionReference.removeAllObservers()
    // Start observing connection.
    connectionReference.observe(.value) { (isConnected) in
        if isConnected.value as! Bool {
            // Connected!
            // Use Bool connectionIssued to ensure this is run only once.
            if !self.connectionIssued {
                self.connectionIssued = true
                self.personalReference = Database.database().reference(withPath: "OnlineUsers/\(userID)")
                // Set onDisconnect before setting value.
                self.personalReference!.onDisconnectRemoveValue()
                self.personalReference!.setValue(room)
                // Now the user is "online" and can proceed.
                // Allow user to "enter" room.
            } else {
                // Connection already issued.
            }
        } else {
            // The user has either disconnected from an active connection or they were already disconnected before connect() was called.
            // Stop observing connection.
            self.connectionReference.removeAllObservers()
            // If the user disconnects after they have entered a room, kick them out.
            if self.connectionIssued {
                // User lost connection.
                kickUserOutOfRoom()
                self.connectionIssued = false
            } else {
                // User cannot log in.
            }
        }
    }
}
// Call when users leave a room when still connected.
func leaveRoomManually() {
    // Remove connection observation.
    connectionReference.removeAllObservers()
    // Attempt to remove "online" marker in database.
    personalReference?.removeValue(completionBlock: { (error, reference) in
        if error != nil {
            // Removal failed, but that should be okay!
            // onDisconnect will still be called later!
            // This failure might result in ghost users if the user proceeds to join another room before disconnecting.
            // Consider writing an onUpdate() cloud function in conjunction with the following onCreate() and onDelete() cloud functions to take care of that case.
        } else {
            // "Online" marker removed from database!
            // We can now cancel the onDisconnect()
            self.personalReference?.cancelDisconnectOperations()
        }
    })
    leaveRoom()
}

ФУНКЦИИ ОБЛАКА (javascript):

Следующие облачные функции обновляют количество гостей соответствующей комнаты в Cloud Firestore.

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

const firestore = admin.firestore();
exports.userCameOnline = functions.database.ref('/OnlineUsers/{userID}').onCreate(
    async (snapshot, context) => {
        const room = snapshot.val();
        const guestCountRef = firestore.doc(`Rooms/${room}`);
        return guestCountRef.update({
            Guests: admin.firestore.FieldValue.increment(1)
        });
    });
exports.userWentOffline = functions.database.ref('/OnlineUsers/{userID}').onDelete(
    async (snapshot, context) => {
        const room = snapshot.val();
        const guestCountRef = firestore.doc(`Rooms/${room}`);
        return guestCountRef.update({
            Guests: admin.firestore.FieldValue.increment(-1)
        });
    });
0 голосов
/ 23 января 2020

Я не уверен, но попробуйте погуглить правила доступа Firebase. Я думаю, что вы можете управлять доступом в этой области.
Я говорю об этих правилах.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true;
    }
  }
}

Извините за ответ в этом стиле, у меня нет необходимой репутации для создания комментариев

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...