faye_tracking 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e65dc0c10240816a421e137aa34bbb0d1a31bf8b
4
- data.tar.gz: ff775198df38629943868fd204a592e77cac9e46
3
+ metadata.gz: 7fcbc653ce1ea17f6709545fd5ac543cee22bfae
4
+ data.tar.gz: 4ea9bc79243cb02c01cff7a846c65c4165aa0447
5
5
  SHA512:
6
- metadata.gz: c8c584abc579d57ac7d091462aada28192503edca65eb7371bccd9e130a176a586d86be5ed4904c7949495cf188da93d73aa6fd9f91e9c99dfb64d2e49243268
7
- data.tar.gz: 07d9b9f1f3e5adbdc827086cefbfe46a7e344b3deba479a2c2aa9b6eeefead78251c7dd911c02635054601acc98e822be3922a963c003e911dc73caf15985341
6
+ metadata.gz: 468a983f7595f5d4965d180bb8bfe52145409e0373c1d79c53c5c6acc173cb576022246527696f91f1ab72d798dd789a6ae084a511199b12219c95b145da545a
7
+ data.tar.gz: 41c937b43b00d5f16ed23bd6a7af702ec9b8457567848836e9e8b57ee0c0e8ef607f5772f847c24db0c0c0989107b81f11b6a2b23445eea63193394138d492d6
data/README.md CHANGED
@@ -3,6 +3,8 @@
3
3
  A Faye extension for tracking user subscriptions, i.e. can be used for
4
4
  checking if a user is online.
5
5
 
6
+ BUT: http://faye.jcoglan.com/ruby/monitoring.html
7
+
6
8
  ## Prerequisites
7
9
 
8
10
  * Faye
@@ -26,16 +28,38 @@ Or install it yourself as:
26
28
 
27
29
  ## Usage
28
30
 
31
+ Set it up:
32
+
29
33
  ```ruby
30
34
  FayeTracking.configure do |config|
31
35
  config.redis = Redis.new
32
36
  end
33
37
 
38
+ client.add_extension(FayeTracking.faye_extension)
39
+
34
40
  FayeTracking.all_users_in_channel('/chat/1')
35
41
  FayeTracking.user_in_any_channel?('/user_1')
36
42
  FayeTracking.user_in_channel?('/user_1', '/chat/1')
43
+ ```
37
44
 
38
- client.add_extension(FayeTracking.faye_extension)
45
+ Client side: a PrivatePub example using a fork here: https://github.com/he9lin/private_pub, which makes it possible to add client side Faye extensions to PrivatePub javascript.
46
+
47
+ ```coffeescript
48
+ FayeTrackingExtension =
49
+ outgoing: (message, callback) ->
50
+ if message.channel == "/meta/subscribe"
51
+ # Attach the user id to subscription messages
52
+ subscription = PrivatePub.subscriptions[message.subscription]
53
+ message.ext ?= {}
54
+ message.ext.faye_tracking_client_id = subscription.user_id
55
+ callback(message)
56
+
57
+ PrivatePub.extensions = [PrivatePubClientIdExtension]
58
+
59
+ # To subscribe to a channel
60
+ subscription["user_id"] = user_id
61
+ PrivatePub.sign(subscription)
62
+ PrivatePub.subscribe(subscription.channel, callback)
39
63
  ```
40
64
 
41
65
  ## Contributing
@@ -1,6 +1,6 @@
1
1
  module FayeTracking
2
2
  class FayeExtension
3
- MONITORED_CHANNELS = [ '/meta/subscribe', '/meta/disconnect' ]
3
+ MONITORED_CHANNELS = [ '/meta/subscribe', '/meta/unsubscribe', '/meta/disconnect' ]
4
4
 
5
5
  def initialize(tracker)
6
6
  @tracker = tracker
@@ -9,15 +9,24 @@ module FayeTracking
9
9
  def incoming(message, callback)
10
10
  return callback.call(message) unless MONITORED_CHANNELS.include? message['channel']
11
11
 
12
+ FayeTracking.logger.debug "received incoming message: #{message}"
13
+
12
14
  unless message['error']
13
15
  subs_channel = message['subscription']
14
- app_client_id = message['ext']['faye_tracking_client_id']
16
+ client_id = message['clientId']
15
17
 
16
18
  case message['channel']
17
19
  when '/meta/subscribe'
18
- @tracker.add(subs_channel, app_client_id)
20
+ ext = message['ext']
21
+ if app_client_id = ext['faye_tracking_client_id']
22
+ @tracker.add(subs_channel, client_id, app_client_id)
23
+ else
24
+ message['error'] = "missing ext['faye_tracking_client_id']"
25
+ end
26
+ when '/meta/unsubscribe'
27
+ @tracker.remove(subs_channel, client_id)
19
28
  when '/meta/disconnect'
20
- @tracker.remove(subs_channel, app_client_id)
29
+ @tracker.remove_user_from_all_channels(client_id)
21
30
  end
22
31
  end
23
32
 
@@ -1,5 +1,5 @@
1
1
  module FayeTracking
2
- class AbstractStore
2
+ class AbstractKeyList
3
3
  def add(key, value)
4
4
  raise NotImplementedError
5
5
  end
@@ -19,5 +19,9 @@ module FayeTracking
19
19
  def empty?(key)
20
20
  raise NotImplementedError
21
21
  end
22
+
23
+ def remove_all(key)
24
+ raise NotImplementedError
25
+ end
22
26
  end
23
27
  end
@@ -0,0 +1,15 @@
1
+ module FayeTracking
2
+ class AbstractMapping
3
+ def set(key, value)
4
+ raise NotImplementedError
5
+ end
6
+
7
+ def get(key)
8
+ raise NotImplementedError
9
+ end
10
+
11
+ def delete(key)
12
+ raise NotImplementedError
13
+ end
14
+ end
15
+ end
@@ -1,5 +1,5 @@
1
1
  module FayeTracking
2
- class RedisStore < AbstractStore
2
+ class RedisKeyList < AbstractKeyList
3
3
  def initialize(redis)
4
4
  @redis = redis
5
5
  end
@@ -23,5 +23,9 @@ module FayeTracking
23
23
  def empty?(key)
24
24
  @redis.smembers(key).empty?
25
25
  end
26
+
27
+ def remove_all(key)
28
+ @redis.del(key)
29
+ end
26
30
  end
27
31
  end
@@ -0,0 +1,20 @@
1
+ module FayeTracking
2
+ class RedisMapping < AbstractMapping
3
+ def initialize(redis, name=FayeTracking::MAPPING_STORE_NAME)
4
+ @name = name
5
+ @redis = redis
6
+ end
7
+
8
+ def set(key, value)
9
+ @redis.hset @name, key, value
10
+ end
11
+
12
+ def get(key)
13
+ @redis.hget @name, key
14
+ end
15
+
16
+ def delete(key)
17
+ @redis.del @name, key
18
+ end
19
+ end
20
+ end
@@ -1,33 +1,46 @@
1
1
  module FayeTracking
2
2
  class Tracker
3
- def initialize(store)
4
- @store = store
3
+ def initialize(key_list, mapping)
4
+ @key_list = key_list
5
+ @mapping = mapping
5
6
  end
6
7
 
7
- def add(channel, user)
8
- @store.add(channel, user)
9
- @store.add(user, channel)
8
+ def add(channel, client_id, user)
9
+ @mapping.set(client_id, user)
10
+ @key_list.add(channel, user)
11
+ @key_list.add(user, channel)
10
12
  end
11
13
 
12
- def remove(channel, user)
13
- @store.remove(channel, user)
14
- @store.remove(user, channel)
14
+ def remove(channel, client_id)
15
+ if user = @mapping.get(client_id)
16
+ @key_list.remove(channel, user)
17
+ @key_list.remove(user, channel)
18
+ end
19
+ end
20
+
21
+ def remove_user_from_all_channels(client_id)
22
+ if user = @mapping.get(client_id)
23
+ channels_for_user(user).each do |channel|
24
+ @key_list.remove(channel, user)
25
+ end
26
+ @key_list.remove_all(user)
27
+ end
15
28
  end
16
29
 
17
30
  def channels_for_user(user)
18
- @store.members(user)
31
+ @key_list.members(user)
19
32
  end
20
33
 
21
34
  def users_in_channel(channel)
22
- @store.members(channel)
35
+ @key_list.members(channel)
23
36
  end
24
37
 
25
38
  def user_in_channel?(user, channel)
26
- @store.member?(user, channel)
39
+ @key_list.member?(user, channel)
27
40
  end
28
41
 
29
42
  def channel_has_user?(channel, user)
30
- @store.member?(channel, user)
43
+ @key_list.member?(channel, user)
31
44
  end
32
45
  end
33
46
  end
@@ -1,3 +1,3 @@
1
1
  module FayeTracking
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/faye_tracking.rb CHANGED
@@ -1,16 +1,20 @@
1
1
  require 'redis'
2
2
  require 'redis-namespace'
3
+ require 'logger'
3
4
  require "faye_tracking/version"
4
5
 
5
6
  module FayeTracking
7
+ MAPPING_STORE_NAME = 'client_id_to_user'.freeze
8
+
6
9
  class << self
7
- attr_accessor :redis
10
+ attr_accessor :redis, :logger
8
11
 
9
12
  def configure(&block)
10
13
  block.call(self)
11
14
  end
12
15
 
13
16
  def reset_store
17
+ raise 'redis is not set' unless redis
14
18
  redis.keys('*').each {|k| redis.del k}
15
19
  end
16
20
 
@@ -30,16 +34,26 @@ module FayeTracking
30
34
  tracker.users_in_channel(channel)
31
35
  end
32
36
 
37
+ def logger
38
+ @logger ||= Logger.new(STDOUT)
39
+ end
40
+
33
41
  private
34
42
 
35
43
  def tracker
36
44
  raise 'redis is not set' unless redis
37
- @_tracker ||= Tracker.new(RedisStore.new(redis))
45
+ @_tracker ||= begin
46
+ key_list_store = RedisKeyList.new(redis)
47
+ mapping_store = RedisMapping.new(redis)
48
+ Tracker.new(key_list_store, mapping_store)
49
+ end
38
50
  end
39
51
  end
40
52
  end
41
53
 
42
54
  require "faye_tracking/faye_extension"
43
- require "faye_tracking/abstract_store"
44
- require "faye_tracking/redis_store"
55
+ require "faye_tracking/store/abstract_key_list"
56
+ require "faye_tracking/store/abstract_mapping"
57
+ require "faye_tracking/store/adapter/redis_key_list"
58
+ require "faye_tracking/store/adapter/redis_mapping"
45
59
  require "faye_tracking/tracker"
@@ -5,24 +5,32 @@ describe FayeTracking do
5
5
  FayeTracking.reset_store
6
6
  end
7
7
 
8
- def faye_run(meta_action, channel, user)
9
- message = {"channel" => meta_action, "ext" => {}}
10
- message["subscription"] = channel
11
- message["ext"]["faye_tracking_client_id"] = user
8
+ let(:client_id) { 'rpy799jnfeq' }
9
+ let(:another_client_id) { '651w533ncba' }
10
+
11
+ def faye_run(meta_action, subscription, client_id, user)
12
+ message = { "channel" => meta_action, "clientId" => client_id }
13
+ message["subscription"] = subscription if subscription
14
+ message["ext"] = { "faye_tracking_client_id" => user } if user
15
+
12
16
  FayeTracking.faye_extension.incoming(message, lambda { |m| m })
13
17
  end
14
18
 
15
- def faye_subscribe(channel, user)
16
- faye_run('/meta/subscribe', channel, user)
19
+ def faye_subscribe(channel, client_id, user)
20
+ faye_run('/meta/subscribe', channel, client_id, user)
21
+ end
22
+
23
+ def faye_unsubscribe(channel, client_id)
24
+ faye_run('/meta/unsubscribe', channel, client_id, nil)
17
25
  end
18
26
 
19
- def faye_disconnect(channel, user)
20
- faye_run('/meta/disconnect', channel, user)
27
+ def faye_disconnect(client_id)
28
+ faye_run('/meta/disconnect', nil, client_id, nil)
21
29
  end
22
30
 
23
31
  context 'subscribing to a channel' do
24
32
  before do
25
- faye_subscribe 'room', 'user_1'
33
+ faye_subscribe 'room', client_id, 'user_1'
26
34
  end
27
35
 
28
36
  it 'adds user to the subscription channel' do
@@ -32,29 +40,43 @@ describe FayeTracking do
32
40
  end
33
41
 
34
42
  it 'returns all users in a channel' do
35
- faye_subscribe 'room', 'user_2'
43
+ faye_subscribe 'room', client_id, 'user_2'
36
44
  expect(described_class.all_users_in_channel('room')).to match_array(['user_1', 'user_2'])
37
45
  end
38
46
  end
39
47
 
40
- context 'disconnecting to a channel' do
48
+ context 'unsubscribing a channel' do
41
49
  before do
42
- faye_subscribe 'room', 'user_1'
50
+ faye_subscribe 'room', client_id, 'user_1'
43
51
  end
44
52
 
45
53
  it 'removes a user from a subscription channel' do
46
- faye_disconnect 'room', 'user_1'
54
+ faye_unsubscribe 'room', client_id
47
55
  expect(described_class.user_in_any_channel?('user_1')).to be_falsey
48
56
  expect(described_class.all_users_in_channel('rooom')).to eq([])
49
57
 
50
- faye_subscribe 'room', 'user_2'
58
+ faye_subscribe 'room', client_id, 'user_2'
51
59
  expect(described_class.user_in_any_channel?('user_2')).to be_truthy
52
60
  end
53
61
 
54
62
  it 'does not raise error when removing a non-existing user' do
55
63
  expect {
56
- faye_disconnect 'room', 'user_2'
64
+ faye_unsubscribe 'room', 'user_2'
57
65
  }.to_not raise_error
58
66
  end
59
67
  end
68
+
69
+ context 'disconnecting' do
70
+ before do
71
+ faye_subscribe 'room1', client_id, 'user_1'
72
+ faye_subscribe 'room2', client_id, 'user_1'
73
+ faye_subscribe 'room1', another_client_id, 'user_2'
74
+ end
75
+
76
+ it 'removes the user from all channels' do
77
+ faye_disconnect(client_id)
78
+ expect(described_class.user_in_any_channel?('user_1')).to be_falsey
79
+ expect(described_class.all_users_in_channel('room1')).to eq(['user_2'])
80
+ end
81
+ end
60
82
  end
data/spec/spec_helper.rb CHANGED
@@ -4,6 +4,7 @@ require 'faye_tracking'
4
4
 
5
5
  FayeTracking.configure do |config|
6
6
  config.redis = Redis::Namespace.new(:faye_tracking_test, redis: Redis.new)
7
+ config.logger.level = Logger::INFO
7
8
  end
8
9
 
9
10
  RSpec.configure do |config|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: faye_tracking
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lin He
@@ -95,9 +95,11 @@ files:
95
95
  - Rakefile
96
96
  - faye_tracking.gemspec
97
97
  - lib/faye_tracking.rb
98
- - lib/faye_tracking/abstract_store.rb
99
98
  - lib/faye_tracking/faye_extension.rb
100
- - lib/faye_tracking/redis_store.rb
99
+ - lib/faye_tracking/store/abstract_key_list.rb
100
+ - lib/faye_tracking/store/abstract_mapping.rb
101
+ - lib/faye_tracking/store/adapter/redis_key_list.rb
102
+ - lib/faye_tracking/store/adapter/redis_mapping.rb
101
103
  - lib/faye_tracking/tracker.rb
102
104
  - lib/faye_tracking/version.rb
103
105
  - spec/faye_tracking_spec.rb