celluloid_pubsub 0.2.0 → 0.3.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: f4ee6c97f0f5d1bcda519f4670ab5b885c4751bd
4
- data.tar.gz: a996759005640ed3bd498cb8b20c0624e078253d
3
+ metadata.gz: 6aad68d75f135124f475c703d0950b1bc0b45e2c
4
+ data.tar.gz: 5e47b790b66d01dc32af3313ec54bb7ba09c8208
5
5
  SHA512:
6
- metadata.gz: f09f7ac3c17117442b84efe1ba90a2d739e4228152d647eba7b31ed3c7caf5888f1a04038514aaf766d9d7944c573ef25023642ad07314f532c4f973969ee64e
7
- data.tar.gz: 4778aa4bab829487290694cf2d4bd6b5f26ae5f307e60474e4c299d43c316f644988685ddef4f8455c906abe9ddd492db1c39790a8b1a8a52f8bb50b83407e08
6
+ metadata.gz: c33c34fab870f68825fd75b42917b556880172b7dbb64108f64a94ed1fcd067980e984715be8118d936fbdb999b105d03c8aa85c1bd26efe2093caa9f56f73bc
7
+ data.tar.gz: 885da36eee95bce09adb0c7e6644d8a53691c87b622355de60b9d94b98757ee14a87360ca48812ed757836e29762cf095c4bdec6585602cae58951e0a41badde
data/.reek ADDED
@@ -0,0 +1,11 @@
1
+ ---
2
+ Attribute:
3
+ enabled: false
4
+ TooManyInstanceVariables:
5
+ enabled: false
6
+ TooManyMethods:
7
+ enabled: false
8
+ UtilityFunction:
9
+ enabled: false
10
+ exclude_paths:
11
+ - examples
data/.rubocop.yml CHANGED
@@ -4,7 +4,11 @@ AllCops:
4
4
  - bin/**/*
5
5
  - Guardfile
6
6
  - vendor/**/*
7
+ - examples/**/*
7
8
 
9
+ ClassLength:
10
+ Max: 500
11
+
8
12
  Documentation:
9
13
  Enabled: true
10
14
 
data/Rakefile CHANGED
@@ -10,13 +10,6 @@ RSpec::Core::RakeTask.new(:spec) do |spec|
10
10
  spec.rspec_opts = ['--backtrace', '--fail-fast'] if ENV['DEBUG']
11
11
  end
12
12
 
13
- # desc "Prepare dummy application"
14
- # task :prepare do
15
- # ENV["RAILS_ENV"] ||= 'test'
16
- # require File.expand_path("./spec/dummy/config/environment", File.dirname(__FILE__))
17
- # Dummy::Application.load_tasks
18
- # Rake::Task["db:test:prepare"].invoke
19
- # end
20
13
  YARD::Config.options[:load_plugins] = true
21
14
  YARD::Config.load_plugins
22
15
 
@@ -26,31 +19,18 @@ YARD::Rake::YardocTask.new do |t|
26
19
  t.stats_options = ['--list-undoc'] # optional
27
20
  end
28
21
 
29
- unless ENV['TRAVIS']
30
- require 'rvm-tester'
31
- RVM::Tester::TesterTask.new(:suite) do |t|
32
- t.rubies = %w(1.9.3 2.0.0 2.1.0) # which versions to test (required!)
33
- t.bundle_install = true # updates Gemfile.lock, default is true
34
- t.use_travis = true # looks for Rubies in .travis.yml (on by default)
35
- t.command = 'bundle exec rake' # runs plain "rake" by default
36
- t.env = { 'VERBOSE' => '1', 'RAILS_ENV' => 'test', 'RACK_ENV' => 'test' } # set any ENV vars
37
- t.num_workers = 5 # defaults to 3
38
- t.verbose = true # shows more output, off by default
39
- end
40
- end
41
-
42
22
  desc 'Default: run the unit tests.'
43
23
  task default: [:all]
44
24
 
45
25
  desc 'Test the plugin under all supported Rails versions.'
46
26
  task :all do |_t|
47
27
  if ENV['TRAVIS']
48
- exec(' bundle exec phare && bundle exec rake spec && bundle exec rake coveralls:push')
28
+ exec(' bundle exec rubocop . && bundle exec rake spec && bundle exec rake coveralls:push')
49
29
  else
50
- exec('bundle exec rubocop -a . && bundle exec phare && bundle exec rake spec')
30
+ exec('bundle exec rubocop -a . && bundle exec reek . && bundle exec rake spec')
51
31
  end
52
32
  end
53
33
 
54
34
  task :docs do
55
- exec(' bundle exec rubocop -a . && bundle exec phare && bundle exec inch --pedantic && bundle exec yard')
35
+ exec(' bundle exec rubocop -a . && bundle exec reek . && bundle exec inch --pedantic && bundle exec yard')
56
36
  end
@@ -26,20 +26,16 @@ Gem::Specification.new do |s|
26
26
  s.add_runtime_dependency 'json', '~> 1.8', '>= 1.8.3'
27
27
 
28
28
  s.add_development_dependency 'rspec-rails', '~> 3.3', '>= 3.3'
29
- s.add_development_dependency 'guard', '~> 2.13', '>= 2.13'
30
- s.add_development_dependency 'guard-rspec', '~> 4.6', '>= 4.6'
31
29
  s.add_development_dependency 'simplecov', '~> 0.10', '>= 0.10'
32
30
  s.add_development_dependency 'simplecov-summary', '~> 0.0.4', '>= 0.0.4'
33
31
  s.add_development_dependency 'mocha', '~> 1.1', '>= 1.1'
34
32
  s.add_development_dependency 'coveralls', '~> 0.7', '>= 0.7'
35
- s.add_development_dependency 'rvm-tester', '~> 1.1', '>= 1.1'
36
33
 
37
34
  s.add_development_dependency 'rubocop', '~> 0.33', '>= 0.33'
38
- s.add_development_dependency 'phare', '~> 0.7', '>= 0.7'
35
+ s.add_development_dependency 'reek', '~> 3.8', '>= 3.8.1'
39
36
  s.add_development_dependency 'yard', '~> 0.8', '>= 0.8.7'
40
37
  s.add_development_dependency 'yard-rspec', '~> 0.1', '>= 0.1'
41
38
  s.add_development_dependency 'redcarpet', '~> 3.3', '>= 3.3'
42
39
  s.add_development_dependency 'github-markup', '~> 1.3', '>= 1.3.3'
43
40
  s.add_development_dependency 'inch', '~> 0.6', '>= 0.6'
44
- s.add_development_dependency 'guard-inch', '~> 0.1', '>= 0.1.0'
45
41
  end
@@ -1,2 +1,2 @@
1
- $use_redis = true
1
+ ENV['USE_REDIS'] = 'true'
2
2
  require_relative './shared_classes'
@@ -3,27 +3,14 @@ require 'celluloid_pubsub'
3
3
  require 'logger'
4
4
 
5
5
  debug_enabled = ENV['DEBUG'].present? && ENV['DEBUG'].to_s == 'true'
6
+ use_redis = ENV['USE_REDIS'].present? && ENV['USE_REDIS'].to_s == 'true'
7
+ log_file_path = File.join(File.expand_path(File.dirname(__FILE__)), 'log', 'celluloid_pubsub.log')
6
8
 
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
9
 
22
10
  # actor that subscribes to a channel
23
11
  class Subscriber
24
12
  include Celluloid
25
13
  include Celluloid::Logger
26
- finalizer :shutdown
27
14
 
28
15
  def initialize(options = {})
29
16
  @client = CelluloidPubsub::Client.new({ actor: Actor.current, channel: 'test_channel' }.merge(options))
@@ -35,7 +22,6 @@ class Subscriber
35
22
  @client.publish('test_channel2', 'data' => ' subscriber got successfull subscription') # the message needs to be a Hash
36
23
  else
37
24
  puts "subscriber got message #{message.inspect}"
38
- @client.unsubscribe('test_channel')
39
25
  end
40
26
  end
41
27
 
@@ -43,48 +29,43 @@ class Subscriber
43
29
  puts "websocket connection closed: #{code.inspect}, #{reason.inspect}"
44
30
  terminate
45
31
  end
46
- def shutdown
47
- debug "#{self.class} tries to 'shudown'"
48
- terminate
49
- end
32
+
33
+
50
34
  end
51
35
 
52
36
  # actor that publishes a message in a channel
53
37
  class Publisher
54
38
  include Celluloid
55
39
  include Celluloid::Logger
56
- finalizer :shutdown
57
40
 
58
41
  def initialize(options = {})
59
42
  @client = CelluloidPubsub::Client.new({ actor: Actor.current, channel: 'test_channel2' }.merge(options))
60
43
  end
61
44
 
62
45
  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')
46
+ if @client.succesfull_subscription?(message)
47
+ puts "publisher got successful subscription #{message.inspect}"
48
+ @client.publish('test_channel', 'data' => ' my_message') # the message needs to be a Hash
49
+ else
50
+ puts "publisher got message #{message.inspect}"
51
+ end
66
52
  end
67
53
 
68
54
  def on_close(code, reason)
69
55
  puts "websocket connection closed: #{code.inspect}, #{reason.inspect}"
70
56
  terminate
71
57
  end
72
- def shutdown
73
- debug "#{self.class} tries to 'shudown'"
74
- terminate
75
- end
58
+
76
59
  end
77
60
 
78
- CelluloidPubsub::WebServer.supervise_as(:web_server, enable_debug: debug_enabled, use_redis: $use_redis)
61
+
62
+ CelluloidPubsub::WebServer.supervise_as(:web_server, enable_debug: debug_enabled, use_redis: use_redis,log_file_path: log_file_path )
79
63
  Subscriber.supervise_as(:subscriber, enable_debug: debug_enabled)
80
64
  Publisher.supervise_as(:publisher, enable_debug: debug_enabled)
81
65
  signal_received = false
82
66
 
83
- at_exit do
84
- Celluloid.shutdown
85
- end
86
67
  Signal.trap('INT') do
87
- puts "\nAn interrupt signal is happening!"
68
+ puts "\nAn interrupt signal has been triggered!"
88
69
  signal_received = true
89
70
  end
90
71
 
@@ -1,2 +1,2 @@
1
- $use_redis = false
1
+ ENV['USE_REDIS'] = 'false'
2
2
  require_relative './shared_classes'
@@ -1,3 +1,4 @@
1
+ require_relative './helper'
1
2
  module CelluloidPubsub
2
3
  # worker that subscribes to a channel or publishes to a channel
3
4
  # if it used to subscribe to a channel the worker will dispatch the messages to the actor that made the
@@ -9,8 +10,8 @@ module CelluloidPubsub
9
10
  # @!attribute connect_blk
10
11
  # @return [Proc] Block that will execute after the connection is opened
11
12
  #
12
- # @!attribute client
13
- # @return [Celluloid::WebSocket::Client] A websocket client that is used to chat witht the webserver
13
+ # @!attribute connection
14
+ # @return [Celluloid::WebSocket::Client] A websocket connection that is used to chat witht the webserver
14
15
  #
15
16
  # @!attribute options
16
17
  # @return [Hash] the options that can be used to connect to webser and send additional data
@@ -26,7 +27,9 @@ module CelluloidPubsub
26
27
  class Client
27
28
  include Celluloid
28
29
  include Celluloid::Logger
29
- attr_accessor :actor, :client, :options, :hostname, :port, :path, :channel
30
+ include CelluloidPubsub::Helper
31
+
32
+ attr_reader :actor, :connection, :options, :hostname, :port, :path, :channel
30
33
  finalizer :shutdown
31
34
  # receives a list of options that are used to connect to the webserver and an actor to which the callbacks are delegated to
32
35
  # when receiving messages from a channel
@@ -43,44 +46,61 @@ module CelluloidPubsub
43
46
  #
44
47
  # @api public
45
48
  def initialize(options)
46
- parse_options(options)
49
+ @options = options.stringify_keys!
50
+ @actor ||= @options.fetch('actor', nil)
51
+ @channel ||= @options.fetch('channel', nil)
47
52
  raise "#{self}: Please provide an actor in the options list!!!" if @actor.blank?
48
53
  raise "#{self}: Please provide an channel in the options list!!!" if @channel.blank?
49
- @actor.link Actor.current if @actor.respond_to?(:link)
50
- @client = Celluloid::WebSocket::Client.new("ws://#{@hostname}:#{@port}#{@path}", Actor.current)
51
- Actor.current.link @client
54
+ supervise_actors
55
+ setup_celluloid_logger
52
56
  end
53
57
 
54
- # the method will terminate the current actor
55
- #
58
+ def log_file_path
59
+ @log_file_path ||= @options.fetch('log_file_path', nil)
60
+ end
61
+
62
+ # the method will link the current actor to the actor that is attached to, and the connection to the current actor
56
63
  #
57
64
  # @return [void]
58
65
  #
59
66
  # @api public
60
- def shutdown
61
- debug "#{self.class} tries to 'shudown'" if debug_enabled?
62
- terminate
67
+ def supervise_actors
68
+ current_actor = Actor.current
69
+ @actor.link current_actor if @actor.respond_to?(:link)
70
+ current_actor.link connection
63
71
  end
64
72
 
65
- # check the options list for values and sets default values if not found
73
+ # the method will return the client that is used to
74
+ #
75
+ #
76
+ # @return [Celluloid::WebSocket::Client] the websocket connection used to connect to server
77
+ #
78
+ # @api public
79
+ def connection
80
+ @connection ||= Celluloid::WebSocket::Client.new("ws://#{hostname}:#{port}#{path}", Actor.current)
81
+ end
82
+
83
+ def hostname
84
+ @hostname ||= @options.fetch('hostname', CelluloidPubsub::WebServer::HOST)
85
+ end
86
+
87
+ def port
88
+ @port ||= @options.fetch('port', CelluloidPubsub::WebServer::PORT)
89
+ end
90
+
91
+ def path
92
+ @path ||= @options.fetch('path', CelluloidPubsub::WebServer::PATH)
93
+ end
94
+
95
+ # the method will terminate the current actor
66
96
  #
67
- # @param [Hash] options the options that can be used to connect to webser and send additional data
68
- # @option options [String] :actor The actor that made the connection
69
- # @option options [String]:hostname The hostname on which the webserver runs on
70
- # @option options [String] :port The port on which the webserver runs on
71
- # @option options [String] :path The request path that the webserver accepts
72
97
  #
73
98
  # @return [void]
74
99
  #
75
100
  # @api public
76
- def parse_options(options)
77
- raise 'Options is not a hash' unless options.is_a?(Hash)
78
- @options = options.stringify_keys!
79
- @actor = @options.fetch('actor', nil)
80
- @channel = @options.fetch('channel', nil)
81
- @hostname = @options.fetch('hostname', CelluloidPubsub::WebServer::HOST)
82
- @port = @options.fetch('port', CelluloidPubsub::WebServer::PORT)
83
- @path = @options.fetch('path', CelluloidPubsub::WebServer::PATH)
101
+ def shutdown
102
+ log_debug "#{self.class} tries to 'shudown'"
103
+ terminate
84
104
  end
85
105
 
86
106
  # checks if debug is enabled
@@ -101,21 +121,10 @@ module CelluloidPubsub
101
121
  #
102
122
  # @api public
103
123
  def subscribe(channel)
104
- debug("#{@actor.class} tries to subscribe to channel #{channel}") if debug_enabled?
124
+ log_debug("#{@actor.class} tries to subscribe to channel #{channel}")
105
125
  async.send_action('subscribe', channel)
106
126
  end
107
127
 
108
- # checks if the message has the successfull subscription action
109
- #
110
- # @param [string] message
111
- #
112
- # @return [void]
113
- #
114
- # @api public
115
- def succesfull_subscription?(message)
116
- message.present? && message['client_action'].present? && message['client_action'] == 'successful_subscription'
117
- end
118
-
119
128
  # publishes to a channel some data (can be anything)
120
129
  #
121
130
  # @param [string] channel
@@ -165,10 +174,14 @@ module CelluloidPubsub
165
174
  #
166
175
  # @api public
167
176
  def on_open
168
- debug("#{@actor.class} websocket connection opened") if debug_enabled?
177
+ log_debug("#{@actor.class} websocket connection opened")
169
178
  async.subscribe(@channel)
170
179
  end
171
180
 
181
+ def log_debug(message)
182
+ debug message if debug_enabled?
183
+ end
184
+
172
185
  # callback executes when actor receives a message from a subscribed channel
173
186
  # and parses the message using JSON.parse and dispatches the parsed
174
187
  # message to the original actor that made the connection
@@ -179,9 +192,8 @@ module CelluloidPubsub
179
192
  #
180
193
  # @api public
181
194
  def on_message(data)
182
- debug("#{@actor.class} received plain #{data}") if debug_enabled?
183
195
  message = JSON.parse(data)
184
- debug("#{@actor.class} received JSON #{message}") if debug_enabled?
196
+ log_debug("#{@actor.class} received JSON #{message}")
185
197
  @actor.async.on_message(message)
186
198
  end
187
199
 
@@ -195,9 +207,9 @@ module CelluloidPubsub
195
207
  #
196
208
  # @api public
197
209
  def on_close(code, reason)
198
- @client.terminate
210
+ connection.terminate
199
211
  terminate
200
- debug("#{@actor.class} dispatching on close #{code} #{reason}") if debug_enabled?
212
+ log_debug("#{@actor.class} dispatching on close #{code} #{reason}")
201
213
  @actor.async.on_close(code, reason)
202
214
  end
203
215
 
@@ -213,9 +225,8 @@ module CelluloidPubsub
213
225
  #
214
226
  # @api private
215
227
  def send_action(action, channel = nil, data = {})
216
- publishing_data = { 'client_action' => action }
217
- publishing_data = publishing_data.merge('channel' => channel) if channel.present?
218
- publishing_data = publishing_data.merge('data' => data) if data.present?
228
+ data = data.is_a?(Hash) ? data : {}
229
+ publishing_data = { 'client_action' => action, 'channel' => channel, 'data' => data }.reject { |_key, value| value.blank? }
219
230
  async.chat(publishing_data)
220
231
  end
221
232
 
@@ -232,12 +243,11 @@ module CelluloidPubsub
232
243
  final_message = nil
233
244
  if message.is_a?(Hash)
234
245
  final_message = message.to_json
235
- debug("#{@actor.class} sends #{message.to_json}") if debug_enabled?
236
246
  else
237
247
  final_message = JSON.dump(action: 'message', message: message)
238
- debug("#{@actor.class} sends JSON #{final_message}") if debug_enabled?
239
248
  end
240
- @client.text final_message
249
+ log_debug("#{@actor.class} sends JSON #{final_message}")
250
+ connection.text final_message
241
251
  end
242
252
  end
243
253
  end
@@ -0,0 +1,64 @@
1
+ module CelluloidPubsub
2
+ # class that holds the options that are configurable for this gem
3
+ module Helper
4
+ # checks if the message has the successfull subscription action
5
+ #
6
+ # @param [string] message
7
+ #
8
+ # @return [void]
9
+ #
10
+ # @api public
11
+ def succesfull_subscription?(message)
12
+ message.is_a?(Hash) && message['client_action'] == 'successful_subscription'
13
+ end
14
+
15
+ module_function
16
+
17
+ def setup_celluloid_logger
18
+ return if !debug_enabled? || (respond_to?(:log_file_path) && log_file_path.blank?)
19
+ setup_log_file
20
+ Celluloid.logger = ::Logger.new(log_file_path.present? ? log_file_path : STDOUT)
21
+ setup_celluloid_exception_handler
22
+ end
23
+
24
+ def setup_celluloid_exception_handler
25
+ Celluloid.task_class = Celluloid::TaskThread
26
+ Celluloid.exception_handler do |ex|
27
+ puts ex unless filtered_error?(ex)
28
+ end
29
+ end
30
+
31
+ def setup_log_file
32
+ return if !debug_enabled? || (respond_to?(:log_file_path) && log_file_path.blank?)
33
+ FileUtils.mkdir_p(File.dirname(log_file_path)) unless File.directory?(log_file_path)
34
+ log_file = File.open(log_file_path, 'w')
35
+ log_file.sync = true
36
+ end
37
+
38
+ def filtered_error?(error)
39
+ [Interrupt].any? { |class_name| error.is_a?(class_name) }
40
+ end
41
+
42
+ # receives a list of options that are used to configure the webserver
43
+ #
44
+ # @param [Hash] options the options that can be used to connect to webser and send additional data
45
+ # @option options [String]:hostname The hostname on which the webserver runs on
46
+ # @option options [Integer] :port The port on which the webserver runs on
47
+ # @option options [String] :path The request path that the webserver accepts
48
+ # @option options [Boolean] :spy Enable this only if you want to enable debugging for the webserver
49
+ # @option options [Integer]:backlog How many connections the server accepts
50
+ #
51
+ # @return [void]
52
+ #
53
+ # @api public
54
+ def parse_options(options)
55
+ options = options.is_a?(Array) ? options.first : options
56
+ options = options.is_a?(Hash) ? options.stringify_keys : {}
57
+ options
58
+ end
59
+
60
+ def log_debug(message)
61
+ debug message if respond_to?(:debug_enabled?) && debug_enabled?
62
+ end
63
+ end
64
+ end