pubsub 0.0.0 → 0.0.1
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.
- data/.autotest +1 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/VERSION +1 -1
- data/autotest/discover.rb +1 -0
- data/lib/pubsub.rb +1 -60
- data/lib/pubsub/logger.rb +12 -0
- data/lib/pubsub/pubsub.rb +79 -26
- data/spec/pubsup_spec.rb +64 -0
- data/spec/spec_helper.rb +42 -0
- metadata +54 -17
- data/test/helper.rb +0 -18
- data/test/test_pubsub.rb +0 -7
data/.autotest
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'autotest/growl'
|
data/.rspec
ADDED
data/Gemfile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.1
|
@@ -0,0 +1 @@
|
|
1
|
+
Autotest.add_discovery { "rspec2" }
|
data/lib/pubsub.rb
CHANGED
@@ -1,61 +1,2 @@
|
|
1
1
|
require "ruby_events"
|
2
|
-
require File.join(File.dirname(__FILE__), "pubsub/pubsub.rb")
|
3
|
-
|
4
|
-
module DigitalPro
|
5
|
-
module Events
|
6
|
-
module PubSub
|
7
|
-
def subscribe(channel, procs = nil, &block)
|
8
|
-
logger.info "Subscribe #{self.class.name} to #{channel}"
|
9
|
-
|
10
|
-
PubSub.events.listen channel, procs, &block
|
11
|
-
|
12
|
-
procs_collected = []
|
13
|
-
if procs.respond_to?(:each) && procs.respond_to?(:to_a)
|
14
|
-
procs_collected += procs.to_a
|
15
|
-
elsif procs
|
16
|
-
procs_collected << procs
|
17
|
-
end
|
18
|
-
procs_collected << block if block
|
19
|
-
|
20
|
-
channel_handlers[channel] ||= []
|
21
|
-
channel_handlers[channel] += procs_collected
|
22
|
-
end
|
23
|
-
|
24
|
-
def unsubscribe(channel=nil, proc = nil)
|
25
|
-
# unsubscribe from all object channels
|
26
|
-
unless channel
|
27
|
-
channel_handlers.each_key{ |channel_name| unsubscribe channel_name}
|
28
|
-
return
|
29
|
-
end
|
30
|
-
|
31
|
-
if proc
|
32
|
-
logger.info "Unsubscribe #{self.class.name} to #{channel}"
|
33
|
-
PubSub.events.remove channel, proc
|
34
|
-
channel_handlers[channel].delete_if {|stored_event| stored_event == proc} if channel_handlers.include? channel
|
35
|
-
else
|
36
|
-
channel_handlers[channel].each { |proc_handler| unsubscribe channel, proc_handler} if channel_handlers.include? channel
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def publish(channel, *args)
|
41
|
-
logger.info "Publish #{self.class.name} to #{channel} with #{args.to_s}"
|
42
|
-
|
43
|
-
channel.sub_before "/" do |sub_channel|
|
44
|
-
PubSub.events.fire sub_channel, *args
|
45
|
-
end
|
46
|
-
PubSub.events.fire "*", *args
|
47
|
-
end
|
48
|
-
|
49
|
-
protected
|
50
|
-
|
51
|
-
def channel_handlers
|
52
|
-
@channel_handlers ||= {}
|
53
|
-
end
|
54
|
-
|
55
|
-
def PubSub.events
|
56
|
-
@@events ||= RubyEvents::Events.new(self)
|
57
|
-
end
|
58
|
-
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
2
|
+
require File.join(File.dirname(__FILE__), "pubsub/pubsub.rb")
|
data/lib/pubsub/pubsub.rb
CHANGED
@@ -1,55 +1,108 @@
|
|
1
1
|
require "ruby_events"
|
2
|
+
require File.join(File.dirname(__FILE__), "logger.rb")
|
2
3
|
require File.join(File.dirname(__FILE__), "string.rb")
|
3
4
|
|
4
5
|
module PubSub
|
5
6
|
def subscribe(channel, procs = nil, &block)
|
6
|
-
|
7
|
+
mutex.synchronize do
|
8
|
+
logger.info "Subscribe #{self.class.name} to #{channel}"
|
7
9
|
|
8
|
-
|
10
|
+
PubSub.events.listen channel, procs, &block
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
procs_collected = []
|
13
|
+
if procs.respond_to?(:each) && procs.respond_to?(:to_a)
|
14
|
+
procs_collected += procs.to_a
|
15
|
+
elsif procs
|
16
|
+
procs_collected << procs
|
17
|
+
end
|
18
|
+
procs_collected << block if block
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
+
channel_handlers[channel] ||= []
|
21
|
+
channel_handlers[channel] += procs_collected
|
22
|
+
end
|
20
23
|
end
|
21
24
|
|
22
25
|
def unsubscribe(channel=nil, proc = nil)
|
23
|
-
|
24
|
-
|
25
|
-
channel_handlers.each_key{ |channel_name| unsubscribe channel_name}
|
26
|
-
return
|
26
|
+
mutex.synchronize do
|
27
|
+
unsubscribe_safe(channel, proc )
|
27
28
|
end
|
29
|
+
end
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
channel_handlers[channel].each { |proc_handler| unsubscribe channel, proc_handler} if channel_handlers.include? channel
|
31
|
+
def publish(channel, *args)
|
32
|
+
mutex.synchronize do
|
33
|
+
logger.info "Add to publish queue #{self.class.name} to #{channel} with #{args.to_s}"
|
34
|
+
PubSub.queue.push({:sender => self, :channel => channel, :params => args})
|
35
|
+
PubSub.thread.wakeup if PubSub.thread.status == "sleep"
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
38
|
-
def
|
39
|
-
|
39
|
+
def PubSub.run
|
40
|
+
@@stopped = false
|
41
|
+
PubSub.thread
|
42
|
+
while true
|
43
|
+
if @@stopped
|
44
|
+
PubSub.queue.clear
|
45
|
+
break
|
46
|
+
end
|
47
|
+
|
48
|
+
sleep if PubSub.queue.empty?
|
49
|
+
|
50
|
+
unless PubSub.queue.empty?
|
51
|
+
publish_info = PubSub.queue.shift
|
52
|
+
sender = publish_info[:sender]
|
53
|
+
channel = publish_info[:channel]
|
54
|
+
params = publish_info[:params]
|
55
|
+
logger.info "Publish ObjectID:#{sender.__id__} of class #{sender.class.name} to #{channel} with #{params.to_s}"
|
40
56
|
|
41
|
-
|
42
|
-
|
57
|
+
channel.sub_before "/" do |sub_channel|
|
58
|
+
PubSub.events.fire sub_channel, *params
|
59
|
+
end
|
60
|
+
PubSub.events.fire "*", *params
|
61
|
+
end
|
43
62
|
end
|
44
|
-
|
63
|
+
end
|
64
|
+
|
65
|
+
def PubSub.stop
|
66
|
+
@@stopped = true
|
45
67
|
end
|
46
68
|
|
47
69
|
protected
|
48
70
|
|
71
|
+
def mutex
|
72
|
+
@mutex ||= Mutex.new
|
73
|
+
end
|
74
|
+
|
49
75
|
def channel_handlers
|
50
76
|
@channel_handlers ||= {}
|
51
77
|
end
|
52
78
|
|
79
|
+
def unsubscribe_safe(channel=nil, proc = nil)
|
80
|
+
# unsubscribe from all object channels
|
81
|
+
unless channel
|
82
|
+
channel_handlers.each_key{ |channel_name| unsubscribe_safe channel_name}
|
83
|
+
return
|
84
|
+
end
|
85
|
+
|
86
|
+
unless proc
|
87
|
+
logger.info "Unsubscribe #{self.class.name} from #{channel}"
|
88
|
+
channel_handlers[channel].each { |proc_handler| PubSub.events.remove channel, proc_handler }if channel_handlers.include? channel
|
89
|
+
channel_handlers[channel].clear
|
90
|
+
return
|
91
|
+
end
|
92
|
+
|
93
|
+
logger.info "Unsubscribe #{self.class.name} from #{channel} listener #{proc}"
|
94
|
+
PubSub.events.remove channel, proc
|
95
|
+
channel_handlers[channel].delete_if {|stored_event| stored_event == proc} if channel_handlers.include? channel
|
96
|
+
end
|
97
|
+
|
98
|
+
def PubSub.thread
|
99
|
+
@@thread ||= Thread.current
|
100
|
+
end
|
101
|
+
|
102
|
+
def PubSub.queue
|
103
|
+
@@queue ||= []
|
104
|
+
end
|
105
|
+
|
53
106
|
def PubSub.events
|
54
107
|
@@events ||= RubyEvents::Events.new(self)
|
55
108
|
end
|
data/spec/pubsup_spec.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper.rb")
|
2
|
+
|
3
|
+
describe "Object with PubSub pattern" do
|
4
|
+
before(:each) do
|
5
|
+
PubSub.events.events_collection.clear
|
6
|
+
@publisher = Publisher.new
|
7
|
+
@subscriber = Subscriber.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should subscribe on channel" do
|
11
|
+
@subscriber.subscribe "channel", @subscriber.method(:listener)
|
12
|
+
PubSub.events.events_collection.size.should == 1
|
13
|
+
PubSub.events.events_collection.should have_key "channel"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should unsubscribe specific listeners from channel" do
|
17
|
+
@subscriber.subscribe "channel", @subscriber.method(:listener)
|
18
|
+
@subscriber.unsubscribe "channel", @subscriber.method(:listener)
|
19
|
+
PubSub.events.events_collection["channel"].should be_empty
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should unsubscribe all listeners from channel" do
|
23
|
+
@subscriber.subscribe "channel", @subscriber.method(:listener)
|
24
|
+
@subscriber.subscribe "channel", @subscriber.method(:listener1)
|
25
|
+
@subscriber.unsubscribe "channel"
|
26
|
+
PubSub.events.events_collection["channel"].should be_empty
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should unsubscribe from all channels" do
|
30
|
+
@subscriber.subscribe "channel", @subscriber.method(:listener)
|
31
|
+
@subscriber.subscribe "channel1", @subscriber.method(:listener1)
|
32
|
+
@subscriber.unsubscribe
|
33
|
+
PubSub.events.events_collection["channel"].should be_empty
|
34
|
+
PubSub.events.events_collection["channel1"].should be_empty
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should publish message to channel" do
|
38
|
+
@subscriber.should_receive(:listener).with("Hello world")
|
39
|
+
@subscriber.subscribe "channel", @subscriber.method(:listener)
|
40
|
+
@subscriber.subscribe "channel", @subscriber.method(:listener_with_stop)
|
41
|
+
@publisher.publish("channel", "Hello world")
|
42
|
+
PubSub.run
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should publish message to channel and subchannel" do
|
46
|
+
@subscriber.should_receive(:listener).with("Hello world")
|
47
|
+
@subscriber.subscribe "test/channel", @subscriber.method(:listener)
|
48
|
+
|
49
|
+
@subscriber.should_receive(:listener1).with("Hello world")
|
50
|
+
@subscriber.subscribe "test", @subscriber.method(:listener1)
|
51
|
+
|
52
|
+
@subscriber.subscribe "test/channel", @subscriber.method(:listener_with_stop)
|
53
|
+
@publisher.publish("test/channel", "Hello world")
|
54
|
+
PubSub.run
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should publish message to global channel" do
|
58
|
+
@subscriber.should_receive(:listener).with("Hello world")
|
59
|
+
@subscriber.subscribe "*", @subscriber.method(:listener)
|
60
|
+
@subscriber.subscribe "*", @subscriber.method(:listener_with_stop)
|
61
|
+
@publisher.publish("channel", "Hello world")
|
62
|
+
PubSub.run
|
63
|
+
end
|
64
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
|
11
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
12
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
13
|
+
require 'pubsub'
|
14
|
+
|
15
|
+
logger.level = Logger::WARN
|
16
|
+
|
17
|
+
module PubSub
|
18
|
+
PubSub.events.class.class_eval do
|
19
|
+
def events_collection
|
20
|
+
@events
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Publisher
|
26
|
+
include PubSub
|
27
|
+
end
|
28
|
+
|
29
|
+
class Subscriber
|
30
|
+
include PubSub
|
31
|
+
|
32
|
+
def listener(message = nil)
|
33
|
+
logger.info "listener_with_stop"
|
34
|
+
end
|
35
|
+
|
36
|
+
def listener1(message = nil)
|
37
|
+
end
|
38
|
+
|
39
|
+
def listener_with_stop(message = nil)
|
40
|
+
PubSub.stop
|
41
|
+
end
|
42
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pubsub
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,12 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-07-
|
12
|
+
date: 2011-07-17 00:00:00.000000000 +04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: ruby_events
|
17
|
-
requirement: &
|
17
|
+
requirement: &18948040 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: '0'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *18948040
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: shoulda
|
28
|
-
requirement: &
|
28
|
+
requirement: &18946840 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ! '>='
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *18946840
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: bundler
|
39
|
-
requirement: &
|
39
|
+
requirement: &18946080 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ~>
|
@@ -44,10 +44,10 @@ dependencies:
|
|
44
44
|
version: 1.0.0
|
45
45
|
type: :development
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *18946080
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: jeweler
|
50
|
-
requirement: &
|
50
|
+
requirement: &18945200 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
53
|
- - ~>
|
@@ -55,10 +55,10 @@ dependencies:
|
|
55
55
|
version: 1.6.4
|
56
56
|
type: :development
|
57
57
|
prerelease: false
|
58
|
-
version_requirements: *
|
58
|
+
version_requirements: *18945200
|
59
59
|
- !ruby/object:Gem::Dependency
|
60
60
|
name: rcov
|
61
|
-
requirement: &
|
61
|
+
requirement: &18944220 !ruby/object:Gem::Requirement
|
62
62
|
none: false
|
63
63
|
requirements:
|
64
64
|
- - ! '>='
|
@@ -66,10 +66,43 @@ dependencies:
|
|
66
66
|
version: '0'
|
67
67
|
type: :development
|
68
68
|
prerelease: false
|
69
|
-
version_requirements: *
|
69
|
+
version_requirements: *18944220
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rspec
|
72
|
+
requirement: &18943460 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: *18943460
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: ZenTest
|
83
|
+
requirement: &18928680 !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: *18928680
|
92
|
+
- !ruby/object:Gem::Dependency
|
93
|
+
name: autotest-growl
|
94
|
+
requirement: &18927540 !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ! '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
type: :development
|
101
|
+
prerelease: false
|
102
|
+
version_requirements: *18927540
|
70
103
|
- !ruby/object:Gem::Dependency
|
71
104
|
name: ruby_events
|
72
|
-
requirement: &
|
105
|
+
requirement: &18921320 !ruby/object:Gem::Requirement
|
73
106
|
none: false
|
74
107
|
requirements:
|
75
108
|
- - ! '>='
|
@@ -77,7 +110,7 @@ dependencies:
|
|
77
110
|
version: '0'
|
78
111
|
type: :runtime
|
79
112
|
prerelease: false
|
80
|
-
version_requirements: *
|
113
|
+
version_requirements: *18921320
|
81
114
|
description: PubSub pattern
|
82
115
|
email: maxkazargm@gmail.com
|
83
116
|
executables: []
|
@@ -86,17 +119,21 @@ extra_rdoc_files:
|
|
86
119
|
- LICENSE.txt
|
87
120
|
- README.rdoc
|
88
121
|
files:
|
122
|
+
- .autotest
|
89
123
|
- .document
|
124
|
+
- .rspec
|
90
125
|
- Gemfile
|
91
126
|
- LICENSE.txt
|
92
127
|
- README.rdoc
|
93
128
|
- Rakefile
|
94
129
|
- VERSION
|
130
|
+
- autotest/discover.rb
|
95
131
|
- lib/pubsub.rb
|
132
|
+
- lib/pubsub/logger.rb
|
96
133
|
- lib/pubsub/pubsub.rb
|
97
134
|
- lib/pubsub/string.rb
|
98
|
-
-
|
99
|
-
-
|
135
|
+
- spec/pubsup_spec.rb
|
136
|
+
- spec/spec_helper.rb
|
100
137
|
has_rdoc: true
|
101
138
|
homepage: http://github.com/maxkazar/pubsub
|
102
139
|
licenses:
|
@@ -113,7 +150,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
113
150
|
version: '0'
|
114
151
|
segments:
|
115
152
|
- 0
|
116
|
-
hash:
|
153
|
+
hash: -2541202216032154175
|
117
154
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
155
|
none: false
|
119
156
|
requirements:
|
data/test/helper.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler'
|
3
|
-
begin
|
4
|
-
Bundler.setup(:default, :development)
|
5
|
-
rescue Bundler::BundlerError => e
|
6
|
-
$stderr.puts e.message
|
7
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
-
exit e.status_code
|
9
|
-
end
|
10
|
-
require 'test/unit'
|
11
|
-
require 'shoulda'
|
12
|
-
|
13
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
-
require 'pubsub'
|
16
|
-
|
17
|
-
class Test::Unit::TestCase
|
18
|
-
end
|