celluloid_pubsub 1.1.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,4 +4,4 @@ source "http://rubygems.org"
4
4
 
5
5
  gem "celluloid", "0.17.3"
6
6
 
7
- gemspec :path => "../"
7
+ gemspec path: "../"
@@ -2,6 +2,6 @@
2
2
 
3
3
  source "http://rubygems.org"
4
4
 
5
- gem "celluloid", "0.18.0.pre"
5
+ gem "celluloid", "0.17.4"
6
6
 
7
- gemspec :path => "../"
7
+ gemspec path: "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "celluloid", "0.18.0"
6
+
7
+ gemspec path: "../"
data/init.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+
3
4
  require 'celluloid_pubsub'
@@ -1,15 +1,16 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+
3
4
  require 'rubygems'
4
5
  require 'bundler'
5
6
  require 'bundler/setup'
6
7
  require 'celluloid/io'
7
- require 'reel'
8
8
  require 'celluloid/websocket/client'
9
9
  require 'active_support/all'
10
10
  require 'json'
11
11
  require 'thread'
12
12
  require 'celluloid/pmap'
13
13
  require 'celluloid_pubsub/base_actor'
14
+ require 'reel'
14
15
  Gem.find_files('celluloid_pubsub/initializers/**/*.rb').each { |path| require path }
15
16
  Gem.find_files('celluloid_pubsub/**/*.rb').each { |path| require path }
@@ -1,5 +1,6 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+
3
4
  require_relative './helper'
4
5
  module CelluloidPubsub
5
6
  # base actor used for compatibility between celluloid versions
@@ -39,6 +40,7 @@ module CelluloidPubsub
39
40
  # @return [Class] returns the logger class from celluloid depending on version
40
41
  #
41
42
  # @api public
43
+ # :nocov:
42
44
  def celluloid_logger_class
43
45
  if version_less_than_seventeen?
44
46
  Celluloid::Logger
@@ -46,6 +48,7 @@ module CelluloidPubsub
46
48
  Celluloid::Internals::Logger
47
49
  end
48
50
  end
51
+ # :nocov:
49
52
 
50
53
  # returns the celluloid version loaded
51
54
  # @return [String] returns the celluloid version loaded
@@ -63,12 +66,34 @@ module CelluloidPubsub
63
66
  verify_gem_version(celluloid_version, '0.17', operator: '<')
64
67
  end
65
68
 
69
+ # returns true if celluloid version less than 0.18, otherwise false
70
+ # @return [Boolean] returns true if celluloid version less than 0.17, otherwise false
71
+ #
72
+ # @api public
73
+ def version_less_than_eigthteen?
74
+ verify_gem_version(celluloid_version, '0.18', operator: '<')
75
+ end
76
+
77
+ # tries to boot up Celluloid if it is not running
78
+ # @return [Boolean] returns true if Celluloid started false otherwise
79
+ #
80
+ # @api public
81
+ def boot_up
82
+ celluloid_running = begin
83
+ Celluloid.running?
84
+ rescue StandardError
85
+ false
86
+ end
87
+ Celluloid.boot unless celluloid_running
88
+ end
89
+
66
90
  # sets up the actor supervision based on celluloid version
67
91
  # @param [Class] class_name The class that will be used to supervise the actor
68
92
  # @param [Hash] options Additional options needed for supervision
69
93
  # @return [void]
70
94
  #
71
95
  # @api public
96
+ # :nocov:
72
97
  def setup_actor_supervision(class_name, options)
73
98
  actor_name, args = options.slice(:actor_name, :args).values
74
99
  if version_less_than_seventeen?
@@ -77,17 +102,24 @@ module CelluloidPubsub
77
102
  class_name.supervise(as: actor_name, args: [args].compact)
78
103
  end
79
104
  end
105
+ # :nocov:
80
106
  end
81
107
  end
82
108
  end
83
109
 
84
-
110
+ # :nocov:
85
111
  if CelluloidPubsub::BaseActor.version_less_than_seventeen?
86
112
  require 'celluloid'
87
113
  require 'celluloid/autostart'
88
- else
114
+ elsif CelluloidPubsub::BaseActor.version_less_than_eigthteen?
89
115
  require 'celluloid/current'
90
- celluloid_running = Celluloid.running? rescue false
91
- Celluloid.boot unless celluloid_running
116
+ CelluloidPubsub::BaseActor.boot_up
117
+ require 'celluloid'
118
+ else
92
119
  require 'celluloid'
120
+ require 'celluloid/pool'
121
+ require 'celluloid/fsm'
122
+ require 'celluloid/supervision'
123
+ CelluloidPubsub::BaseActor.boot_up
93
124
  end
125
+ # :nocov:
@@ -1,6 +1,8 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+
3
4
  require_relative './helper'
5
+ require_relative './client_connection'
4
6
  module CelluloidPubsub
5
7
  # worker that subscribes to a channel or publishes to a channel
6
8
  # if it used to subscribe to a channel the worker will dispatch the messages to the actor that made the
@@ -30,6 +32,7 @@ module CelluloidPubsub
30
32
  attr_accessor :channel
31
33
 
32
34
  finalizer :shutdown
35
+ trap_exit :actor_died
33
36
  # receives a list of options that are used to connect to the webserver and an actor to which the callbacks are delegated to
34
37
  # when receiving messages from a channel
35
38
  #
@@ -48,9 +51,21 @@ module CelluloidPubsub
48
51
  @options = options.stringify_keys!
49
52
  @actor ||= @options.fetch('actor', nil)
50
53
  @channel ||= @options.fetch('channel', nil)
54
+ @shutting_down = false
51
55
  raise "#{self}: Please provide an actor in the options list!!!" if @actor.blank?
52
- supervise_actors
53
56
  setup_celluloid_logger
57
+ log_debug "#{@actor.class} starting on #{hostname}:#{port}"
58
+ supervise_actors
59
+ end
60
+
61
+ # the method will return true if the actor is shutting down
62
+ #
63
+ #
64
+ # @return [Boolean] returns true if the actor is shutting down
65
+ #
66
+ # @api public
67
+ def shutting_down?
68
+ @shutting_down == true
54
69
  end
55
70
 
56
71
  # the method will return the path to the log file where debug messages will be printed
@@ -62,6 +77,15 @@ module CelluloidPubsub
62
77
  @log_file_path ||= @options.fetch('log_file_path', nil)
63
78
  end
64
79
 
80
+ # the method will return the log level of the logger
81
+ #
82
+ # @return [Integer, nil] return the log level used by the logger ( default is 1 - info)
83
+ #
84
+ # @api public
85
+ def log_level
86
+ @log_level ||= @options['log_level'] || ::Logger::Severity::INFO
87
+ end
88
+
65
89
  # the method will link the current actor to the actor that is attached to, and the connection to the current actor
66
90
  #
67
91
  # @return [void]
@@ -80,7 +104,7 @@ module CelluloidPubsub
80
104
  #
81
105
  # @api public
82
106
  def connection
83
- @connection ||= Celluloid::WebSocket::Client.new("ws://#{hostname}:#{port}#{path}", Actor.current)
107
+ @connection ||= CelluloidPubsub::ClientConnection.new("ws://#{hostname}:#{port}#{path}", Actor.current)
84
108
  end
85
109
 
86
110
  # the method will return the hostname of the server
@@ -120,7 +144,8 @@ module CelluloidPubsub
120
144
  #
121
145
  # @api public
122
146
  def shutdown
123
- log_debug "#{self.class} tries to 'shudown'"
147
+ @shutting_down = true
148
+ log_debug "#{self.class} tries to 'shutdown'"
124
149
  terminate
125
150
  end
126
151
 
@@ -228,17 +253,19 @@ module CelluloidPubsub
228
253
  #
229
254
  # @api public
230
255
  def on_close(code, reason)
231
- connection.terminate
232
- terminate
233
- log_debug("#{@actor.class} dispatching on close #{code} #{reason}")
256
+ log_debug("#{self.class} dispatching on close #{code} #{reason}")
234
257
  if @actor.respond_to?(:async)
235
258
  @actor.async.on_close(code, reason)
236
259
  else
237
260
  @actor.on_close(code, reason)
238
261
  end
262
+ ensure
263
+ log_debug("#{self.class} closing the connection on close and terminating")
264
+ connection.terminate unless actor_dead?(connection)
265
+ terminate
239
266
  end
240
267
 
241
- private
268
+ private
242
269
 
243
270
  # method used to send an action to the webserver reactor , to a chanel and with data
244
271
  #
@@ -269,5 +296,18 @@ module CelluloidPubsub
269
296
  log_debug("#{@actor.class} sends JSON #{final_message}")
270
297
  connection.text final_message
271
298
  end
299
+
300
+ # method called when the actor is exiting
301
+ #
302
+ # @param [actor] actor - the current actor
303
+ # @param [Hash] reason - the reason it crashed
304
+ #
305
+ # @return [void]
306
+ #
307
+ # @api public
308
+ def actor_died(actor, reason)
309
+ @shutting_down = true
310
+ log_debug "Oh no! #{actor.inspect} has died because of a #{reason.class}"
311
+ end
272
312
  end
273
313
  end
@@ -0,0 +1,57 @@
1
+ require 'celluloid/websocket/client/connection'
2
+ require 'websocket/driver'
3
+ require_relative './helper'
4
+ module CelluloidPubsub
5
+ class ClientConnection < ::Celluloid::WebSocket::Client::Connection
6
+ include CelluloidPubsub::Helper
7
+
8
+ finalizer :shutdown
9
+ trap_exit :actor_died
10
+
11
+ def initialize(url, handler)
12
+ @shutting_down = false
13
+ super(url, handler)
14
+ end
15
+
16
+ def run
17
+ super
18
+ rescue EOFError, Errno::ECONNRESET, StandardError
19
+ @client.emit(:close, ::WebSocket::Driver::CloseEvent.new(1001, 'server closed connection'))
20
+ end
21
+
22
+ # the method will return true if the actor is shutting down
23
+ #
24
+ #
25
+ # @return [Boolean] returns true if the actor is shutting down
26
+ #
27
+ # @api public
28
+ def shutting_down?
29
+ @shutting_down == true
30
+ end
31
+
32
+ # the method will terminate the current actor
33
+ #
34
+ #
35
+ # @return [void]
36
+ #
37
+ # @api public
38
+ def shutdown
39
+ @shutting_down = true
40
+ log_debug "#{self.class} tries to 'shutdown'"
41
+ terminate
42
+ end
43
+
44
+ # method called when the actor is exiting
45
+ #
46
+ # @param [actor] actor - the current actor
47
+ # @param [Hash] reason - the reason it crashed
48
+ #
49
+ # @return [void]
50
+ #
51
+ # @api public
52
+ def actor_died(actor, reason)
53
+ @shutting_down = true
54
+ log_debug "Oh no! #{actor.inspect} has died because of a #{reason.class}"
55
+ end
56
+ end
57
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module CelluloidPubsub
3
4
  # class used for parsing gem versions
4
5
  # @!attribute [r] version
@@ -7,8 +8,7 @@ module CelluloidPubsub
7
8
  # @!attribute [r] options
8
9
  # @return [Hash] The additional options for parsing the version
9
10
  class GemVersionParser
10
- attr_reader :version
11
- attr_reader :options
11
+ attr_reader :version, :options
12
12
 
13
13
  # receives the version and the additional options
14
14
  #
@@ -1,5 +1,6 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+
3
4
  require_relative './gem_version_parser'
4
5
  module CelluloidPubsub
5
6
  # class that holds the options that are configurable for this gem
@@ -15,7 +16,39 @@ module CelluloidPubsub
15
16
  message.is_a?(Hash) && message['client_action'] == 'successful_subscription'
16
17
  end
17
18
 
18
- module_function
19
+ # the method try to decide if an actor is dead
20
+ # In Celluloid 0.18 there is no `dead?` method anymore
21
+ # So we are trying to be backward-compatible with older versions
22
+ #
23
+ # @param [Celluloid::Actor] actor
24
+ # @return [Boolean] returns true if the actor is dead, otherwise false
25
+ #
26
+ # @api public
27
+ def actor_dead?(actor)
28
+ raise actor.class.inspect if !actor.respond_to?(:dead?) && !actor.respond_to?(:alive?)
29
+ (actor.respond_to?(:dead?) && actor.dead?) ||
30
+ (actor.respond_to?(:alive?) && !actor.alive?)
31
+ end
32
+
33
+ # returns the instance of the class that includes the actor, this is useful in tests
34
+ #
35
+ # @return [Object] returns the object
36
+ #
37
+ # @api public
38
+ def own_self
39
+ self
40
+ end
41
+
42
+ # returns the current actor
43
+ #
44
+ # @return [::Celluloid::Actor] returns the current actor
45
+ #
46
+ # @api public
47
+ def cell_actor
48
+ ::Celluloid::Actor.current
49
+ end
50
+
51
+ module_function
19
52
 
20
53
  # returns the gem's property from its speification or nil
21
54
  # @param [String] name the name of the gem
@@ -91,36 +124,48 @@ module CelluloidPubsub
91
124
  # @return [void]
92
125
  #
93
126
  # @api private
127
+ # :nocov:
94
128
  def setup_celluloid_logger
95
129
  return if !debug_enabled? || (respond_to?(:log_file_path) && log_file_path.blank?)
96
130
  setup_log_file
97
- Celluloid.logger = ::Logger.new(log_file_path.present? ? log_file_path : STDOUT)
131
+ Celluloid.logger = ::Logger.new(log_file_path).tap do |logger|
132
+ logger.level = respond_to?(:log_level) ? log_level : ::Logger::Severity::INFO
133
+ end
98
134
  setup_celluloid_exception_handler
99
135
  end
136
+ # :nocov:
100
137
 
101
138
  # sets the celluloid exception handler
102
139
  #
103
140
  # @return [void]
104
141
  #
105
142
  # @api private
143
+ # :nocov:
106
144
  def setup_celluloid_exception_handler
107
145
  Celluloid.task_class = defined?(Celluloid::TaskThread) ? Celluloid::TaskThread : Celluloid::Task::Threaded
108
146
  Celluloid.exception_handler do |ex|
109
- puts ex unless filtered_error?(ex)
147
+ unless filtered_error?(ex)
148
+ puts ex
149
+ puts ex.backtrace
150
+ puts ex.cause
151
+ end
110
152
  end
111
153
  end
154
+ # :nocov:
112
155
 
113
156
  # creates the log file where the debug messages will be printed
114
157
  #
115
158
  # @return [void]
116
159
  #
117
160
  # @api private
161
+ # :nocov:
118
162
  def setup_log_file
119
163
  return if !debug_enabled? || (respond_to?(:log_file_path) && log_file_path.blank?)
120
164
  FileUtils.mkdir_p(File.dirname(log_file_path)) unless File.directory?(log_file_path)
121
- log_file = File.open(log_file_path, 'w')
165
+ log_file = File.open(log_file_path, 'wb')
122
166
  log_file.sync = true
123
167
  end
168
+ # :nocov:
124
169
 
125
170
  # checks if a given error needs to be filtered
126
171
  #
@@ -143,9 +188,8 @@ module CelluloidPubsub
143
188
  #
144
189
  # @api private
145
190
  def parse_options(options)
146
- options = options.is_a?(Array) ? options.first : options
147
- options = options.is_a?(Hash) ? options.stringify_keys : {}
148
- options
191
+ options = options.is_a?(Array) ? options.last : options
192
+ options.is_a?(Hash) ? options.deep_stringify_keys : {}
149
193
  end
150
194
 
151
195
  # receives a message, and logs it to the log file if debug is enabled
@@ -155,8 +199,12 @@ module CelluloidPubsub
155
199
  # @return [void]
156
200
  #
157
201
  # @api private
202
+ # :nocov:
158
203
  def log_debug(message)
159
- debug message if respond_to?(:debug_enabled?) && debug_enabled?
204
+ return unless respond_to?(:debug_enabled?)
205
+ return if Celluloid.logger.blank? || !debug_enabled?
206
+ Celluloid.logger.debug(message)
160
207
  end
208
+ # :nocov:
161
209
  end
162
210
  end