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.
- checksums.yaml +5 -5
- data/.hound.yml +10 -0
- data/.reek +2 -0
- data/.rubocop.yml +107 -25
- data/.rubocop_todo.yml +7 -0
- data/.travis.yml +52 -11
- data/Appraisals +10 -2
- data/Gemfile +1 -6
- data/Rakefile +7 -2
- data/celluloid_pubsub.gemspec +15 -13
- data/examples/simple_test.rb +30 -8
- data/gemfiles/{celluloid_0.16.0.gemfile → cell_0.16.0.gemfile} +1 -1
- data/gemfiles/{celluloid_0.17.3.gemfile → cell_0.17.3.gemfile} +1 -1
- data/gemfiles/cell_0.17.4.gemfile +7 -0
- data/gemfiles/cell_0.18.0.gemfile +7 -0
- data/init.rb +1 -0
- data/lib/celluloid_pubsub.rb +2 -1
- data/lib/celluloid_pubsub/base_actor.rb +38 -1
- data/lib/celluloid_pubsub/client.rb +47 -7
- data/lib/celluloid_pubsub/client_connection.rb +57 -0
- data/lib/celluloid_pubsub/gem_version_parser.rb +2 -2
- data/lib/celluloid_pubsub/helper.rb +56 -8
- data/lib/celluloid_pubsub/initializers/reel_colors.rb +6 -1
- data/lib/celluloid_pubsub/reactor.rb +154 -22
- data/lib/celluloid_pubsub/registry.rb +28 -2
- data/lib/celluloid_pubsub/version.rb +20 -2
- data/lib/celluloid_pubsub/web_server.rb +84 -6
- data/spec/lib/celluloid_pubsub/base_actor_spec.rb +78 -0
- data/spec/lib/celluloid_pubsub/client_pubsub_spec.rb +168 -37
- data/spec/lib/celluloid_pubsub/reactor_spec.rb +373 -98
- data/spec/lib/celluloid_pubsub/registry_spec.rb +19 -1
- data/spec/lib/celluloid_pubsub/version_spec.rb +21 -0
- data/spec/lib/celluloid_pubsub/web_server_spec.rb +2 -2
- data/spec/spec_helper.rb +76 -11
- metadata +62 -81
data/init.rb
CHANGED
data/lib/celluloid_pubsub.rb
CHANGED
@@ -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
|
-
|
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 ||=
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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
|
-
|
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, '
|
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.
|
147
|
-
options
|
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
|
-
|
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
|