celluloid_pubsub 1.0.2 → 2.0.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.
@@ -4,4 +4,4 @@ source "http://rubygems.org"
4
4
 
5
5
  gem "celluloid", "0.16.0"
6
6
 
7
- gemspec :path => "../"
7
+ gemspec path: "../"
@@ -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: "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "celluloid", "0.17.4"
6
+
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,12 +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
 
110
+ # :nocov:
84
111
  if CelluloidPubsub::BaseActor.version_less_than_seventeen?
112
+ require 'celluloid'
85
113
  require 'celluloid/autostart'
86
- else
114
+ elsif CelluloidPubsub::BaseActor.version_less_than_eigthteen?
87
115
  require 'celluloid/current'
116
+ CelluloidPubsub::BaseActor.boot_up
117
+ require 'celluloid'
118
+ else
119
+ require 'celluloid'
120
+ require 'celluloid/pool'
121
+ require 'celluloid/fsm'
122
+ require 'celluloid/supervision'
123
+ CelluloidPubsub::BaseActor.boot_up
88
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