celluloid_pubsub 0.0.1

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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +2 -0
  3. data/.gitignore +16 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +68 -0
  6. data/.travis.yml +12 -0
  7. data/CONTRIBUTING.md +44 -0
  8. data/Gemfile +3 -0
  9. data/Guardfile +12 -0
  10. data/LICENSE +20 -0
  11. data/README.rdoc +96 -0
  12. data/Rakefile +42 -0
  13. data/bin/appraisal +16 -0
  14. data/bin/autospec +16 -0
  15. data/bin/bundler +16 -0
  16. data/bin/cdiff +16 -0
  17. data/bin/coderay +16 -0
  18. data/bin/colortab +16 -0
  19. data/bin/coveralls +16 -0
  20. data/bin/decolor +16 -0
  21. data/bin/erubis +16 -0
  22. data/bin/guard +16 -0
  23. data/bin/htmldiff +16 -0
  24. data/bin/ldiff +16 -0
  25. data/bin/listen +16 -0
  26. data/bin/nokogiri +16 -0
  27. data/bin/phare +16 -0
  28. data/bin/pry +16 -0
  29. data/bin/rackup +16 -0
  30. data/bin/rails +16 -0
  31. data/bin/rake +16 -0
  32. data/bin/restclient +16 -0
  33. data/bin/rspec +16 -0
  34. data/bin/rubocop +16 -0
  35. data/bin/ruby-parse +16 -0
  36. data/bin/ruby-rewrite +16 -0
  37. data/bin/sass +16 -0
  38. data/bin/sass-convert +16 -0
  39. data/bin/scss +16 -0
  40. data/bin/scss-lint +16 -0
  41. data/bin/term_display +16 -0
  42. data/bin/term_mandel +16 -0
  43. data/bin/thor +16 -0
  44. data/bin/yard +16 -0
  45. data/bin/yardoc +16 -0
  46. data/bin/yardstick +16 -0
  47. data/bin/yri +16 -0
  48. data/celluloid_pubsub.gemspec +39 -0
  49. data/init.rb +1 -0
  50. data/lib/celluloid_pubsub/client_pubsub.rb +71 -0
  51. data/lib/celluloid_pubsub/reactor.rb +114 -0
  52. data/lib/celluloid_pubsub/registry.rb +9 -0
  53. data/lib/celluloid_pubsub/version.rb +14 -0
  54. data/lib/celluloid_pubsub/web_server.rb +92 -0
  55. data/lib/celluloid_pubsub.rb +6 -0
  56. data/spec/lib/celluloid_pubsub/client_pubsub_spec.rb +9 -0
  57. data/spec/lib/celluloid_pubsub/reactor_spec.rb +6 -0
  58. data/spec/lib/celluloid_pubsub/registry_spec.rb +6 -0
  59. data/spec/lib/celluloid_pubsub/web_server_spec.rb +6 -0
  60. data/spec/spec_helper.rb +48 -0
  61. metadata +459 -0
data/bin/restclient ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'restclient' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rest-client', 'restclient')
data/bin/rspec ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rspec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rspec-core', 'rspec')
data/bin/rubocop ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rubocop' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rubocop', 'rubocop')
data/bin/ruby-parse ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'ruby-parse' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('parser', 'ruby-parse')
data/bin/ruby-rewrite ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'ruby-rewrite' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('parser', 'ruby-rewrite')
data/bin/sass ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'sass' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('sass', 'sass')
data/bin/sass-convert ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'sass-convert' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('sass', 'sass-convert')
data/bin/scss ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'scss' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('sass', 'scss')
data/bin/scss-lint ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'scss-lint' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('scss-lint', 'scss-lint')
data/bin/term_display ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'term_display' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('term-ansicolor', 'term_display')
data/bin/term_mandel ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'term_mandel' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('term-ansicolor', 'term_mandel')
data/bin/thor ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'thor' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('thor', 'thor')
data/bin/yard ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'yard' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('yard', 'yard')
data/bin/yardoc ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'yardoc' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('yard', 'yardoc')
data/bin/yardstick ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'yardstick' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('yardstick', 'yardstick')
data/bin/yri ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'yri' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('yard', 'yri')
@@ -0,0 +1,39 @@
1
+ require File.expand_path('../lib/celluloid_pubsub/version', __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'celluloid_pubsub'
5
+ s.version = CelluloidPubsub.gem_version
6
+ s.platform = Gem::Platform::RUBY
7
+ s.summary = 'CelluloidPubsub is a simple ruby implementation of publish subscribe design patterns using celluloid actors and websockets, using Celluloid::Reel server'
8
+ s.email = 'raoul_ice@yahoo.com'
9
+ s.homepage = 'http://github.com/bogdanRada/celluloid_pubsub/'
10
+ s.description = 'CelluloidPubsub is a simple ruby implementation of publish subscribe design patterns using celluloid actors and websockets, using Reel server for inter-process communication'
11
+ s.authors = ['bogdanRada']
12
+ s.date = Date.today
13
+
14
+ s.licenses = ['MIT']
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = s.files.grep(/^(spec)/)
17
+ s.require_paths = ['lib']
18
+
19
+ s.add_runtime_dependency 'celluloid', '~> 0.16.0', '>= 0.16.0'
20
+ s.add_runtime_dependency 'celluloid-io', '~> 0.16.2', '>= 0.16.2'
21
+ s.add_runtime_dependency 'reel', '~> 0.5.0', '>= 0.5.0'
22
+ s.add_runtime_dependency 'celluloid-websocket-client', '0.0.1'
23
+ s.add_runtime_dependency 'activesupport', '~> 4.2.0', '>= 4.2.0'
24
+
25
+ s.add_development_dependency 'rspec-rails', '~> 2.0', '>= 2.0'
26
+ s.add_development_dependency 'guard', '~> 2.6.1', '>= 2.6'
27
+ s.add_development_dependency 'guard-rspec', '~> 4.2.9', '>= 4.2'
28
+ s.add_development_dependency 'simplecov', '~> 0.9', '>= 0.9'
29
+ s.add_development_dependency 'simplecov-summary', '~> 0.0.4', '>= 0.0.4'
30
+ s.add_development_dependency 'mocha', '~> 1.1', '>= 1.1'
31
+ s.add_development_dependency 'coveralls', '~> 0.7', '>= 0.7'
32
+ s.add_development_dependency 'rvm-tester', '~> 1.1', '>= 1.1'
33
+
34
+ s.add_development_dependency 'rubocop', '0.29'
35
+ s.add_development_dependency 'phare', '~> 0.6', '>= 0.6'
36
+ s.add_development_dependency 'scss-lint', '~> 0.34', '>= 0.34'
37
+ s.add_development_dependency 'yard', '~> 0.8.7', '>= 0.8.7'
38
+ s.add_development_dependency 'yardstick', '~> 0.9.9', '>= 0.9.9'
39
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'celluloid_pubsub'
@@ -0,0 +1,71 @@
1
+ module CelluloidPubsub
2
+ class Client
3
+ class PubSubWorker
4
+ include Celluloid
5
+ include Celluloid::Logger
6
+ attr_reader :proc, :topic, :message
7
+
8
+ def initialize(options, &connect_blk)
9
+ options = options.stringify_keys!
10
+ @actor = options['actor'].present? ? options['actor'] : nil
11
+ raise "#{self}: Please provide an actor in the options list!!!" if @actor.blank?
12
+ @connect_blk = connect_blk
13
+ @client = Celluloid::WebSocket::Client.new("ws://#{CelluloidPubsub::WebServer::HOST}:#{CelluloidPubsub::WebServer::PORT}#{CelluloidPubsub::WebServer::PATH}", Actor.current)
14
+ end
15
+
16
+ def debug_enabled?
17
+ CelluloidPubsub::WebServer.debug_enabled?
18
+ end
19
+
20
+ def subscribe(channel)
21
+ subscription_data = { 'client_action' => 'subscribe', 'channel' => channel }
22
+ debug("#{self.class} tries to subscribe #{subscription_data}") if debug_enabled?
23
+ async.chat(subscription_data)
24
+ end
25
+
26
+ def publish(channel, data)
27
+ publishing_data = { 'client_action' => 'publish', 'channel' => channel, 'data' => data }
28
+ debug(" #{self.class} publishl to #{channel} message: #{publishing_data}") if debug_enabled?
29
+ async.chat(publishing_data)
30
+ end
31
+
32
+ def on_open
33
+ debug("#{self.class} websocket connection opened") if debug_enabled?
34
+ @connect_blk.call Actor.current
35
+ end
36
+
37
+ def on_message(data)
38
+ debug("#{self.class} received plain #{data}") if debug_enabled?
39
+ message = JSON.parse(data)
40
+ debug("#{self.class} received JSON #{message}") if debug_enabled?
41
+ @actor.async.on_message(message)
42
+ end
43
+
44
+ def on_close(code, reason)
45
+ @client.terminate
46
+ terminate
47
+ debug("#{self.class} dispatching on close #{code} #{reason}") if debug_enabled?
48
+ @actor.async.on_close(code, reason)
49
+ end
50
+
51
+ private
52
+
53
+ def chat(message)
54
+ final_message = nil
55
+ if message.is_a?(Hash)
56
+ debug("#{self.class} sends #{message.to_json}") if debug_enabled?
57
+ final_message = message.to_json
58
+ else
59
+ text_messsage = JSON.dump(action: 'message', message: message)
60
+ debug("#{self.class} sends JSON #{text_messsage}") if debug_enabled?
61
+ final_message = text_messsage
62
+ end
63
+ @client.text final_message
64
+ end
65
+ end
66
+
67
+ def self.connect(options = {}, &connect_blk)
68
+ CelluloidPubsub::Client::PubSubWorker.new(options, &connect_blk)
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,114 @@
1
+ require_relative './registry'
2
+ module CelluloidPubsub
3
+ class Reactor
4
+ include Celluloid
5
+ include Celluloid::IO
6
+ include Celluloid::Logger
7
+
8
+ attr_accessor :websocket, :server, :mutex
9
+
10
+ def work(websocket, server)
11
+ @server = server
12
+ @mutex = Mutex.new
13
+ @websocket = websocket
14
+ info "Streaming changes for #{websocket.url}" if @server.debug_enabled?
15
+ async.run
16
+ end
17
+
18
+ def run
19
+ while message = @websocket.read
20
+ handle_websocket_message(message)
21
+ end
22
+ end
23
+
24
+ def parse_json_data(message)
25
+ debug "Reactor read message #{message}" if @server.debug_enabled?
26
+ json_data = nil
27
+ begin
28
+ json_data = JSON.parse(message)
29
+ rescue => e
30
+ debug "Reactor could not parse #{message} because of #{e.inspect}" if @server.debug_enabled?
31
+ # do nothing
32
+ end
33
+ json_data = message if json_data.nil?
34
+ json_data
35
+ end
36
+
37
+ def handle_websocket_message(message)
38
+ json_data = parse_json_data(message)
39
+ handle_parsed_websocket_message(json_data)
40
+ end
41
+
42
+ def handle_parsed_websocket_message(json_data)
43
+ if json_data.is_a?(Hash)
44
+ json_data = json_data.stringify_keys
45
+ debug "Reactor finds actions for #{json_data}" if @server.debug_enabled?
46
+ delegate_action(json_data) if json_data['client_action'].present?
47
+ else
48
+ handle_unknown_action(json_data)
49
+ end
50
+ end
51
+
52
+ def delegate_action(json_data)
53
+ case json_data['client_action']
54
+ when 'unsubscribe_all'
55
+ unsubscribe_all
56
+ when 'unsubscribe'
57
+ async.unsubscribe_client(json_data['channel'])
58
+ when 'subscribe'
59
+ async.start_subscriber(json_data['channel'], json_data)
60
+ when 'publish'
61
+ @server.publish_event(json_data['channel'], json_data['data'].to_json)
62
+ else
63
+ handle_unknown_action(json_data)
64
+ end
65
+ end
66
+
67
+ def handle_unknown_action(json_data)
68
+ debug "Trying to dispatch to server #{json_data}" if @server.debug_enabled?
69
+ @server.async.handle_dispatched_message(Actor.current, json_data)
70
+ end
71
+
72
+ def unsubscribe_client(channel)
73
+ return unless channel.present?
74
+ @websocket.close
75
+ @server.unsubscribe_client(Actor.current, channel)
76
+ end
77
+
78
+ def shutdown
79
+ terminate
80
+ end
81
+
82
+ def start_subscriber(channel, message)
83
+ return unless channel.present?
84
+ @mutex.lock
85
+ begin
86
+ add_subscriber_to_channel(channel, message)
87
+ debug "Subscribed to #{channel} with #{message}" if @server.debug_enabled?
88
+ @websocket << message.merge('client_action' => 'successful_subscription', 'channel' => channel).to_json
89
+ rescue => e
90
+ raise [e, e.respond_to?(:backtrace) ? e.backtrace : '', channel, message].inspect
91
+ ensure
92
+ @mutex.unlock
93
+ end
94
+ end
95
+
96
+ def add_subscriber_to_channel(channel, message)
97
+ CelluloidPubsub::Registry.channels << channel unless CelluloidPubsub::Registry.channels.include?(channel)
98
+ @server.subscribers[channel] ||= []
99
+ @server.subscribers[channel] << { reactor: Actor.current, message: message }
100
+ end
101
+
102
+ def unsubscribe_all
103
+ CelluloidPubsub::Registry.channels.map do |channel|
104
+ @subscribers[channel].each do |hash|
105
+ hash[:reactor].websocket.close
106
+ end
107
+ @server.subscribers[channel] = []
108
+ end
109
+
110
+ info 'clearing connections' if @server.debug_enabled?
111
+ shutdown
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,9 @@
1
+ module CelluloidPubsub
2
+ class Registry
3
+ include ActiveSupport::Configurable
4
+ class << self
5
+ attr_accessor :channels
6
+ end
7
+ @channels = []
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ module CelluloidPubsub # Returns the version of the currently loaded Rails as a <tt>Gem::Version</tt>
2
+ def self.gem_version
3
+ Gem::Version.new VERSION::STRING
4
+ end
5
+
6
+ module VERSION
7
+ MAJOR = 0
8
+ MINOR = 0
9
+ TINY = 1
10
+ PRE = nil
11
+
12
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
13
+ end
14
+ end
@@ -0,0 +1,92 @@
1
+ require_relative './reactor'
2
+ module CelluloidPubsub
3
+ class WebServer < Reel::Server::HTTP
4
+ include Celluloid::Logger
5
+
6
+ HOST = '0.0.0.0'
7
+ PORT = 1234
8
+ PATH = '/ws'
9
+
10
+ attr_accessor :options, :subscribers, :backlog
11
+
12
+ def initialize(options = {})
13
+ parse_options(options)
14
+ @subscribers = {}
15
+ info "CelluloidPubsub::WebServer example starting on #{@hostname}:#{@port}" if debug_enabled?
16
+ super(@hostname, @port, { spy: @spy, backlog: @backlog }, &method(:on_connection))
17
+ end
18
+
19
+ def parse_options(options)
20
+ raise 'Options is not a hash or is not present ' unless options.is_a?(Hash)
21
+ @options = options.stringify_keys
22
+ @backlog = @options.fetch(:backlog, 1024)
23
+ @hostname = @options.fetch(:hostname, CelluloidPubsub::WebServer::HOST)
24
+ @port = @options.fetch(:port, CelluloidPubsub::WebServer::PORT)
25
+ @path = @options.fetch(:path, CelluloidPubsub::WebServer::PATH)
26
+ @spy = @options.fetch(:spy, false)
27
+ end
28
+
29
+ def debug_enabled?
30
+ self.class.debug_enabled?
31
+ end
32
+
33
+ def self.debug_enabled?
34
+ ENV['DEBUG_CELLULOID'].present? && (ENV['DEBUG_CELLULOID'] == 'true' || ENV['DEBUG_CELLULOID'] == true)
35
+ end
36
+
37
+ def publish_event(current_topic, message)
38
+ return if current_topic.blank? || message.blank?
39
+ @subscribers[current_topic].each do |hash|
40
+ hash[:reactor].websocket << message
41
+ end
42
+ end
43
+
44
+ def on_connection(connection)
45
+ while request = connection.request
46
+ if request.websocket?
47
+ info 'Received a WebSocket connection' if debug_enabled?
48
+
49
+ # We're going to hand off this connection to another actor (Writer/Reader)
50
+ # However, initially Reel::Connections are "attached" to the
51
+ # Reel::Server::HTTP actor, meaning that the server manages the connection
52
+ # lifecycle (e.g. error handling) for us.
53
+ #
54
+ # If we want to hand this connection off to another actor, we first
55
+ # need to detach it from the Reel::Server (in this case, Reel::Server::HTTP)
56
+ connection.detach
57
+ route_websocket(request.websocket)
58
+ return
59
+ else
60
+ route_request connection, request
61
+ end
62
+ end
63
+ end
64
+
65
+ def route_request(connection, request)
66
+ info "404 Not Found: #{request.path}" if debug_enabled?
67
+ connection.respond :not_found, 'Not found'
68
+ end
69
+
70
+ def route_websocket(socket)
71
+ if socket.url == @path
72
+ info 'Reactor handles new socket connection' if debug_enabled?
73
+ reactor = CelluloidPubsub::Reactor.new
74
+ Actor.current.link reactor
75
+ reactor.async.work(socket, Actor.current)
76
+ else
77
+ info "Received invalid WebSocket request for: #{socket.url}" if debug_enabled?
78
+ socket.close
79
+ end
80
+ end
81
+
82
+ def handle_dispatched_message(reactor, data)
83
+ debug "Webserver trying to dispatch message #{data.inspect}" if debug_enabled?
84
+ message = reactor.parse_json_data(data)
85
+ if message.present? && message.is_a?(Hash)
86
+ reactor.websocket << message.to_json
87
+ else
88
+ reactor.websocket << data.to_json
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,6 @@
1
+ require 'celluloid'
2
+ require 'celluloid/io'
3
+ require 'reel'
4
+ require 'celluloid/websocket/client'
5
+ require 'active_support/all'
6
+ Gem.find_files('celluloid_pubsub/**/*.rb').each { |path| require path }
@@ -0,0 +1,9 @@
1
+ # encoding:utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe CelluloidPubsub::Client do
6
+ end
7
+
8
+ describe CelluloidPubsub::Client::PubSubWorker do
9
+ end
@@ -0,0 +1,6 @@
1
+ # encoding:utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe CelluloidPubsub::Reactor do
6
+ end
@@ -0,0 +1,6 @@
1
+ # encoding:utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe CelluloidPubsub::Registry do
6
+ end
@@ -0,0 +1,6 @@
1
+ # encoding:utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe CelluloidPubsub::WebServer do
6
+ end