celluloid_pubsub 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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