faye_tracking 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +25 -1
- data/lib/faye_tracking/faye_extension.rb +13 -4
- data/lib/faye_tracking/{abstract_store.rb → store/abstract_key_list.rb} +5 -1
- data/lib/faye_tracking/store/abstract_mapping.rb +15 -0
- data/lib/faye_tracking/{redis_store.rb → store/adapter/redis_key_list.rb} +5 -1
- data/lib/faye_tracking/store/adapter/redis_mapping.rb +20 -0
- data/lib/faye_tracking/tracker.rb +25 -12
- data/lib/faye_tracking/version.rb +1 -1
- data/lib/faye_tracking.rb +18 -4
- data/spec/faye_tracking_spec.rb +37 -15
- data/spec/spec_helper.rb +1 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7fcbc653ce1ea17f6709545fd5ac543cee22bfae
|
4
|
+
data.tar.gz: 4ea9bc79243cb02c01cff7a846c65c4165aa0447
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
-
|
16
|
+
client_id = message['clientId']
|
15
17
|
|
16
18
|
case message['channel']
|
17
19
|
when '/meta/subscribe'
|
18
|
-
|
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.
|
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
|
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
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module FayeTracking
|
2
|
-
class
|
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(
|
4
|
-
@
|
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
|
-
@
|
9
|
-
@
|
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,
|
13
|
-
@
|
14
|
-
|
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
|
-
@
|
31
|
+
@key_list.members(user)
|
19
32
|
end
|
20
33
|
|
21
34
|
def users_in_channel(channel)
|
22
|
-
@
|
35
|
+
@key_list.members(channel)
|
23
36
|
end
|
24
37
|
|
25
38
|
def user_in_channel?(user, channel)
|
26
|
-
@
|
39
|
+
@key_list.member?(user, channel)
|
27
40
|
end
|
28
41
|
|
29
42
|
def channel_has_user?(channel, user)
|
30
|
-
@
|
43
|
+
@key_list.member?(channel, user)
|
31
44
|
end
|
32
45
|
end
|
33
46
|
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 ||=
|
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/
|
44
|
-
require "faye_tracking/
|
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"
|
data/spec/faye_tracking_spec.rb
CHANGED
@@ -5,24 +5,32 @@ describe FayeTracking do
|
|
5
5
|
FayeTracking.reset_store
|
6
6
|
end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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(
|
20
|
-
faye_run('/meta/disconnect',
|
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 '
|
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
|
-
|
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
|
-
|
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
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.
|
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/
|
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
|