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.
@@ -0,0 +1 @@
1
+ require 'autotest/growl'
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/Gemfile CHANGED
@@ -7,4 +7,8 @@ group :development do
7
7
  gem "bundler", "~> 1.0.0"
8
8
  gem "jeweler", "~> 1.6.4"
9
9
  gem "rcov", ">= 0"
10
+
11
+ gem "rspec"
12
+ gem "ZenTest"
13
+ gem "autotest-growl"
10
14
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.0.1
@@ -0,0 +1 @@
1
+ Autotest.add_discovery { "rspec2" }
@@ -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")
@@ -0,0 +1,12 @@
1
+ require "logger"
2
+
3
+ class Object
4
+ @@logger = nil
5
+ def logger
6
+ unless @@logger
7
+ @@logger = Logger.new(STDERR)
8
+ @@logger.level = Logger::DEBUG
9
+ end
10
+ @@logger
11
+ end
12
+ end
@@ -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
- logger.info "Subscribe #{self.class.name} to #{channel}"
7
+ mutex.synchronize do
8
+ logger.info "Subscribe #{self.class.name} to #{channel}"
7
9
 
8
- PubSub.events.listen channel, procs, &block
10
+ PubSub.events.listen channel, procs, &block
9
11
 
10
- procs_collected = []
11
- if procs.respond_to?(:each) && procs.respond_to?(:to_a)
12
- procs_collected += procs.to_a
13
- elsif procs
14
- procs_collected << procs
15
- end
16
- procs_collected << block if block
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
- channel_handlers[channel] ||= []
19
- channel_handlers[channel] += procs_collected
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
- # unsubscribe from all object channels
24
- unless channel
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
- if proc
30
- logger.info "Unsubscribe #{self.class.name} to #{channel}"
31
- PubSub.events.remove channel, proc
32
- channel_handlers[channel].delete_if {|stored_event| stored_event == proc} if channel_handlers.include? channel
33
- else
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 publish(channel, *args)
39
- logger.info "Publish #{self.class.name} to #{channel} with #{args.to_s}"
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
- channel.sub_before "/" do |sub_channel|
42
- PubSub.events.fire sub_channel, *args
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
- PubSub.events.fire "*", *args
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
@@ -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
@@ -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.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-15 00:00:00.000000000 +04:00
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: &11460780 !ruby/object:Gem::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: *11460780
25
+ version_requirements: *18948040
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: shoulda
28
- requirement: &11458140 !ruby/object:Gem::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: *11458140
36
+ version_requirements: *18946840
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: bundler
39
- requirement: &11419840 !ruby/object:Gem::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: *11419840
47
+ version_requirements: *18946080
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: jeweler
50
- requirement: &11418620 !ruby/object:Gem::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: *11418620
58
+ version_requirements: *18945200
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: rcov
61
- requirement: &11417000 !ruby/object:Gem::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: *11417000
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: &11414840 !ruby/object:Gem::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: *11414840
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
- - test/helper.rb
99
- - test/test_pubsub.rb
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: 3917047595112901718
153
+ hash: -2541202216032154175
117
154
  required_rubygems_version: !ruby/object:Gem::Requirement
118
155
  none: false
119
156
  requirements:
@@ -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
@@ -1,7 +0,0 @@
1
- require 'helper'
2
-
3
- class TestPubsub < Test::Unit::TestCase
4
- should "probably rename this file and start testing for real" do
5
- flunk "hey buddy, you should probably rename this file and start testing for real"
6
- end
7
- end