celluloid_pubsub 0.9.0 → 1.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 +4 -4
- data/.gitignore +1 -0
- data/.reek +8 -1
- data/.rubocop.yml +6 -1
- data/celluloid_pubsub.gemspec +3 -2
- data/examples/simple_test.rb +4 -4
- data/gemfiles/celluloid_0.16.0.gemfile +8 -0
- data/gemfiles/celluloid_0.17.3.gemfile +8 -0
- data/init.rb +2 -0
- data/lib/celluloid_pubsub.rb +2 -0
- data/lib/celluloid_pubsub/base_actor.rb +42 -9
- data/lib/celluloid_pubsub/client.rb +15 -8
- data/lib/celluloid_pubsub/gem_version_parser.rb +47 -0
- data/lib/celluloid_pubsub/helper.rb +40 -7
- data/lib/celluloid_pubsub/initializers/reel_colors.rb +3 -1
- data/lib/celluloid_pubsub/reactor.rb +67 -26
- data/lib/celluloid_pubsub/registry.rb +6 -2
- data/lib/celluloid_pubsub/version.rb +5 -3
- data/lib/celluloid_pubsub/web_server.rb +43 -25
- data/spec/spec_helper.rb +1 -1
- metadata +6 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bdde06fb1422bf75d45e6f83706c695288d9c42e
|
4
|
+
data.tar.gz: f98a1a07331fbc7fcb67ee168191c0e4510b5181
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 02f4c5e864fa97fa3cffbb2cdf30f0f5dddf7f6341c2b042b247cbc75209118feb79cb9570ebae48f7e7ac6928a3ebdf1df7247523001f84a0d4bf04873d25c9
|
7
|
+
data.tar.gz: b8e905df5512a160194ea0ea13e0034c62ffbaa6b05031fa63df6f7c3d2af8384b49eba3e12a2092ffefd343e28061a5823319094c754576fe086e4ccafe1ba2
|
data/.gitignore
CHANGED
data/.reek
CHANGED
@@ -7,5 +7,12 @@ TooManyMethods:
|
|
7
7
|
enabled: false
|
8
8
|
UtilityFunction:
|
9
9
|
enabled: false
|
10
|
+
ManualDispatch:
|
11
|
+
enabled: false
|
12
|
+
InstanceVariableAssumption:
|
13
|
+
enabled: false
|
14
|
+
ClassVariable:
|
15
|
+
enabled: false
|
10
16
|
exclude_paths:
|
11
|
-
|
17
|
+
- examples/**/**
|
18
|
+
- spec/**/**
|
data/.rubocop.yml
CHANGED
data/celluloid_pubsub.gemspec
CHANGED
@@ -13,9 +13,10 @@ Gem::Specification.new do |s|
|
|
13
13
|
|
14
14
|
s.licenses = ['MIT']
|
15
15
|
s.files = `git ls-files`.split("\n")
|
16
|
-
s.test_files
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split('\n').map{ |f| File.basename(f) }
|
17
18
|
s.require_paths = ['lib']
|
18
|
-
|
19
|
+
|
19
20
|
s.add_runtime_dependency 'celluloid', '>= 0.16', '>= 0.16.0'
|
20
21
|
s.add_runtime_dependency 'celluloid-io', '>= 0.16', '>= 0.16.2'
|
21
22
|
s.add_runtime_dependency 'reel', '~> 0.6', '>= 0.6.0'
|
data/examples/simple_test.rb
CHANGED
@@ -15,10 +15,10 @@ class FirstActor
|
|
15
15
|
|
16
16
|
def on_message(message)
|
17
17
|
if @client.succesfull_subscription?(message)
|
18
|
-
puts "subscriber got successful subscription #{message
|
18
|
+
puts "subscriber got successful subscription #{message}"
|
19
19
|
@client.publish('test_channel2', 'data' => ' subscriber got successfull subscription') # the message needs to be a Hash
|
20
20
|
else
|
21
|
-
puts "subscriber got message #{message
|
21
|
+
puts "subscriber got message #{message}"
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -40,10 +40,10 @@ class SecondActor
|
|
40
40
|
|
41
41
|
def on_message(message)
|
42
42
|
if @client.succesfull_subscription?(message)
|
43
|
-
puts "publisher got successful subscription #{message
|
43
|
+
puts "publisher got successful subscription #{message}"
|
44
44
|
@client.publish('test_channel', 'data' => ' my_message') # the message needs to be a Hash
|
45
45
|
else
|
46
|
-
puts "publisher got message #{message
|
46
|
+
puts "publisher got message #{message}"
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
data/init.rb
CHANGED
data/lib/celluloid_pubsub.rb
CHANGED
@@ -1,25 +1,44 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
1
3
|
require_relative './helper'
|
2
4
|
module CelluloidPubsub
|
3
5
|
# base actor used for compatibility between celluloid versions
|
6
|
+
# @!attribute [r] config
|
7
|
+
# @return [Hash] The configuration classes and their aliases
|
4
8
|
module BaseActor
|
5
|
-
|
6
9
|
class << self
|
7
10
|
include Helper
|
8
|
-
attr_reader :config
|
9
11
|
|
12
|
+
# includes all the required modules in the class that includes this module
|
13
|
+
# @param [Class] base the class that will be used to include the required modules into it
|
14
|
+
# @return [void]
|
15
|
+
#
|
16
|
+
# @api public
|
10
17
|
def included(base)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
18
|
+
[
|
19
|
+
Celluloid,
|
20
|
+
Celluloid::IO,
|
21
|
+
CelluloidPubsub::Helper,
|
22
|
+
config['logger_class']
|
23
|
+
].each do |module_name|
|
24
|
+
base.send(:include, module_name)
|
25
|
+
end
|
15
26
|
end
|
16
27
|
|
28
|
+
# returns the configuration classes and their aliases for celluloid
|
29
|
+
# @return [Hash] returns the configuration classes and their aliases for celluloid
|
30
|
+
#
|
31
|
+
# @api public
|
17
32
|
def config
|
18
33
|
{
|
19
34
|
'logger_class' => celluloid_logger_class
|
20
35
|
}
|
21
36
|
end
|
22
37
|
|
38
|
+
# returns the logger class from celluloid depending on version
|
39
|
+
# @return [Class] returns the logger class from celluloid depending on version
|
40
|
+
#
|
41
|
+
# @api public
|
23
42
|
def celluloid_logger_class
|
24
43
|
if version_less_than_seventeen?
|
25
44
|
Celluloid::Logger
|
@@ -28,22 +47,36 @@ module CelluloidPubsub
|
|
28
47
|
end
|
29
48
|
end
|
30
49
|
|
50
|
+
# returns the celluloid version loaded
|
51
|
+
# @return [String] returns the celluloid version loaded
|
52
|
+
#
|
53
|
+
# @api public
|
31
54
|
def celluloid_version
|
32
55
|
find_loaded_gem_property('celluloid', 'version')
|
33
56
|
end
|
34
57
|
|
58
|
+
# returns true if celluloid version less than 0.17, otherwise false
|
59
|
+
# @return [Boolean] returns true if celluloid version less than 0.17, otherwise false
|
60
|
+
#
|
61
|
+
# @api public
|
35
62
|
def version_less_than_seventeen?
|
36
63
|
verify_gem_version(celluloid_version, '0.17', operator: '<')
|
37
64
|
end
|
38
65
|
|
66
|
+
# sets up the actor supervision based on celluloid version
|
67
|
+
# @param [Class] class_name The class that will be used to supervise the actor
|
68
|
+
# @param [Hash] options Additional options needed for supervision
|
69
|
+
# @return [void]
|
70
|
+
#
|
71
|
+
# @api public
|
39
72
|
def setup_actor_supervision(class_name, options)
|
73
|
+
actor_name, args = options.slice(:actor_name, :args).values
|
40
74
|
if version_less_than_seventeen?
|
41
|
-
class_name.supervise_as(
|
75
|
+
class_name.supervise_as(actor_name, args)
|
42
76
|
else
|
43
|
-
class_name.supervise(as:
|
77
|
+
class_name.supervise(as: actor_name, args: [args].compact)
|
44
78
|
end
|
45
79
|
end
|
46
|
-
|
47
80
|
end
|
48
81
|
end
|
49
82
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
1
3
|
require_relative './helper'
|
2
4
|
module CelluloidPubsub
|
3
5
|
# worker that subscribes to a channel or publishes to a channel
|
@@ -15,8 +17,18 @@ module CelluloidPubsub
|
|
15
17
|
class Client
|
16
18
|
include CelluloidPubsub::BaseActor
|
17
19
|
|
20
|
+
# The actor that made the connection
|
21
|
+
# @return [Celluloid::Actor] actor to which callbacks will be delegated to
|
22
|
+
attr_accessor :actor
|
23
|
+
|
24
|
+
# options that can be used to connect to webser and send additional data
|
25
|
+
# @return [Hash] the options that can be used to connect to webser and send additional data
|
26
|
+
attr_accessor :options
|
27
|
+
|
28
|
+
# The channel to which the client will subscribe to once the connection is open
|
29
|
+
# @return [String] The channel to which the client will subscribe to
|
30
|
+
attr_accessor :channel
|
18
31
|
|
19
|
-
attr_accessor :actor, :options, :channel
|
20
32
|
finalizer :shutdown
|
21
33
|
# receives a list of options that are used to connect to the webserver and an actor to which the callbacks are delegated to
|
22
34
|
# when receiving messages from a channel
|
@@ -88,7 +100,7 @@ module CelluloidPubsub
|
|
88
100
|
#
|
89
101
|
# @api public
|
90
102
|
def port
|
91
|
-
@port ||= @options.fetch('port', nil) ||
|
103
|
+
@port ||= @options.fetch('port', nil) || CelluloidPubsub::WebServer.find_unused_port
|
92
104
|
end
|
93
105
|
|
94
106
|
# the method will return the path of the URL on which the servers acccepts the connection
|
@@ -253,12 +265,7 @@ module CelluloidPubsub
|
|
253
265
|
#
|
254
266
|
# @api private
|
255
267
|
def chat(message)
|
256
|
-
final_message =
|
257
|
-
if message.is_a?(Hash)
|
258
|
-
final_message = message.to_json
|
259
|
-
else
|
260
|
-
final_message = JSON.dump(action: 'message', message: message)
|
261
|
-
end
|
268
|
+
final_message = message.is_a?(Hash) ? message.to_json : JSON.dump(action: 'message', message: message)
|
262
269
|
log_debug("#{@actor.class} sends JSON #{final_message}")
|
263
270
|
connection.text final_message
|
264
271
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module CelluloidPubsub
|
3
|
+
# class used for parsing gem versions
|
4
|
+
# @!attribute [r] version
|
5
|
+
# @return [String, Integer] version that needs parsing
|
6
|
+
#
|
7
|
+
# @!attribute [r] options
|
8
|
+
# @return [Hash] The additional options for parsing the version
|
9
|
+
class GemVersionParser
|
10
|
+
attr_reader :version
|
11
|
+
attr_reader :options
|
12
|
+
|
13
|
+
# receives the version and the additional options
|
14
|
+
#
|
15
|
+
# @param [String, Integer] version the version that needs parsing
|
16
|
+
# @param [Hash] options The additional options for parsing the version
|
17
|
+
#
|
18
|
+
# @return [void]
|
19
|
+
#
|
20
|
+
# @api public
|
21
|
+
#
|
22
|
+
# :nocov:
|
23
|
+
def initialize(version, options = {})
|
24
|
+
@version = version
|
25
|
+
@options = options.is_a?(Hash) ? options : {}
|
26
|
+
end
|
27
|
+
|
28
|
+
# parses the version and returns the version with a single decimal point by default
|
29
|
+
# @return [Float]
|
30
|
+
#
|
31
|
+
# @api public
|
32
|
+
def parsed_number
|
33
|
+
return 0 if @version.blank?
|
34
|
+
@version_array = @version.to_s.split('.')
|
35
|
+
number_with_single_decimal_point if @version_array.size > 2
|
36
|
+
@version_array.join('.').to_f
|
37
|
+
end
|
38
|
+
|
39
|
+
# pops from the version array elements until its size is 2
|
40
|
+
# @return [void]
|
41
|
+
#
|
42
|
+
# @api public
|
43
|
+
def number_with_single_decimal_point
|
44
|
+
@version_array.pop until @version_array.size == 2
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require_relative './gem_version_parser'
|
1
4
|
module CelluloidPubsub
|
2
5
|
# class that holds the options that are configurable for this gem
|
3
6
|
module Helper
|
@@ -12,31 +15,61 @@ module CelluloidPubsub
|
|
12
15
|
message.is_a?(Hash) && message['client_action'] == 'successful_subscription'
|
13
16
|
end
|
14
17
|
|
15
|
-
|
18
|
+
module_function
|
16
19
|
|
20
|
+
# returns the gem's property from its speification or nil
|
21
|
+
# @param [String] name the name of the gem
|
22
|
+
# @param [String] property name of the property we want
|
23
|
+
#
|
24
|
+
# @return [String, nil] returns the version of the gem
|
25
|
+
#
|
26
|
+
# @api public
|
17
27
|
def find_loaded_gem(name, property = nil)
|
18
28
|
gem_spec = Gem.loaded_specs.values.find { |repo| repo.name == name }
|
19
29
|
gem_spec.present? && property.present? ? gem_spec.send(property) : gem_spec
|
20
30
|
end
|
21
31
|
|
32
|
+
# returns the gem's property from its speification or nil
|
33
|
+
# @param [String] gem_name name of the gem
|
34
|
+
# @param [String] property name of the property we want
|
35
|
+
#
|
36
|
+
# @return [String, nil] returns the version of the gem
|
37
|
+
#
|
38
|
+
# @api public
|
22
39
|
def find_loaded_gem_property(gem_name, property = 'version')
|
23
40
|
find_loaded_gem(gem_name, property)
|
24
41
|
end
|
25
42
|
|
43
|
+
# returns the parsed version of the gem
|
44
|
+
# @param [String] gem_name name of the gem
|
45
|
+
#
|
46
|
+
# @return [Float, nil] returns the version of the gem
|
47
|
+
#
|
48
|
+
# @api public
|
26
49
|
def fetch_gem_version(gem_name)
|
27
50
|
version = find_loaded_gem_property(gem_name)
|
28
51
|
version.blank? ? nil : get_parsed_version(version)
|
29
52
|
end
|
30
53
|
|
54
|
+
# returns the parsed version as a float or nil
|
55
|
+
# @param [String] version the version that needs to be parsed
|
56
|
+
#
|
57
|
+
# @return [Float, nil] returns the version of the gem
|
58
|
+
#
|
59
|
+
# @api public
|
31
60
|
def get_parsed_version(version)
|
32
|
-
|
33
|
-
|
34
|
-
if version.size > 2
|
35
|
-
version.pop until version.size == 2
|
36
|
-
end
|
37
|
-
version.join('.').to_f
|
61
|
+
version_parser = CelluloidPubsub::GemVersionParser.new(version)
|
62
|
+
version_parser.parsed_number
|
38
63
|
end
|
39
64
|
|
65
|
+
# returns true if gem_version is less or equal to the specified version, otherwise false
|
66
|
+
# @param [String] gem_version the version of the gem
|
67
|
+
# @param [String] version the version that will be checked against
|
68
|
+
# @param [Hash] options additional options
|
69
|
+
#
|
70
|
+
# @return [Boolean] returns true if gem_version is less or equal to the specified version, otherwise false
|
71
|
+
#
|
72
|
+
# @api public
|
40
73
|
def verify_gem_version(gem_version, version, options = {})
|
41
74
|
options.stringify_keys!
|
42
75
|
version = get_parsed_version(version)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
1
3
|
require_relative './registry'
|
2
4
|
require_relative './helper'
|
3
5
|
module CelluloidPubsub
|
@@ -15,7 +17,21 @@ module CelluloidPubsub
|
|
15
17
|
class Reactor
|
16
18
|
include CelluloidPubsub::BaseActor
|
17
19
|
|
18
|
-
|
20
|
+
# available actions that can be delegated
|
21
|
+
AVAILABLE_ACTIONS = %w(unsubscribe_clients unsubscribe subscribe publish unsubscribe_all).freeze
|
22
|
+
|
23
|
+
# The websocket connection received from the server
|
24
|
+
# @return [Reel::WebSocket] websocket connection
|
25
|
+
attr_accessor :websocket
|
26
|
+
|
27
|
+
# The server instance to which this reactor is linked to
|
28
|
+
# @return [CelluloidPubsub::Webserver] the server actor to which the reactor is connected to
|
29
|
+
attr_accessor :server
|
30
|
+
|
31
|
+
# The channels to which this reactor has subscribed to
|
32
|
+
# @return [Array] array of channels to which the current reactor has subscribed to
|
33
|
+
attr_accessor :channels
|
34
|
+
|
19
35
|
finalizer :shutdown
|
20
36
|
# rececives a new socket connection from the server
|
21
37
|
# and listens for messages
|
@@ -163,21 +179,9 @@ module CelluloidPubsub
|
|
163
179
|
#
|
164
180
|
# @api public
|
165
181
|
def delegate_action(json_data)
|
166
|
-
channel = json_data.
|
167
|
-
|
168
|
-
|
169
|
-
unsubscribe_all
|
170
|
-
when 'unsubscribe_clients'
|
171
|
-
async.unsubscribe_clients(channel)
|
172
|
-
when 'unsubscribe'
|
173
|
-
async.unsubscribe(channel)
|
174
|
-
when 'subscribe'
|
175
|
-
async.start_subscriber(channel, json_data)
|
176
|
-
when 'publish'
|
177
|
-
async.publish_event(channel, json_data['data'].to_json)
|
178
|
-
else
|
179
|
-
handle_unknown_action(json_data)
|
180
|
-
end
|
182
|
+
channel, client_action = json_data.slice('channel', 'client_action').values
|
183
|
+
return unless CelluloidPubsub::Reactor::AVAILABLE_ACTIONS.include?(client_action)
|
184
|
+
async.send(client_action, channel, json_data)
|
181
185
|
end
|
182
186
|
|
183
187
|
# the method will delegate the message to the server in an asyncronous way by sending the current actor and the message
|
@@ -188,8 +192,8 @@ module CelluloidPubsub
|
|
188
192
|
# @return [void]
|
189
193
|
#
|
190
194
|
# @api public
|
191
|
-
def handle_unknown_action(json_data)
|
192
|
-
log_debug "Trying to dispatch to server #{json_data}"
|
195
|
+
def handle_unknown_action(channel, json_data)
|
196
|
+
log_debug "Trying to dispatch to server #{json_data} on channel #{channel}"
|
193
197
|
@server.async.handle_dispatched_message(Actor.current, json_data)
|
194
198
|
end
|
195
199
|
|
@@ -217,10 +221,21 @@ module CelluloidPubsub
|
|
217
221
|
# @return [void]
|
218
222
|
#
|
219
223
|
# @api public
|
220
|
-
def unsubscribe(channel)
|
224
|
+
def unsubscribe(channel, _json_data)
|
221
225
|
log_debug "#{self.class} runs 'unsubscribe' method with #{channel}"
|
222
226
|
return unless channel.present?
|
223
227
|
forget_channel(channel)
|
228
|
+
delete_server_subscribers(channel)
|
229
|
+
end
|
230
|
+
|
231
|
+
# the method will delete the reactor from the channel list on the server
|
232
|
+
#
|
233
|
+
# @param [String] channel
|
234
|
+
#
|
235
|
+
# @return [void]
|
236
|
+
#
|
237
|
+
# @api public
|
238
|
+
def delete_server_subscribers(channel)
|
224
239
|
@server.mutex.synchronize do
|
225
240
|
(@server.subscribers[channel] || []).delete_if do |hash|
|
226
241
|
hash[:reactor] == Actor.current
|
@@ -235,7 +250,7 @@ module CelluloidPubsub
|
|
235
250
|
# @return [void]
|
236
251
|
#
|
237
252
|
# @api public
|
238
|
-
def unsubscribe_clients(channel)
|
253
|
+
def unsubscribe_clients(channel, _json_data)
|
239
254
|
log_debug "#{self.class} runs 'unsubscribe_clients' method with #{channel}"
|
240
255
|
return if channel.blank?
|
241
256
|
unsubscribe_from_channel(channel)
|
@@ -265,7 +280,7 @@ module CelluloidPubsub
|
|
265
280
|
# @return [void]
|
266
281
|
#
|
267
282
|
# @api public
|
268
|
-
def
|
283
|
+
def subscribe(channel, message)
|
269
284
|
return unless channel.present?
|
270
285
|
add_subscriber_to_channel(channel, message)
|
271
286
|
log_debug "#{self.class} subscribed to #{channel} with #{message}"
|
@@ -305,28 +320,44 @@ module CelluloidPubsub
|
|
305
320
|
# method for publishing data to a channel
|
306
321
|
#
|
307
322
|
# @param [String] current_topic The Channel to which the reactor instance {CelluloidPubsub::Reactor} will publish the message to
|
308
|
-
# @param [Object] message
|
323
|
+
# @param [Object] json_data The additional data that contains the message that needs to be sent
|
309
324
|
#
|
310
325
|
# @return [void]
|
311
326
|
#
|
312
327
|
# @api public
|
313
|
-
def
|
328
|
+
def publish(current_topic, json_data)
|
329
|
+
message = json_data['data'].to_json
|
314
330
|
return if current_topic.blank? || message.blank?
|
331
|
+
server_pusblish_event(current_topic, message)
|
332
|
+
rescue => exception
|
333
|
+
log_debug("could not publish message #{message} into topic #{current_topic} because of #{exception.inspect}")
|
334
|
+
end
|
335
|
+
|
336
|
+
# the method will publish to all subsribers of a channel a message
|
337
|
+
#
|
338
|
+
# @param [String] current_topic
|
339
|
+
# @param [#to_s] message
|
340
|
+
#
|
341
|
+
# @return [void]
|
342
|
+
#
|
343
|
+
# @api public
|
344
|
+
def server_pusblish_event(current_topic, message)
|
315
345
|
@server.mutex.synchronize do
|
316
346
|
(@server.subscribers[current_topic].dup || []).pmap do |hash|
|
317
347
|
hash[:reactor].websocket << message
|
318
348
|
end
|
319
349
|
end
|
320
|
-
rescue => exception
|
321
|
-
log_debug("could not publish message #{message} into topic #{current_topic} because of #{exception.inspect}")
|
322
350
|
end
|
323
351
|
|
324
352
|
# unsubscribes all actors from all channels and terminates the curent actor
|
325
353
|
#
|
354
|
+
# @param [String] _channel NOT USED - needed to maintain compatibility with the other methods
|
355
|
+
# @param [Object] _json_data NOT USED - needed to maintain compatibility with the other methods
|
356
|
+
#
|
326
357
|
# @return [void]
|
327
358
|
#
|
328
359
|
# @api public
|
329
|
-
def unsubscribe_all
|
360
|
+
def unsubscribe_all(_channel, _json_data)
|
330
361
|
log_debug "#{self.class} runs 'unsubscribe_all' method"
|
331
362
|
CelluloidPubsub::Registry.channels.dup.pmap do |channel|
|
332
363
|
unsubscribe_clients(channel)
|
@@ -343,6 +374,16 @@ module CelluloidPubsub
|
|
343
374
|
# @api public
|
344
375
|
def unsubscribe_from_channel(channel)
|
345
376
|
log_debug "#{self.class} runs 'unsubscribe_from_channel' method with #{channel}"
|
377
|
+
server_kill_reactors(channel)
|
378
|
+
end
|
379
|
+
|
380
|
+
# kills all reactors registered on a channel and closes their websocket connection
|
381
|
+
#
|
382
|
+
# @param [String] channel
|
383
|
+
# @return [void]
|
384
|
+
#
|
385
|
+
# @api public
|
386
|
+
def server_kill_reactors(channel)
|
346
387
|
@server.mutex.synchronize do
|
347
388
|
(@server.subscribers[channel].dup || []).pmap do |hash|
|
348
389
|
reactor = hash[:reactor]
|
@@ -1,9 +1,13 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
1
3
|
module CelluloidPubsub
|
2
4
|
# class used to register new channels and save them in memory
|
5
|
+
# @attr channels
|
6
|
+
# @return [Array] array of channels to which actors have subscribed to
|
3
7
|
class Registry
|
4
8
|
class << self
|
5
|
-
#
|
6
|
-
#
|
9
|
+
# The channels that the server can handle
|
10
|
+
# @return [Array] array of channels to which actors have subscribed to
|
7
11
|
attr_accessor :channels
|
8
12
|
end
|
9
13
|
@channels = []
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
1
3
|
# Returns the version of the gem as a <tt>Gem::Version</tt>
|
2
4
|
module CelluloidPubsub
|
3
5
|
# it prints the gem version as a string
|
@@ -13,14 +15,14 @@ module CelluloidPubsub
|
|
13
15
|
# provides a easy way of getting the major, minor and tiny
|
14
16
|
module VERSION
|
15
17
|
# major release version
|
16
|
-
MAJOR =
|
18
|
+
MAJOR = 1
|
17
19
|
# minor release version
|
18
|
-
MINOR =
|
20
|
+
MINOR = 0
|
19
21
|
# tiny release version
|
20
22
|
TINY = 0
|
21
23
|
# prelease version ( set this only if it is a prelease)
|
22
24
|
PRE = nil
|
23
|
-
|
25
|
+
|
24
26
|
# generates the version string
|
25
27
|
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
26
28
|
end
|
@@ -1,18 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
1
3
|
require_relative './reactor'
|
2
4
|
require_relative './helper'
|
3
5
|
module CelluloidPubsub
|
4
6
|
# webserver to which socket connects should connect to .
|
5
7
|
# the server will dispatch each request into a new Reactor
|
6
8
|
# which will handle the action based on the message
|
7
|
-
#
|
9
|
+
# @attr server_options
|
8
10
|
# @return [Hash] options used to configure the webserver
|
9
|
-
# @option
|
10
|
-
# @option
|
11
|
-
# @option
|
12
|
-
# @option
|
11
|
+
# @option server_options [String]:hostname The hostname on which the webserver runs on
|
12
|
+
# @option server_options [Integer] :port The port on which the webserver runs on
|
13
|
+
# @option server_options [String] :path The request path that the webserver accepts
|
14
|
+
# @option server_options [Boolean] :spy Enable this only if you want to enable debugging for the webserver
|
13
15
|
#
|
14
|
-
#
|
16
|
+
# @attr subscribers
|
15
17
|
# @return [Hash] The hostname on which the webserver runs on
|
18
|
+
# @attr mutex
|
19
|
+
# @return [Mutex] The mutex that will synchronize actions on subscribers
|
16
20
|
class WebServer < Reel::Server::HTTP
|
17
21
|
include CelluloidPubsub::BaseActor
|
18
22
|
|
@@ -20,7 +24,7 @@ module CelluloidPubsub
|
|
20
24
|
HOST = '0.0.0.0'
|
21
25
|
# The request path that the webserver accepts by default
|
22
26
|
PATH = '/ws'
|
23
|
-
|
27
|
+
# The name of the default adapter
|
24
28
|
CLASSIC_ADAPTER = 'classic'
|
25
29
|
|
26
30
|
attr_accessor :server_options, :subscribers, :mutex
|
@@ -55,12 +59,30 @@ module CelluloidPubsub
|
|
55
59
|
#
|
56
60
|
# @api public
|
57
61
|
def self.open_socket_on_unused_port
|
58
|
-
|
59
|
-
|
62
|
+
return ::TCPServer.open('0.0.0.0', 0) if socket_families.key?('AF_INET')
|
63
|
+
return ::TCPServer.open('::', 0) if socket_families.key?('AF_INET6')
|
64
|
+
::TCPServer.open(0)
|
65
|
+
end
|
60
66
|
|
61
|
-
|
62
|
-
|
63
|
-
|
67
|
+
# the method will return the socket information available as an array
|
68
|
+
#
|
69
|
+
#
|
70
|
+
# @return [Array] return the socket information available as an array
|
71
|
+
#
|
72
|
+
# @api public
|
73
|
+
def self.socket_infos
|
74
|
+
::Socket::getaddrinfo('localhost', nil, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
|
75
|
+
end
|
76
|
+
|
77
|
+
# the method will return the socket families avaiable
|
78
|
+
#
|
79
|
+
#
|
80
|
+
# @return [Hash] return the socket families available as keys in the hash
|
81
|
+
#
|
82
|
+
# @api public
|
83
|
+
# rubocop:disable ClassVars
|
84
|
+
def self.socket_families
|
85
|
+
@@socket_families ||= Hash[*socket_infos.map { |af, *_| af }.uniq.zip([]).flatten]
|
64
86
|
end
|
65
87
|
|
66
88
|
# the method get from the socket connection that is already opened the port used.
|
@@ -77,6 +99,7 @@ module CelluloidPubsub
|
|
77
99
|
port
|
78
100
|
end
|
79
101
|
end
|
102
|
+
# rubocop:enable ClassVars
|
80
103
|
|
81
104
|
# this method is overriden from the Reel::Server::HTTP in order to set the spy to the celluloid logger
|
82
105
|
# before the connection is accepted.
|
@@ -105,7 +128,7 @@ module CelluloidPubsub
|
|
105
128
|
#
|
106
129
|
# @api public
|
107
130
|
def debug_enabled?
|
108
|
-
@debug_enabled = @server_options.fetch('enable_debug',
|
131
|
+
@debug_enabled = @server_options.fetch('enable_debug', true)
|
109
132
|
@debug_enabled == true
|
110
133
|
end
|
111
134
|
|
@@ -180,7 +203,6 @@ module CelluloidPubsub
|
|
180
203
|
@backlog = @server_options.fetch('backlog', 1024)
|
181
204
|
end
|
182
205
|
|
183
|
-
|
184
206
|
# callback that will execute when receiving new conections
|
185
207
|
# If the connections is a websocket will call method {#route_websocket}
|
186
208
|
# and if the connection is HTTP will call method {#route_request}
|
@@ -263,13 +285,13 @@ module CelluloidPubsub
|
|
263
285
|
#
|
264
286
|
# @api public
|
265
287
|
def route_websocket(reactor, socket)
|
266
|
-
|
267
|
-
|
288
|
+
url = socket.url
|
289
|
+
if url == path || url == '/?'
|
268
290
|
reactor.async.work(socket, Actor.current)
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
291
|
+
else
|
292
|
+
log_debug "Received invalid WebSocket request for: #{url}"
|
293
|
+
socket.close
|
294
|
+
end
|
273
295
|
end
|
274
296
|
|
275
297
|
# 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
|
@@ -284,11 +306,7 @@ module CelluloidPubsub
|
|
284
306
|
def handle_dispatched_message(reactor, data)
|
285
307
|
log_debug "#{self.class} trying to dispatch message #{data.inspect}"
|
286
308
|
message = reactor.parse_json_data(data)
|
287
|
-
|
288
|
-
final_data = message.to_json
|
289
|
-
else
|
290
|
-
final_data = data.to_json
|
291
|
-
end
|
309
|
+
final_data = message.present? && message.is_a?(Hash) ? message.to_json : data.to_json
|
292
310
|
reactor.websocket << final_data
|
293
311
|
end
|
294
312
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: celluloid_pubsub
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- bogdanRada
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-09-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: celluloid
|
@@ -361,10 +361,13 @@ files:
|
|
361
361
|
- Rakefile
|
362
362
|
- celluloid_pubsub.gemspec
|
363
363
|
- examples/simple_test.rb
|
364
|
+
- gemfiles/celluloid_0.16.0.gemfile
|
365
|
+
- gemfiles/celluloid_0.17.3.gemfile
|
364
366
|
- init.rb
|
365
367
|
- lib/celluloid_pubsub.rb
|
366
368
|
- lib/celluloid_pubsub/base_actor.rb
|
367
369
|
- lib/celluloid_pubsub/client.rb
|
370
|
+
- lib/celluloid_pubsub/gem_version_parser.rb
|
368
371
|
- lib/celluloid_pubsub/helper.rb
|
369
372
|
- lib/celluloid_pubsub/initializers/reel_colors.rb
|
370
373
|
- lib/celluloid_pubsub/reactor.rb
|
@@ -401,10 +404,5 @@ signing_key:
|
|
401
404
|
specification_version: 4
|
402
405
|
summary: CelluloidPubsub is a simple ruby implementation of publish subscribe design
|
403
406
|
patterns using celluloid actors and websockets, using Celluloid::Reel server
|
404
|
-
test_files:
|
405
|
-
- spec/lib/celluloid_pubsub/client_pubsub_spec.rb
|
406
|
-
- spec/lib/celluloid_pubsub/reactor_spec.rb
|
407
|
-
- spec/lib/celluloid_pubsub/registry_spec.rb
|
408
|
-
- spec/lib/celluloid_pubsub/web_server_spec.rb
|
409
|
-
- spec/spec_helper.rb
|
407
|
+
test_files: []
|
410
408
|
has_rdoc:
|