10

Meteor でデータ機密性の高いアプリケーションを作成しており、クライアント アクセスをできるだけ多くの情報に制限しようとしています。したがって、ログインしている匿名のユーザーの数をカウントする方法をサーバー側に実装したいと考えています。

私はさまざまな方法を試しました。1 つ目は、この質問Server cleanup after a client disconnectsで概説されているとおりで、以下にフックすることを示唆しています。

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

ただし、コレクションを変更しようとすると、「Meteor コードは常にファイバー内で実行する必要があります」というエラーがスローされました。この問題は、ソケットが閉じられるとファイバーが強制終了され、データベースにアクセスできなくなるためだと思います。OPは、可能な解決策としてサーバーでCollection.insertを呼び出すときに、この「Meteorコードは常にファイバー内で実行する必要がある」と指摘しましたが、回答へのコメントに基づいて、それが最善の方法であるかどうかはわかりませんでした。

次に、変数で自動実行を試みました。

Meteor.default_server.stream_server.all_sockets().length

しかし、自動実行は呼び出されていないようだったので、変数はリアクティブなコンテキストではないと想定しており、それを作成する方法がわかりませんでした.

最後のアイデアは、キープアライブ スタイルの処理を行うことでしたが、それは Meteor の哲学の趣旨に完全に反しているように思われます。絶対的な最後の手段としてのみ使用すると思います。

console.logで関数を実行しましたが、this.session.socket可能な他の関数は だけでし.on("data")たが、これはソケットが閉じているときに呼び出されません。

私はここで少し途方に暮れているので、どんな助けも素晴らしいでしょう、ありがとう.

4

3 に答える 3

3

Sorhus のヒントのおかげで、これを解決することができました。彼の答えには、私が避けたかったハートビートが含まれています。ただし、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);
    }));
  }
}
于 2013-01-04T18:27:29.253 に答える
2

GitHubプロジェクトをチェックしてください。

現在オンラインになっているユーザーの数を示すMeteorアプリケーションテスト。

于 2012-12-03T03:03:53.193 に答える