celluloid_pubsub 0.1.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 81bb4bf2f3f59d8e2cea33053a7f89efb5af637d
4
- data.tar.gz: 640efba60772877db2fdd2839b1359cc84578b19
3
+ metadata.gz: f4ee6c97f0f5d1bcda519f4670ab5b885c4751bd
4
+ data.tar.gz: a996759005640ed3bd498cb8b20c0624e078253d
5
5
  SHA512:
6
- metadata.gz: 70f8af8310490d573cbdb09b457da8695f91a7581e274e6793e0945a3f16a5021cad452f69165d874ae2714fe74d24545c775ed0a61dfaf856630700cd47bf8d
7
- data.tar.gz: d4ff8d15ddbf405e136bbc0b17f502dc6ec4843f7e1ac7170711d45f57b3484762b7ed458a89392ed9fd2c330aa2f18fdff41784e7bbd53e8968d86e4de4fe73
6
+ metadata.gz: f09f7ac3c17117442b84efe1ba90a2d739e4228152d647eba7b31ed3c7caf5888f1a04038514aaf766d9d7944c573ef25023642ad07314f532c4f973969ee64e
7
+ data.tar.gz: 4778aa4bab829487290694cf2d4bd6b5f26ae5f307e60474e4c299d43c316f644988685ddef4f8455c906abe9ddd492db1c39790a8b1a8a52f8bb50b83407e08
data/.gitignore CHANGED
@@ -11,10 +11,9 @@ spec/dummy/log/*.log
11
11
  spec/dummy/tmp/
12
12
  coverage
13
13
  tags
14
- Gemfile.lock
14
+ #Gemfile.lock
15
15
  /nbproject/
16
16
  /.git-rewrite/
17
17
  .yardoc/
18
18
  doc/
19
19
  bin/
20
- examples/log/**/*
@@ -22,6 +22,8 @@ Gem::Specification.new do |s|
22
22
  s.add_runtime_dependency 'http', '~> 0.9.8', '>= 0.9.8' # TODO: remove this once fixed in reel gem ( waiting for version 0.6.0 of reel to be stable)
23
23
  s.add_runtime_dependency 'celluloid-websocket-client', '~> 0.0', '>= 0.0.1'
24
24
  s.add_runtime_dependency 'activesupport', '~> 4.1', '>= 4.1.0'
25
+ s.add_runtime_dependency 'em-hiredis', '~> 0.3', '>= 0.3.0'
26
+ s.add_runtime_dependency 'json', '~> 1.8', '>= 1.8.3'
25
27
 
26
28
  s.add_development_dependency 'rspec-rails', '~> 3.3', '>= 3.3'
27
29
  s.add_development_dependency 'guard', '~> 2.13', '>= 2.13'
@@ -0,0 +1,2 @@
1
+ $use_redis = true
2
+ require_relative './shared_classes'
@@ -0,0 +1,92 @@
1
+ require 'bundler/setup'
2
+ require 'celluloid_pubsub'
3
+ require 'logger'
4
+
5
+ debug_enabled = ENV['DEBUG'].present? && ENV['DEBUG'].to_s == 'true'
6
+
7
+ if debug_enabled == true
8
+ log_file_path = File.join(File.expand_path(File.dirname(__FILE__)), 'log', 'celluloid_pubsub.log')
9
+ puts log_file_path
10
+ FileUtils.mkdir_p(File.dirname(log_file_path))
11
+ log_file = File.open(log_file_path, 'w')
12
+ log_file.sync = true
13
+ Celluloid.logger = ::Logger.new(log_file_path)
14
+ Celluloid.task_class = Celluloid::TaskThread
15
+ Celluloid.exception_handler do |ex|
16
+ unless ex.is_a?(Interrupt)
17
+ puts ex
18
+ end
19
+ end
20
+ end
21
+
22
+ # actor that subscribes to a channel
23
+ class Subscriber
24
+ include Celluloid
25
+ include Celluloid::Logger
26
+ finalizer :shutdown
27
+
28
+ def initialize(options = {})
29
+ @client = CelluloidPubsub::Client.new({ actor: Actor.current, channel: 'test_channel' }.merge(options))
30
+ end
31
+
32
+ def on_message(message)
33
+ if @client.succesfull_subscription?(message)
34
+ puts "subscriber got successful subscription #{message.inspect}"
35
+ @client.publish('test_channel2', 'data' => ' subscriber got successfull subscription') # the message needs to be a Hash
36
+ else
37
+ puts "subscriber got message #{message.inspect}"
38
+ @client.unsubscribe('test_channel')
39
+ end
40
+ end
41
+
42
+ def on_close(code, reason)
43
+ puts "websocket connection closed: #{code.inspect}, #{reason.inspect}"
44
+ terminate
45
+ end
46
+ def shutdown
47
+ debug "#{self.class} tries to 'shudown'"
48
+ terminate
49
+ end
50
+ end
51
+
52
+ # actor that publishes a message in a channel
53
+ class Publisher
54
+ include Celluloid
55
+ include Celluloid::Logger
56
+ finalizer :shutdown
57
+
58
+ def initialize(options = {})
59
+ @client = CelluloidPubsub::Client.new({ actor: Actor.current, channel: 'test_channel2' }.merge(options))
60
+ end
61
+
62
+ def on_message(message)
63
+ puts " publisher got #{message.inspect}"
64
+ @client.publish('test_channel', 'data' => 'my_message') # the message needs to be a Hash
65
+ @client.unsubscribe('test_channel2')
66
+ end
67
+
68
+ def on_close(code, reason)
69
+ puts "websocket connection closed: #{code.inspect}, #{reason.inspect}"
70
+ terminate
71
+ end
72
+ def shutdown
73
+ debug "#{self.class} tries to 'shudown'"
74
+ terminate
75
+ end
76
+ end
77
+
78
+ CelluloidPubsub::WebServer.supervise_as(:web_server, enable_debug: debug_enabled, use_redis: $use_redis)
79
+ Subscriber.supervise_as(:subscriber, enable_debug: debug_enabled)
80
+ Publisher.supervise_as(:publisher, enable_debug: debug_enabled)
81
+ signal_received = false
82
+
83
+ at_exit do
84
+ Celluloid.shutdown
85
+ end
86
+ Signal.trap('INT') do
87
+ puts "\nAn interrupt signal is happening!"
88
+ signal_received = true
89
+ end
90
+
91
+ sleep 0.1 until signal_received
92
+ puts 'Exited succesfully! =)'
@@ -1,65 +1,2 @@
1
- require 'bundler/setup'
2
- require 'celluloid_pubsub'
3
- require 'logger'
4
-
5
- debug_enabled = ENV['DEBUG'].present? && ENV['DEBUG'].to_s == 'true'
6
-
7
- if debug_enabled == true
8
- log_file_path = File.join(File.expand_path(File.dirname(__FILE__)), 'log', 'celluloid_pubsub.log')
9
- puts log_file_path
10
- FileUtils.mkdir_p(File.dirname(log_file_path))
11
- log_file = File.open(log_file_path, 'w')
12
- log_file.sync = true
13
- Celluloid.logger = ::Logger.new(log_file_path)
14
- end
15
-
16
- # actor that subscribes to a channel
17
- class Subscriber
18
- include Celluloid
19
- include Celluloid::Logger
20
-
21
- def initialize(options = {})
22
- @client = CelluloidPubsub::Client.new({ actor: Actor.current, channel: 'test_channel' }.merge(options))
23
- end
24
-
25
- def on_message(message)
26
- if @client.succesfull_subscription?(message)
27
- puts "subscriber got successful subscription #{message.inspect}"
28
- @client.publish('test_channel2', 'data' => ' subscriber got successfull subscription') # the message needs to be a Hash
29
- else
30
- puts "subscriber got message #{message.inspect}"
31
- @client.unsubscribe('test_channel')
32
- end
33
- end
34
-
35
- def on_close(code, reason)
36
- puts "websocket connection closed: #{code.inspect}, #{reason.inspect}"
37
- terminate
38
- end
39
- end
40
-
41
- # actor that publishes a message in a channel
42
- class Publisher
43
- include Celluloid
44
- include Celluloid::Logger
45
-
46
- def initialize(options = {})
47
- @client = CelluloidPubsub::Client.new({ actor: Actor.current, channel: 'test_channel2' }.merge(options))
48
- @client.publish('test_channel', 'data' => 'my_message') # the message needs to be a Hash
49
- end
50
-
51
- def on_message(message)
52
- puts " publisher got #{message.inspect}"
53
- @client.unsubscribe('test_channel2')
54
- end
55
-
56
- def on_close(code, reason)
57
- puts "websocket connection closed: #{code.inspect}, #{reason.inspect}"
58
- terminate
59
- end
60
- end
61
-
62
- CelluloidPubsub::WebServer.supervise_as(:web_server, enable_debug: debug_enabled)
63
- Subscriber.supervise_as(:subscriber, enable_debug: debug_enabled)
64
- Publisher.supervise_as(:publisher, enable_debug: debug_enabled)
65
- sleep
1
+ $use_redis = false
2
+ require_relative './shared_classes'
@@ -3,4 +3,5 @@ require 'celluloid/io'
3
3
  require 'reel'
4
4
  require 'celluloid/websocket/client'
5
5
  require 'active_support/all'
6
+ require 'json'
6
7
  Gem.find_files('celluloid_pubsub/**/*.rb').each { |path| require path }
@@ -27,7 +27,7 @@ module CelluloidPubsub
27
27
  include Celluloid
28
28
  include Celluloid::Logger
29
29
  attr_accessor :actor, :client, :options, :hostname, :port, :path, :channel
30
-
30
+ finalizer :shutdown
31
31
  # receives a list of options that are used to connect to the webserver and an actor to which the callbacks are delegated to
32
32
  # when receiving messages from a channel
33
33
  #
@@ -46,7 +46,20 @@ module CelluloidPubsub
46
46
  parse_options(options)
47
47
  raise "#{self}: Please provide an actor in the options list!!!" if @actor.blank?
48
48
  raise "#{self}: Please provide an channel in the options list!!!" if @channel.blank?
49
+ @actor.link Actor.current if @actor.respond_to?(:link)
49
50
  @client = Celluloid::WebSocket::Client.new("ws://#{@hostname}:#{@port}#{@path}", Actor.current)
51
+ Actor.current.link @client
52
+ end
53
+
54
+ # the method will terminate the current actor
55
+ #
56
+ #
57
+ # @return [void]
58
+ #
59
+ # @api public
60
+ def shutdown
61
+ debug "#{self.class} tries to 'shudown'" if debug_enabled?
62
+ terminate
50
63
  end
51
64
 
52
65
  # check the options list for values and sets default values if not found
@@ -88,9 +101,8 @@ module CelluloidPubsub
88
101
  #
89
102
  # @api public
90
103
  def subscribe(channel)
91
- subscription_data = { 'client_action' => 'subscribe', 'channel' => channel }
92
- debug("#{self.class} tries to subscribe #{subscription_data}") if debug_enabled?
93
- async.chat(subscription_data)
104
+ debug("#{@actor.class} tries to subscribe to channel #{channel}") if debug_enabled?
105
+ async.send_action('subscribe', channel)
94
106
  end
95
107
 
96
108
  # checks if the message has the successfull subscription action
@@ -153,7 +165,7 @@ module CelluloidPubsub
153
165
  #
154
166
  # @api public
155
167
  def on_open
156
- debug("#{self.class} websocket connection opened") if debug_enabled?
168
+ debug("#{@actor.class} websocket connection opened") if debug_enabled?
157
169
  async.subscribe(@channel)
158
170
  end
159
171
 
@@ -167,9 +179,9 @@ module CelluloidPubsub
167
179
  #
168
180
  # @api public
169
181
  def on_message(data)
170
- debug("#{self.class} received plain #{data}") if debug_enabled?
182
+ debug("#{@actor.class} received plain #{data}") if debug_enabled?
171
183
  message = JSON.parse(data)
172
- debug("#{self.class} received JSON #{message}") if debug_enabled?
184
+ debug("#{@actor.class} received JSON #{message}") if debug_enabled?
173
185
  @actor.async.on_message(message)
174
186
  end
175
187
 
@@ -185,7 +197,7 @@ module CelluloidPubsub
185
197
  def on_close(code, reason)
186
198
  @client.terminate
187
199
  terminate
188
- debug("#{self.class} dispatching on close #{code} #{reason}") if debug_enabled?
200
+ debug("#{@actor.class} dispatching on close #{code} #{reason}") if debug_enabled?
189
201
  @actor.async.on_close(code, reason)
190
202
  end
191
203
 
@@ -204,7 +216,6 @@ module CelluloidPubsub
204
216
  publishing_data = { 'client_action' => action }
205
217
  publishing_data = publishing_data.merge('channel' => channel) if channel.present?
206
218
  publishing_data = publishing_data.merge('data' => data) if data.present?
207
- debug(" #{self.class} sends: #{publishing_data}") if debug_enabled?
208
219
  async.chat(publishing_data)
209
220
  end
210
221
 
@@ -221,10 +232,10 @@ module CelluloidPubsub
221
232
  final_message = nil
222
233
  if message.is_a?(Hash)
223
234
  final_message = message.to_json
224
- debug("#{self.class} sends #{message.to_json}") if debug_enabled?
235
+ debug("#{@actor.class} sends #{message.to_json}") if debug_enabled?
225
236
  else
226
237
  final_message = JSON.dump(action: 'message', message: message)
227
- debug("#{self.class} sends JSON #{final_message}") if debug_enabled?
238
+ debug("#{@actor.class} sends JSON #{final_message}") if debug_enabled?
228
239
  end
229
240
  @client.text final_message
230
241
  end
@@ -18,7 +18,7 @@ module CelluloidPubsub
18
18
  include Celluloid::Logger
19
19
 
20
20
  attr_accessor :websocket, :server, :channels
21
-
21
+ finalizer :shutdown
22
22
  # rececives a new socket connection from the server
23
23
  # and listens for messages
24
24
  #
@@ -31,7 +31,7 @@ module CelluloidPubsub
31
31
  @server = server
32
32
  @channels = []
33
33
  @websocket = websocket
34
- info "Streaming changes for #{websocket.url}" if @server.debug_enabled?
34
+ info "#{self.class} Streaming changes for #{websocket.url}" if @server.debug_enabled?
35
35
  async.run
36
36
  end
37
37
 
@@ -63,7 +63,7 @@ module CelluloidPubsub
63
63
  begin
64
64
  message = @websocket.read
65
65
  rescue => e
66
- debug(e) if @server.debug_enabled?
66
+ debug(e)
67
67
  end
68
68
  message
69
69
  end
@@ -78,12 +78,12 @@ module CelluloidPubsub
78
78
  #
79
79
  # @api public
80
80
  def parse_json_data(message)
81
- debug "Reactor read message #{message}" if @server.debug_enabled?
81
+ debug "#{self.class} read message #{message}" if @server.debug_enabled?
82
82
  json_data = nil
83
83
  begin
84
84
  json_data = JSON.parse(message)
85
85
  rescue => e
86
- debug "Reactor could not parse #{message} because of #{e.inspect}" if @server.debug_enabled?
86
+ debug "#{self.class} could not parse #{message} because of #{e.inspect}" if @server.debug_enabled?
87
87
  # do nothing
88
88
  end
89
89
  json_data = message if json_data.nil?
@@ -124,7 +124,7 @@ module CelluloidPubsub
124
124
  def handle_parsed_websocket_message(json_data)
125
125
  if json_data.is_a?(Hash)
126
126
  json_data = json_data.stringify_keys
127
- debug "Reactor finds actions for #{json_data}" if @server.debug_enabled?
127
+ debug "#{self.class} finds actions for #{json_data}" if @server.debug_enabled?
128
128
  delegate_action(json_data) if json_data['client_action'].present?
129
129
  else
130
130
  handle_unknown_action(json_data)
@@ -154,18 +154,18 @@ module CelluloidPubsub
154
154
  # @api public
155
155
  def delegate_action(json_data)
156
156
  case json_data['client_action']
157
- when 'unsubscribe_all'
158
- unsubscribe_all
159
- when 'unsubscribe_clients'
160
- async.unsubscribe_clients(json_data['channel'])
161
- when 'unsubscribe'
162
- async.unsubscribe(json_data['channel'])
163
- when 'subscribe'
164
- async.start_subscriber(json_data['channel'], json_data)
165
- when 'publish'
166
- @server.publish_event(json_data['channel'], json_data['data'].to_json)
167
- else
168
- handle_unknown_action(json_data)
157
+ when 'unsubscribe_all'
158
+ unsubscribe_all
159
+ when 'unsubscribe_clients'
160
+ async.unsubscribe_clients(json_data['channel'])
161
+ when 'unsubscribe'
162
+ async.unsubscribe(json_data['channel'])
163
+ when 'subscribe'
164
+ async.start_subscriber(json_data['channel'], json_data)
165
+ when 'publish'
166
+ @server.publish_event(json_data['channel'], json_data['data'].to_json)
167
+ else
168
+ handle_unknown_action(json_data)
169
169
  end
170
170
  end
171
171
 
@@ -191,6 +191,7 @@ module CelluloidPubsub
191
191
  #
192
192
  # @api public
193
193
  def unsubscribe(channel)
194
+ debug "#{self.class} runs 'unsubscribe' method with #{channel}" if @server.debug_enabled?
194
195
  return unless channel.present?
195
196
  @channels.delete(channel) unless @channels.blank?
196
197
  @websocket.close if @channels.blank?
@@ -207,6 +208,7 @@ module CelluloidPubsub
207
208
  #
208
209
  # @api public
209
210
  def unsubscribe_clients(channel)
211
+ debug "#{self.class} runs 'unsubscribe_clients' method with #{channel}" if @server.debug_enabled?
210
212
  return if channel.blank? || @server.subscribers[channel].blank?
211
213
  unsubscribe_from_channel(channel)
212
214
  @server.subscribers[channel] = []
@@ -219,6 +221,7 @@ module CelluloidPubsub
219
221
  #
220
222
  # @api public
221
223
  def shutdown
224
+ debug "#{self.class} tries to 'shudown'"
222
225
  terminate
223
226
  end
224
227
 
@@ -236,8 +239,8 @@ module CelluloidPubsub
236
239
  def start_subscriber(channel, message)
237
240
  return unless channel.present?
238
241
  add_subscriber_to_channel(channel, message)
239
- debug "Subscribed to #{channel} with #{message}" if @server.debug_enabled?
240
- @websocket << message.merge('client_action' => 'successful_subscription', 'channel' => channel).to_json
242
+ debug "#{self.class} subscribed to #{channel} with #{message}" if @server.debug_enabled?
243
+ @websocket << message.merge('client_action' => 'successful_subscription', 'channel' => channel).to_json unless @server.redis_enabled?
241
244
  end
242
245
 
243
246
  # adds the curent actor the list of the subscribers for a particular channel
@@ -254,6 +257,7 @@ module CelluloidPubsub
254
257
  CelluloidPubsub::Registry.channels << channel unless CelluloidPubsub::Registry.channels.include?(channel)
255
258
  @server.subscribers[channel] ||= []
256
259
  @server.subscribers[channel] << { reactor: Actor.current, message: message }
260
+
257
261
  end
258
262
 
259
263
  # unsubscribes all actors from all channels and terminates the curent actor
@@ -262,6 +266,7 @@ module CelluloidPubsub
262
266
  #
263
267
  # @api public
264
268
  def unsubscribe_all
269
+ debug "#{self.class} runs 'unsubscribe_all' method" if @server.debug_enabled?
265
270
  CelluloidPubsub::Registry.channels.map do |channel|
266
271
  unsubscribe_from_channel(channel)
267
272
  @server.subscribers[channel] = []
@@ -278,6 +283,8 @@ module CelluloidPubsub
278
283
  #
279
284
  # @api public
280
285
  def unsubscribe_from_channel(channel)
286
+ debug "#{self.class} runs 'unsubscribe_from_channel' method with #{channel}" if @server.debug_enabled?
287
+ return if @server.subscribers[channel].blank?
281
288
  @server.subscribers[channel].each do |hash|
282
289
  hash[:reactor].websocket.close
283
290
  Celluloid::Actor.kill(hash[:reactor])
@@ -0,0 +1,25 @@
1
+ module CelluloidPubsub
2
+ class Redis
3
+ class << self
4
+ @connected ||= false
5
+ attr_accessor :connected, :connection
6
+
7
+ alias_method :connected?, :connected
8
+
9
+ def connect(_options = {})
10
+ require 'eventmachine'
11
+ require 'em-hiredis'
12
+ EM.run do
13
+ @connection = EM::Hiredis.connect
14
+ @connected = true
15
+ yield @connection if block_given?
16
+ end
17
+ EM.error_handler do |error|
18
+ unless error.is_a?(Interrupt)
19
+ puts error.inspect
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,78 @@
1
+ require_relative './reactor'
2
+ module CelluloidPubsub
3
+ class RedisReactor < CelluloidPubsub::Reactor
4
+ include Celluloid
5
+ include Celluloid::IO
6
+ include Celluloid::Logger
7
+
8
+ def unsubscribe(channel)
9
+ super
10
+ async.redis_action('unsubscribe', channel)
11
+ end
12
+
13
+ def add_subscriber_to_channel(channel, message)
14
+ super
15
+ async.redis_action('subscribe', channel, message)
16
+ end
17
+
18
+ def unsubscribe_from_channel(channel)
19
+ super
20
+ async.redis_action('unsubscribe', channel)
21
+ end
22
+
23
+
24
+ def unsubscribe_all
25
+ CelluloidPubsub::Registry.channels.map do |channel|
26
+ async.redis_action('unsubscribe', channel)
27
+ end
28
+ info 'clearing connections'
29
+ shutdown
30
+ end
31
+
32
+ def shutdown
33
+ @channels.each do |channel|
34
+ redis_action('unsubscribe', channel)
35
+ end
36
+ super
37
+ end
38
+
39
+ private
40
+
41
+ def redis_action(action, channel = nil, message = {})
42
+ CelluloidPubsub::Redis.connect do |connection|
43
+ pubsub = connection.pubsub
44
+ pubsub.on(:unsubscribe) { |channel, remaining_subscriptions|
45
+ debug [:unsubscribe_happened, channel, remaining_subscriptions].inspect if @server.debug_enabled?
46
+ }
47
+
48
+ if action == 'subscribe' && channel.present?
49
+ subscription = pubsub.subscribe(channel) {|subscribed_message|
50
+ @websocket << subscribed_message
51
+ }
52
+ subscription.callback { |reply|
53
+ @websocket << message.merge('client_action' => 'successful_subscription', 'channel' => channel, 'subscriptions' => reply).to_json
54
+ }
55
+ subscription.errback {|reply|
56
+ debug "subscription error #{reply.inspect}" if @server.debug_enabled?
57
+ }
58
+ else
59
+ if channel.present?
60
+ unsubscription = pubsub.unsubscribe(channel)
61
+ unsubscription.callback {|reply|
62
+ debug "unsubscription success #{reply.inspect}" if @server.debug_enabled?
63
+ }
64
+ unsubscription.errback {|reply|
65
+ debug "unsubscription error #{reply.inspect}" if @server.debug_enabled?
66
+ }
67
+ else
68
+ connection.unsubscribe
69
+ end
70
+
71
+ end
72
+
73
+
74
+ end
75
+ end
76
+
77
+ end
78
+ end
@@ -15,7 +15,7 @@ module CelluloidPubsub
15
15
  # major release version
16
16
  MAJOR = 0
17
17
  # minor release version
18
- MINOR = 1
18
+ MINOR = 2
19
19
  # tiny release version
20
20
  TINY = 0
21
21
  # prelease version ( set this only if it is a prelease)
@@ -38,8 +38,8 @@ module CelluloidPubsub
38
38
  # The request path that the webserver accepts by default
39
39
  PATH = '/ws'
40
40
 
41
- attr_accessor :options, :subscribers, :backlog, :hostname, :port, :path, :spy
42
-
41
+ attr_accessor :options, :subscribers, :backlog, :hostname, :port, :path, :spy, :use_redis, :debug_enabled
42
+ finalizer :shutdown
43
43
  # receives a list of options that are used to configure the webserver
44
44
  #
45
45
  # @param [Hash] options the options that can be used to connect to webser and send additional data
@@ -54,11 +54,24 @@ module CelluloidPubsub
54
54
  #
55
55
  # :nocov:
56
56
  def initialize(options = {})
57
+ options = options.is_a?(Array) ? options.first : options
57
58
  parse_options(options)
58
59
  @subscribers = {}
59
60
  info "CelluloidPubsub::WebServer example starting on #{@hostname}:#{@port}" if debug_enabled?
60
61
  super(@hostname, @port, { spy: @spy, backlog: @backlog }, &method(:on_connection))
61
62
  end
63
+
64
+ # the method will terminate the current actor
65
+ #
66
+ #
67
+ # @return [void]
68
+ #
69
+ # @api public
70
+ def shutdown
71
+ debug "#{self.class} tries to 'shudown'"
72
+ terminate
73
+ end
74
+
62
75
  # :nocov:
63
76
 
64
77
  # receives a list of options that are used to configure the webserver
@@ -74,7 +87,7 @@ module CelluloidPubsub
74
87
  #
75
88
  # @api public
76
89
  def parse_options(options)
77
- raise 'Options is not a hash ' unless options.is_a?(Hash)
90
+ options = options.is_a?(Hash) ? options : {}
78
91
  @options = options.stringify_keys
79
92
  debug @options if debug_enabled?
80
93
  @backlog = @options.fetch('backlog', 1024)
@@ -82,6 +95,8 @@ module CelluloidPubsub
82
95
  @port = @options.fetch('port', CelluloidPubsub::WebServer::PORT)
83
96
  @path = @options.fetch('path', CelluloidPubsub::WebServer::PATH)
84
97
  @spy = @options.fetch('spy', false)
98
+ @use_redis = @options.fetch('use_redis', false)
99
+ @debug_enabled = @options.fetch('enable_debug', false)
85
100
  end
86
101
 
87
102
  # checks if debug is enabled
@@ -90,7 +105,11 @@ module CelluloidPubsub
90
105
  #
91
106
  # @api public
92
107
  def debug_enabled?
93
- @options.fetch('enable_debug', false).to_s == 'true'
108
+ @debug_enabled.to_s == 'true'
109
+ end
110
+
111
+ def redis_enabled?
112
+ @use_redis.to_s.downcase == 'true'
94
113
  end
95
114
 
96
115
  # method for publishing data to a channel
@@ -102,14 +121,16 @@ module CelluloidPubsub
102
121
  #
103
122
  # @api public
104
123
  def publish_event(current_topic, message)
105
- return if current_topic.blank? || message.blank? || @subscribers[current_topic].blank?
106
- begin
124
+ return if current_topic.blank? || message.blank?
125
+ if redis_enabled?
126
+ CelluloidPubsub::Redis.connection.publish(current_topic, message)
127
+ elsif @subscribers[current_topic].present?
107
128
  @subscribers[current_topic].each do |hash|
108
129
  hash[:reactor].websocket << message
109
130
  end
110
- rescue => e
111
- debug("could not publish message #{message} into topic #{current_topic} because of #{e.inspect}") if debug_enabled?
112
131
  end
132
+ rescue => e
133
+ debug("could not publish message #{message} into topic #{current_topic} because of #{e.inspect}") if debug_enabled?
113
134
  end
114
135
 
115
136
  # callback that will execute when receiving new conections
@@ -128,7 +149,7 @@ module CelluloidPubsub
128
149
  def on_connection(connection)
129
150
  while request = connection.request
130
151
  if request.websocket?
131
- info 'Received a WebSocket connection' if debug_enabled?
152
+ info "#{self.class} Received a WebSocket connection" if debug_enabled?
132
153
 
133
154
  # We're going to hand off this connection to another actor (Writer/Reader)
134
155
  # However, initially Reel::Connections are "attached" to the
@@ -171,8 +192,8 @@ module CelluloidPubsub
171
192
  # @api public
172
193
  def route_websocket(socket)
173
194
  if socket.url == @path
174
- info 'Reactor handles new socket connection' if debug_enabled?
175
- reactor = CelluloidPubsub::Reactor.new
195
+ reactor = redis_enabled? ? CelluloidPubsub::RedisReactor.new : CelluloidPubsub::Reactor.new
196
+ info "#{reactor.class} handles new socket connection" if debug_enabled?
176
197
  Actor.current.link reactor
177
198
  reactor.async.work(socket, Actor.current)
178
199
  else
@@ -191,7 +212,7 @@ module CelluloidPubsub
191
212
  #
192
213
  # @api public
193
214
  def handle_dispatched_message(reactor, data)
194
- debug "Webserver trying to dispatch message #{data.inspect}" if debug_enabled?
215
+ debug "#{self.class} trying to dispatch message #{data.inspect}" if debug_enabled?
195
216
  message = reactor.parse_json_data(data)
196
217
  if message.present? && message.is_a?(Hash)
197
218
  reactor.websocket << message.to_json
@@ -199,5 +220,6 @@ module CelluloidPubsub
199
220
  reactor.websocket << data.to_json
200
221
  end
201
222
  end
223
+
202
224
  end
203
225
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: celluloid_pubsub
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - bogdanRada
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-28 00:00:00.000000000 Z
11
+ date: 2015-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: celluloid
@@ -130,6 +130,46 @@ dependencies:
130
130
  - - ">="
131
131
  - !ruby/object:Gem::Version
132
132
  version: 4.1.0
133
+ - !ruby/object:Gem::Dependency
134
+ name: em-hiredis
135
+ requirement: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - "~>"
138
+ - !ruby/object:Gem::Version
139
+ version: '0.3'
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: 0.3.0
143
+ type: :runtime
144
+ prerelease: false
145
+ version_requirements: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - "~>"
148
+ - !ruby/object:Gem::Version
149
+ version: '0.3'
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: 0.3.0
153
+ - !ruby/object:Gem::Dependency
154
+ name: json
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '1.8'
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: 1.8.3
163
+ type: :runtime
164
+ prerelease: false
165
+ version_requirements: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - "~>"
168
+ - !ruby/object:Gem::Version
169
+ version: '1.8'
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: 1.8.3
133
173
  - !ruby/object:Gem::Dependency
134
174
  name: rspec-rails
135
175
  requirement: !ruby/object:Gem::Requirement
@@ -470,11 +510,15 @@ files:
470
510
  - README.md
471
511
  - Rakefile
472
512
  - celluloid_pubsub.gemspec
513
+ - examples/redis_test.rb
514
+ - examples/shared_classes.rb
473
515
  - examples/simple_test.rb
474
516
  - init.rb
475
517
  - lib/celluloid_pubsub.rb
476
- - lib/celluloid_pubsub/client_pubsub.rb
518
+ - lib/celluloid_pubsub/client.rb
477
519
  - lib/celluloid_pubsub/reactor.rb
520
+ - lib/celluloid_pubsub/redis.rb
521
+ - lib/celluloid_pubsub/redis_reactor.rb
478
522
  - lib/celluloid_pubsub/registry.rb
479
523
  - lib/celluloid_pubsub/version.rb
480
524
  - lib/celluloid_pubsub/web_server.rb