Как отслеживать количество анонимных пользователей на стороне сервера в Meteor?

Я пишу чувствительное к данным приложение в Meteor и пытаюсь ограничить доступ клиента к максимально возможной информации. Поэтому я хочу реализовать серверную сторону для подсчета количества зарегистрированных и анонимных пользователей.

Я пробовал различные методы. Первый из них был описан в этом вопросе Очистка сервера после отсоединения клиента, что предполагает подключение к нему:

this.session.socket.on("close")

Однако когда я это сделал и попытался сменить коллекцию, он выбросил код "Метеор", который должен всегда выполняться внутри Fiber. Я предполагаю, что эта проблема связана с тем, что после того, как сокет закрыт, этот Fiber убит, поэтому доступ к базе данных невозможен. OP указал на этот код Meteor всегда должен работать в пределах Fiber " при вызове Collection.insert на сервере в качестве возможного решения, но я не был уверен, что это лучший метод, основанный на комментариях к ответу.

Затем я попытался автозапускать переменную:

Meteor.default_server.stream_server.all_sockets().length

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

Последняя идея состояла в том, чтобы сделать стиль keepalive style, но это, похоже, полностью противоречит текстуре "Метеор", и я думаю, что буду использовать только в качестве крайней последней меры.

Я выполнил console.log функций на this.session.socket, и единственной возможной функцией была .on("data"), но это не вызывается, когда сокет закрыт.

Я немного потерял здесь, поэтому любая помощь будет отличной, Спасибо.

Ответ 1

Для полноты, вероятно, лучше всего совместить два ответа выше. Другими словами, сделайте следующее:

Вероятно, это будет канонический способ реализовать это в Метеор. Я создал это как смарт-пакет, который можно установить с помощью Meteorite: https://github.com/mizzao/meteor-user-status

Ответ 2

Благодаря наконечнику Сорхуса мне удалось это решить. Его ответ содержит сердцебиение, которое я хотел избежать. Тем не менее, он содержал трюк использования Meteor "bindEnvironment". Это позволяет получить доступ к коллекции, которая в противном случае была бы недоступна.

Meteor.publish("whatever", function() {
  userId = this.userId;
  if(userId) Stats.update({}, {$addToSet: {users: userId}});
  else Stats.update({}, {$inc: {users_anon: 1}});

  // This is required, because otherwise each time the publish function is called,
  // the events re-bind and the counts will start becoming ridiculous as the functions
  // are called multiple times!
  if(this.session.socket._events.data.length === 1) {

    this.session.socket.on("data", Meteor.bindEnvironment(function(data) {
      var method = JSON.parse(data).method;

      // If a user is logging in, dec anon. Don't need to add user to set,
      // because when a user logs in, they are re-subscribed to the collection,
      // so the publish function will be called again.
      // Similarly, if they logout, they re-subscribe, and so the anon count
      // will be handled when the publish function is called again - need only
      // to take out the user ID from the users array.
      if(method === 'login')
        Stats.update({}, {$inc: {users_anon: -1}});

      // If a user is logging out, remove from set
      else if(method === 'logout')
        Stats.update({}, {$pull: {users: userId}});

    }, function(e) {
      console.log(e);
    }));

    this.session.socket.on("close", Meteor.bindEnvironment(function() {
      if(userId === null || userId === undefined) 
        Stats.update({}, {$inc: {users_anon: -1}});
      else
        Stats.update({}, {$pull: {users: userId}});
    }, function(e) {
      console.log("close error", e);
    }));
  }
}

Ответ 3

Оформить проект GitHub howmanypeoplearelooking

Тестирование приложения Meteor, чтобы показать, сколько пользователей сейчас в сети.