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 +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
|