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
@@ -1,17 +1,22 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
|
+
|
3
4
|
require 'reel/spy'
|
4
5
|
Reel::Spy::Colors.class_eval do
|
5
6
|
alias_method :original_colorize, :colorize
|
6
7
|
|
7
|
-
|
8
|
+
# :nocov:
|
9
|
+
def colorize(_var, str)
|
8
10
|
force_utf8_encoding(str)
|
9
11
|
end
|
12
|
+
# :nocov:
|
10
13
|
|
11
14
|
# Returns utf8 encoding of the msg
|
12
15
|
# @param [String] msg
|
13
16
|
# @return [String] ReturnsReturns utf8 encoding of the msg
|
17
|
+
# :nocov:
|
14
18
|
def force_utf8_encoding(msg)
|
15
19
|
msg.respond_to?(:force_encoding) && msg.encoding.name != 'UTF-8' ? msg.force_encoding('UTF-8') : msg
|
16
20
|
end
|
21
|
+
# :nocov:
|
17
22
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
|
+
|
3
4
|
require_relative './registry'
|
4
5
|
require_relative './helper'
|
5
6
|
module CelluloidPubsub
|
@@ -18,7 +19,7 @@ module CelluloidPubsub
|
|
18
19
|
include CelluloidPubsub::BaseActor
|
19
20
|
|
20
21
|
# available actions that can be delegated
|
21
|
-
AVAILABLE_ACTIONS = %w
|
22
|
+
AVAILABLE_ACTIONS = %w[unsubscribe_clients unsubscribe subscribe publish unsubscribe_all].freeze
|
22
23
|
|
23
24
|
# The websocket connection received from the server
|
24
25
|
# @return [Reel::WebSocket] websocket connection
|
@@ -32,7 +33,13 @@ module CelluloidPubsub
|
|
32
33
|
# @return [Array] array of channels to which the current reactor has subscribed to
|
33
34
|
attr_accessor :channels
|
34
35
|
|
36
|
+
# The same options passed to the server are available on the reactor too
|
37
|
+
# @return [Hash] Hash with all the options passed to the server
|
38
|
+
attr_reader :options
|
39
|
+
|
35
40
|
finalizer :shutdown
|
41
|
+
trap_exit :actor_died
|
42
|
+
|
36
43
|
# rececives a new socket connection from the server
|
37
44
|
# and listens for messages
|
38
45
|
#
|
@@ -42,11 +49,68 @@ module CelluloidPubsub
|
|
42
49
|
#
|
43
50
|
# @api public
|
44
51
|
def work(websocket, server)
|
52
|
+
initialize_data(websocket, server)
|
53
|
+
server.reactors << Actor.current
|
54
|
+
async.run
|
55
|
+
end
|
56
|
+
|
57
|
+
# initializes the actor
|
58
|
+
#
|
59
|
+
# @param [Reel::WebSocket] websocket
|
60
|
+
# @param [CelluloidPubsub::WebServer] server
|
61
|
+
#
|
62
|
+
# @return [Celluloid::Actor] returns the actor
|
63
|
+
#
|
64
|
+
# @api public
|
65
|
+
def initialize_data(websocket, server)
|
66
|
+
@websocket = websocket
|
45
67
|
@server = server
|
68
|
+
@options = @server.server_options
|
46
69
|
@channels = []
|
47
|
-
@
|
48
|
-
|
49
|
-
|
70
|
+
@shutting_down = false
|
71
|
+
setup_celluloid_logger
|
72
|
+
log_debug "#{self.class} Streaming changes for #{websocket.url} #{websocket.class.name}"
|
73
|
+
yield(websocket, server) if block_given?
|
74
|
+
cell_actor
|
75
|
+
end
|
76
|
+
|
77
|
+
# the method will return the file path of the log file where debug messages will be printed
|
78
|
+
#
|
79
|
+
#
|
80
|
+
# @return [String] returns the file path of the log file where debug messages will be printed
|
81
|
+
#
|
82
|
+
# @api public
|
83
|
+
def log_file_path
|
84
|
+
@log_file_path ||= options.fetch('log_file_path', nil)
|
85
|
+
end
|
86
|
+
|
87
|
+
# the method will return the log level of the logger
|
88
|
+
#
|
89
|
+
# @return [Integer, nil] return the log level used by the logger ( default is 1 - info)
|
90
|
+
#
|
91
|
+
# @api public
|
92
|
+
def log_level
|
93
|
+
@log_level ||= options['log_level'] || ::Logger::Severity::INFO
|
94
|
+
end
|
95
|
+
|
96
|
+
# the method will return options needed when configuring an adapter
|
97
|
+
# @see celluloid_pubsub_redis_adapter for more information
|
98
|
+
#
|
99
|
+
# @return [Hash] returns options needed by the adapter
|
100
|
+
#
|
101
|
+
# @api public
|
102
|
+
def adapter_options
|
103
|
+
@adapter_options ||= options['adapter_options'] || {}
|
104
|
+
end
|
105
|
+
|
106
|
+
# the method will return true if the actor is shutting down
|
107
|
+
#
|
108
|
+
#
|
109
|
+
# @return [Boolean] returns true if the actor is shutting down
|
110
|
+
#
|
111
|
+
# @api public
|
112
|
+
def shutting_down?
|
113
|
+
@shutting_down == true
|
50
114
|
end
|
51
115
|
|
52
116
|
# the method will return true if debug is enabled
|
@@ -56,7 +120,8 @@ module CelluloidPubsub
|
|
56
120
|
#
|
57
121
|
# @api public
|
58
122
|
def debug_enabled?
|
59
|
-
|
123
|
+
@debug_enabled = options.fetch('enable_debug', false)
|
124
|
+
@debug_enabled == true
|
60
125
|
end
|
61
126
|
|
62
127
|
# reads from the socket the message
|
@@ -70,11 +135,12 @@ module CelluloidPubsub
|
|
70
135
|
# :nocov:
|
71
136
|
def run
|
72
137
|
loop do
|
73
|
-
break if Actor.current
|
138
|
+
break if shutting_down? || actor_dead?(Actor.current) || @websocket.closed? || actor_dead?(@server)
|
74
139
|
message = try_read_websocket
|
75
140
|
handle_websocket_message(message) if message.present?
|
76
141
|
end
|
77
142
|
end
|
143
|
+
# :nocov:
|
78
144
|
|
79
145
|
# will try to read the message from the websocket
|
80
146
|
# and if it fails will log the exception if debug is enabled
|
@@ -83,10 +149,9 @@ module CelluloidPubsub
|
|
83
149
|
#
|
84
150
|
# @api public
|
85
151
|
#
|
86
|
-
# :nocov:
|
87
152
|
def try_read_websocket
|
88
153
|
@websocket.closed? ? nil : @websocket.read
|
89
|
-
rescue
|
154
|
+
rescue StandardError
|
90
155
|
nil
|
91
156
|
end
|
92
157
|
|
@@ -108,9 +173,10 @@ module CelluloidPubsub
|
|
108
173
|
#
|
109
174
|
# @api public
|
110
175
|
def parse_json_data(message)
|
176
|
+
log_debug "#{reactor_class} received #{message}"
|
111
177
|
JSON.parse(message)
|
112
|
-
rescue =>
|
113
|
-
log_debug "#{reactor_class} could not parse #{message} because of #{
|
178
|
+
rescue StandardError => e
|
179
|
+
log_debug "#{reactor_class} could not parse #{message} because of #{e.inspect}"
|
114
180
|
message
|
115
181
|
end
|
116
182
|
|
@@ -147,7 +213,7 @@ module CelluloidPubsub
|
|
147
213
|
#
|
148
214
|
# @api public
|
149
215
|
def handle_parsed_websocket_message(json_data)
|
150
|
-
data =
|
216
|
+
data = json_data.is_a?(Hash) ? json_data.stringify_keys : {}
|
151
217
|
if CelluloidPubsub::Reactor::AVAILABLE_ACTIONS.include?(data['client_action'].to_s)
|
152
218
|
log_debug "#{self.class} finds actions for #{json_data}"
|
153
219
|
delegate_action(data) if data['client_action'].present?
|
@@ -183,7 +249,7 @@ module CelluloidPubsub
|
|
183
249
|
end
|
184
250
|
|
185
251
|
# the method will delegate the message to the server in an asyncronous way by sending the current actor and the message
|
186
|
-
# @see
|
252
|
+
# @see CelluloidPubsub::WebServer#handle_dispatched_message
|
187
253
|
#
|
188
254
|
# @param [Hash] json_data
|
189
255
|
#
|
@@ -262,7 +328,8 @@ module CelluloidPubsub
|
|
262
328
|
#
|
263
329
|
# @api public
|
264
330
|
def shutdown
|
265
|
-
|
331
|
+
@shutting_down = true
|
332
|
+
log_debug "#{self.class} tries to 'shutdown'"
|
266
333
|
@websocket.close if @websocket.present? && !@websocket.closed?
|
267
334
|
terminate
|
268
335
|
end
|
@@ -285,6 +352,42 @@ module CelluloidPubsub
|
|
285
352
|
@websocket << message.merge('client_action' => 'successful_subscription', 'channel' => channel).to_json if @server.adapter == CelluloidPubsub::WebServer::CLASSIC_ADAPTER
|
286
353
|
end
|
287
354
|
|
355
|
+
# this method will write to the socket all messages that were published
|
356
|
+
# to that channel before the actor subscribed
|
357
|
+
#
|
358
|
+
# @param [String] channel
|
359
|
+
# @return [void]
|
360
|
+
#
|
361
|
+
# @api public
|
362
|
+
def send_unpublished(channel)
|
363
|
+
return if (messages = unpublished_messages(channel)).blank?
|
364
|
+
messages.each do |msg|
|
365
|
+
@websocket << msg.to_json
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
# the method clears all the messages left unpublished in a channel
|
370
|
+
#
|
371
|
+
# @param [String] channel
|
372
|
+
#
|
373
|
+
# @return [void]
|
374
|
+
#
|
375
|
+
# @api public
|
376
|
+
def clear_unpublished_messages(channel)
|
377
|
+
CelluloidPubsub::Registry.messages[channel] = []
|
378
|
+
end
|
379
|
+
|
380
|
+
# the method will return a list of all unpublished messages in a channel
|
381
|
+
#
|
382
|
+
# @param [String] channel
|
383
|
+
#
|
384
|
+
# @return [Array] the list of messages that were not published
|
385
|
+
#
|
386
|
+
# @api public
|
387
|
+
def unpublished_messages(channel)
|
388
|
+
(messages = CelluloidPubsub::Registry.messages[channel]).present? ? messages : []
|
389
|
+
end
|
390
|
+
|
288
391
|
# this method will return a list of all subscribers to a particular channel or a empty array
|
289
392
|
#
|
290
393
|
#
|
@@ -326,9 +429,9 @@ module CelluloidPubsub
|
|
326
429
|
def publish(current_topic, json_data)
|
327
430
|
message = json_data['data'].to_json
|
328
431
|
return if current_topic.blank? || message.blank?
|
329
|
-
|
330
|
-
rescue =>
|
331
|
-
log_debug("could not publish message #{message} into topic #{current_topic} because of #{
|
432
|
+
server_publish_event(current_topic, message)
|
433
|
+
rescue StandardError => e
|
434
|
+
log_debug("could not publish message #{message} into topic #{current_topic} because of #{e.inspect}")
|
332
435
|
end
|
333
436
|
|
334
437
|
# the method will publish to all subsribers of a channel a message
|
@@ -339,18 +442,34 @@ module CelluloidPubsub
|
|
339
442
|
# @return [void]
|
340
443
|
#
|
341
444
|
# @api public
|
342
|
-
def
|
343
|
-
@server.
|
344
|
-
|
445
|
+
def server_publish_event(current_topic, message)
|
446
|
+
if (subscribers = @server.subscribers[current_topic]).present?
|
447
|
+
subscribers.dup.pmap do |hash|
|
345
448
|
hash[:reactor].websocket << message
|
346
449
|
end
|
450
|
+
else
|
451
|
+
save_unpublished_message(current_topic, message)
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
# the method save the message for a specific channel if there are no subscribers
|
456
|
+
#
|
457
|
+
# @param [String] current_topic
|
458
|
+
# @param [#to_s] message
|
459
|
+
#
|
460
|
+
# @return [void]
|
461
|
+
#
|
462
|
+
# @api public
|
463
|
+
def save_unpublished_message(current_topic, message)
|
464
|
+
@server.timers_mutex.synchronize do
|
465
|
+
(CelluloidPubsub::Registry.messages[current_topic] ||= []) << message
|
347
466
|
end
|
348
467
|
end
|
349
468
|
|
350
|
-
# unsubscribes all actors from all channels and terminates the
|
469
|
+
# unsubscribes all actors from all channels and terminates the current actor
|
351
470
|
#
|
352
471
|
# @param [String] _channel NOT USED - needed to maintain compatibility with the other methods
|
353
|
-
# @param [Object]
|
472
|
+
# @param [Object] json_data NOT USED - needed to maintain compatibility with the other methods
|
354
473
|
#
|
355
474
|
# @return [void]
|
356
475
|
#
|
@@ -383,12 +502,25 @@ module CelluloidPubsub
|
|
383
502
|
# @api public
|
384
503
|
def server_kill_reactors(channel)
|
385
504
|
@server.mutex.synchronize do
|
386
|
-
(@server.subscribers[channel]
|
505
|
+
(@server.subscribers[channel] || []).dup.pmap do |hash|
|
387
506
|
reactor = hash[:reactor]
|
388
507
|
reactor.websocket.close
|
389
508
|
Celluloid::Actor.kill(reactor)
|
390
509
|
end
|
391
510
|
end
|
392
511
|
end
|
512
|
+
|
513
|
+
# method called when the actor is exiting
|
514
|
+
#
|
515
|
+
# @param [actor] actor - the current actor
|
516
|
+
# @param [Hash] reason - the reason it crashed
|
517
|
+
#
|
518
|
+
# @return [void]
|
519
|
+
#
|
520
|
+
# @api public
|
521
|
+
def actor_died(actor, reason)
|
522
|
+
@shutting_down = true
|
523
|
+
log_debug "Oh no! #{actor.inspect} has died because of a #{reason.class}"
|
524
|
+
end
|
393
525
|
end
|
394
526
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
|
+
|
3
4
|
module CelluloidPubsub
|
4
5
|
# class used to register new channels and save them in memory
|
5
6
|
# @attr channels
|
@@ -8,8 +9,33 @@ module CelluloidPubsub
|
|
8
9
|
class << self
|
9
10
|
# The channels that the server can handle
|
10
11
|
# @return [Array] array of channels to which actors have subscribed to
|
11
|
-
|
12
|
+
attr_writer :channels
|
13
|
+
|
14
|
+
# Messages that are published before any clients being subscribed to those channels
|
15
|
+
# will be kept here until a client subscribes to that channel
|
16
|
+
# @return [Hash] key-value pairs containing the channel and the messages that were published
|
17
|
+
attr_writer :messages
|
18
|
+
|
19
|
+
# holds a list of all messages sent by clients that were not published
|
20
|
+
# to a channel because there were no subscribers at that time
|
21
|
+
#
|
22
|
+
# The keys are the channel names and the values are arrays of messages
|
23
|
+
#
|
24
|
+
# @return [Hash<String, Array<Hash>>]
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
def messages
|
28
|
+
@messages ||= {}
|
29
|
+
end
|
30
|
+
|
31
|
+
# holds a list of all known channels
|
32
|
+
#
|
33
|
+
# @return [Array<String>]
|
34
|
+
#
|
35
|
+
# @api private
|
36
|
+
def channels
|
37
|
+
@channels ||= []
|
38
|
+
end
|
12
39
|
end
|
13
|
-
@channels = []
|
14
40
|
end
|
15
41
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
|
+
|
3
4
|
# Returns the version of the gem as a <tt>Gem::Version</tt>
|
4
5
|
module CelluloidPubsub
|
5
6
|
# it prints the gem version as a string
|
@@ -7,23 +8,40 @@ module CelluloidPubsub
|
|
7
8
|
# @return [String]
|
8
9
|
#
|
9
10
|
# @api public
|
11
|
+
# :nocov:
|
10
12
|
def self.gem_version
|
11
13
|
Gem::Version.new VERSION::STRING
|
12
14
|
end
|
15
|
+
# :nocov:
|
13
16
|
|
14
17
|
# module used to generate the version string
|
15
18
|
# provides a easy way of getting the major, minor and tiny
|
19
|
+
# :nocov:
|
16
20
|
module VERSION
|
17
21
|
# major release version
|
18
|
-
|
22
|
+
# :nocov:
|
23
|
+
MAJOR = 2
|
24
|
+
# :nocov:
|
25
|
+
|
19
26
|
# minor release version
|
27
|
+
# :nocov:
|
20
28
|
MINOR = 0
|
29
|
+
# :nocov:
|
30
|
+
|
21
31
|
# tiny release version
|
22
|
-
|
32
|
+
# :nocov:
|
33
|
+
TINY = 0
|
34
|
+
# :nocov:
|
35
|
+
|
23
36
|
# prelease version ( set this only if it is a prelease)
|
37
|
+
# :nocov:
|
24
38
|
PRE = nil
|
39
|
+
# :nocov:
|
25
40
|
|
26
41
|
# generates the version string
|
42
|
+
# :nocov:
|
27
43
|
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
44
|
+
# :nocov:
|
28
45
|
end
|
46
|
+
# :nocov:
|
29
47
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
|
+
|
3
4
|
require_relative './reactor'
|
4
5
|
require_relative './helper'
|
5
6
|
module CelluloidPubsub
|
@@ -17,6 +18,8 @@ module CelluloidPubsub
|
|
17
18
|
# @return [Hash] The hostname on which the webserver runs on
|
18
19
|
# @attr mutex
|
19
20
|
# @return [Mutex] The mutex that will synchronize actions on subscribers
|
21
|
+
# @attr timers_mutex
|
22
|
+
# @return [Mutex] The mutex that will synchronize actions on registry messages
|
20
23
|
class WebServer < Reel::Server::HTTP
|
21
24
|
include CelluloidPubsub::BaseActor
|
22
25
|
|
@@ -27,8 +30,12 @@ module CelluloidPubsub
|
|
27
30
|
# The name of the default adapter
|
28
31
|
CLASSIC_ADAPTER = 'classic'
|
29
32
|
|
30
|
-
attr_accessor :server_options, :subscribers, :mutex
|
33
|
+
attr_accessor :server_options, :subscribers, :mutex, :timers_mutex
|
34
|
+
|
35
|
+
attr_reader :reactors
|
36
|
+
|
31
37
|
finalizer :shutdown
|
38
|
+
trap_exit :actor_died
|
32
39
|
# receives a list of options that are used to configure the webserver
|
33
40
|
#
|
34
41
|
# @param [Hash] options the options that can be used to connect to webser and send additional data
|
@@ -47,8 +54,11 @@ module CelluloidPubsub
|
|
47
54
|
@server_options = parse_options(options)
|
48
55
|
@subscribers = {}
|
49
56
|
@mutex = Mutex.new
|
57
|
+
@timers_mutex = Mutex.new
|
58
|
+
@shutting_down = false
|
59
|
+
@reactors = []
|
50
60
|
setup_celluloid_logger
|
51
|
-
|
61
|
+
log_debug "CelluloidPubsub::WebServer example starting on #{hostname}:#{port}"
|
52
62
|
super(hostname, port, { spy: spy, backlog: backlog }, &method(:on_connection))
|
53
63
|
end
|
54
64
|
|
@@ -80,7 +90,7 @@ module CelluloidPubsub
|
|
80
90
|
# @return [Hash] return the socket families available as keys in the hash
|
81
91
|
#
|
82
92
|
# @api public
|
83
|
-
# rubocop:disable ClassVars
|
93
|
+
# rubocop:disable Style/ClassVars
|
84
94
|
def self.socket_families
|
85
95
|
@@socket_families ||= Hash[*socket_infos.map { |af, *_| af }.uniq.zip([]).flatten]
|
86
96
|
end
|
@@ -99,7 +109,7 @@ module CelluloidPubsub
|
|
99
109
|
port
|
100
110
|
end
|
101
111
|
end
|
102
|
-
# rubocop:enable ClassVars
|
112
|
+
# rubocop:enable Style/ClassVars
|
103
113
|
|
104
114
|
# this method is overriden from the Reel::Server::HTTP in order to set the spy to the celluloid logger
|
105
115
|
# before the connection is accepted.
|
@@ -107,9 +117,24 @@ module CelluloidPubsub
|
|
107
117
|
# @api public
|
108
118
|
def run
|
109
119
|
@spy = Celluloid.logger if spy
|
120
|
+
async.bind_timers
|
110
121
|
loop { async.handle_connection @server.accept }
|
111
122
|
end
|
112
123
|
|
124
|
+
# the method will run indefinitely and will check if are there
|
125
|
+
# any unpublished messages that can be send to new subscribers
|
126
|
+
#
|
127
|
+
# @param [Boolean] run FLag to control if the server should try checking
|
128
|
+
# if there are any unpublished messages that need to be sent
|
129
|
+
#
|
130
|
+
# @return [void]
|
131
|
+
#
|
132
|
+
# @api public
|
133
|
+
def bind_timers(run = false)
|
134
|
+
try_sending_unpublished if run
|
135
|
+
after(0.1) { bind_timers(true) }
|
136
|
+
end
|
137
|
+
|
113
138
|
# the method will return true if redis can be used otherwise false
|
114
139
|
#
|
115
140
|
#
|
@@ -121,6 +146,16 @@ module CelluloidPubsub
|
|
121
146
|
@adapter.present? ? @adapter : CelluloidPubsub::WebServer::CLASSIC_ADAPTER
|
122
147
|
end
|
123
148
|
|
149
|
+
# the method will return true if the actor is shutting down
|
150
|
+
#
|
151
|
+
#
|
152
|
+
# @return [Boolean] returns true if the actor is shutting down
|
153
|
+
#
|
154
|
+
# @api public
|
155
|
+
def shutting_down?
|
156
|
+
@shutting_down == true
|
157
|
+
end
|
158
|
+
|
124
159
|
# the method will return true if debug is enabled otherwise false
|
125
160
|
#
|
126
161
|
#
|
@@ -139,7 +174,11 @@ module CelluloidPubsub
|
|
139
174
|
#
|
140
175
|
# @api public
|
141
176
|
def shutdown
|
142
|
-
|
177
|
+
@shutting_down = true
|
178
|
+
log_debug "#{self.class} tries to 'shutdown'"
|
179
|
+
reactors.each do |reactor|
|
180
|
+
reactor.terminate unless actor_dead?(reactor)
|
181
|
+
end
|
143
182
|
terminate
|
144
183
|
end
|
145
184
|
|
@@ -153,6 +192,15 @@ module CelluloidPubsub
|
|
153
192
|
@log_file_path = @server_options.fetch('log_file_path', nil)
|
154
193
|
end
|
155
194
|
|
195
|
+
# the method will return the log level of the logger
|
196
|
+
#
|
197
|
+
# @return [Integer, nil] return the log level used by the logger ( default is 1 - info)
|
198
|
+
#
|
199
|
+
# @api public
|
200
|
+
def log_level
|
201
|
+
@log_level ||= @server_options['log_level'] || ::Logger::Severity::INFO
|
202
|
+
end
|
203
|
+
|
156
204
|
# the method will return the hostname on which the server is running on
|
157
205
|
#
|
158
206
|
#
|
@@ -219,7 +267,7 @@ module CelluloidPubsub
|
|
219
267
|
def on_connection(connection)
|
220
268
|
while request = connection.request
|
221
269
|
if request.websocket?
|
222
|
-
log_debug "#{self.class} Received a WebSocket connection"
|
270
|
+
log_debug "#{self.class} Received a WebSocket connection #{request.websocket.url}"
|
223
271
|
|
224
272
|
# We're going to hand off this connection to another actor (Writer/Reader)
|
225
273
|
# However, initially Reel::Connections are "attached" to the
|
@@ -294,6 +342,23 @@ module CelluloidPubsub
|
|
294
342
|
end
|
295
343
|
end
|
296
344
|
|
345
|
+
# this method will know when a client has successfully registered
|
346
|
+
# and will write to the socket all messages that were published
|
347
|
+
# to that channel before the actor subscribed
|
348
|
+
#
|
349
|
+
# @return [void]
|
350
|
+
#
|
351
|
+
# @api publicsCelluloidPubsub::Registry.messages
|
352
|
+
def try_sending_unpublished
|
353
|
+
CelluloidPubsub::Registry.messages.each_key do |channel|
|
354
|
+
next if (clients = subscribers[channel]).blank?
|
355
|
+
clients.dup.pmap do |hash|
|
356
|
+
hash[:reactor].send_unpublished(channel)
|
357
|
+
end
|
358
|
+
clients.last[:reactor].clear_unpublished_messages(channel)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
297
362
|
# If the message can be parsed into a Hash it will respond to the reactor's websocket connection with the same message in JSON format
|
298
363
|
# otherwise will try send the message how it is and escaped into JSON format
|
299
364
|
#
|
@@ -309,5 +374,18 @@ module CelluloidPubsub
|
|
309
374
|
final_data = message.present? && message.is_a?(Hash) ? message.to_json : data.to_json
|
310
375
|
reactor.websocket << final_data
|
311
376
|
end
|
377
|
+
|
378
|
+
# method called when the actor is exiting
|
379
|
+
#
|
380
|
+
# @param [actor] actor - the current actor
|
381
|
+
# @param [Hash] reason - the reason it crashed
|
382
|
+
#
|
383
|
+
# @return [void]
|
384
|
+
#
|
385
|
+
# @api public
|
386
|
+
def actor_died(actor, reason)
|
387
|
+
@shutting_down = true
|
388
|
+
log_debug "Oh no! #{actor.inspect} has died because of a #{reason.class}"
|
389
|
+
end
|
312
390
|
end
|
313
391
|
end
|