plezi 0.10.6 → 0.10.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 86970dabaa35cafd7bdae2e7dc5233816f108247
4
- data.tar.gz: 3e304fb54b25fa57cf03b56c0290a27baa0f76cc
3
+ metadata.gz: c504b33f40bbc1d8235c5d48101abab00a0facac
4
+ data.tar.gz: 5fad18c3d52af38f9ecc94cb899c337b54a3afdd
5
5
  SHA512:
6
- metadata.gz: f66fbaefd4333b7400d25576b85a1f9444bcf1db176ae981ed4c6512130f8903999a863b8d72d7e608da8dcf3f01f4211a32327867130f7bc58b3e9df88727a3
7
- data.tar.gz: 9f31d2ee28fcce84f1fbba07a6e559ac966743ffa03a0b98210a077a29aee81105ec49436b65f7754b679ef145a5512a09c0ff8e9c0d925549cc3f808af104ad
6
+ metadata.gz: c4f6a25bfa2846fd8ea384b741ee754673c3ecc6384402b9bd8c0766dea71ab0cc9711723ccaf38f20934fbf0b0f05c3c409850aa427a9d87f26775467b7382e
7
+ data.tar.gz: db2844de88d6dae7a1e019b4ec46fde5f33f4342484e38d5dc03f9aa9e5cc70c897ace96b4fed46f92bfd7e8c4d572f2e4bdc4952caa7dc0b283d93a01c1aaea
data/CHANGELOG.md CHANGED
@@ -2,6 +2,28 @@
2
2
 
3
3
  ***
4
4
 
5
+ Change log v.0.10.8
6
+
7
+ **Fix**: Fixed an issue with the new websocket upgrade handler. It is unclear how come the issue did not show up during the testing.
8
+
9
+ \* (All the changes in version 0.10.7 still apply)
10
+
11
+ ***
12
+
13
+ Change log v.0.10.7 (yanked)
14
+
15
+ **Fix**: Forces the use of a better version of the GRHttp server, now as fully tested as I could manage. This fixes an issue where the lasy byte on a Websocket message might have been corrupt.
16
+
17
+ **Fix**: fixed an issue where websocket connections would be quietly established (messages would be ignored) even though they should have been declined.
18
+
19
+ **Update**: Better support for intigration of Plezi with other frameworks, using `Plezi.start_async` and `Plezi.start_placebo` to get all the benifits of Plezi without distrupting the host framework.
20
+
21
+ **Update**: added the multicasting feature - allows you to send a message to ALL the websocket connections that defined a method to handle the message - use `multicast :method_name, arg1, arg2, arg3...`.
22
+
23
+ **Update**: Added the Placebo API to support websocket broadcasting on normal classes - allows for super-easy framework integration with other Ruby frameworks such as Rails and Sinatra.
24
+
25
+ ***
26
+
5
27
  Change log v.0.10.6
6
28
 
7
29
  **Performance Boost**: updated the GRHttp server version, to leverage the new Websocket engine, which offers a significant performance boost and allows for larger data to be transmitted over the websocket connection (tested with more than 250MB of data).
data/README.md CHANGED
@@ -10,7 +10,7 @@ Find more info on [Plezi's framework documentation](http://www.rubydoc.info/gems
10
10
 
11
11
  Plezi is an easy to use Ruby Websocket Framework, with full RESTful routing support and HTTP streaming support. It's name comes from the word "fun" in Haitian, since Plezi is really fun to work with and it keeps our code clean and streamlined.
12
12
 
13
- Plezi works as an asynchronous multi-threaded Ruby alternative to a Rack/Rails/Sintra/Faye/EM-Websockets combo. It's also great as an alternative to socket.io, allowing for both websockets and long pulling.
13
+ Plezi can both augment an existing Rails/Sinatra app, by providing it with easy Websocket and Asynchronous Events support, as well as offer an alternative to a Rack/Rails/Sintra/Faye/EM-Websockets combo. It's also great as an alternative to socket.io, allowing for both websockets and long pulling.
14
14
 
15
15
  Plezi runs over the [GRHttp server](https://github.com/boazsegev/GRHttp), which is a pure Ruby HTTP and Websocket Generic Server build using [GReactor](https://github.com/boazsegev/GReactor) - a multi-threaded pure ruby alternative to EventMachine with basic process forking support (enjoy it, if your code is scaling ready).
16
16
 
@@ -125,6 +125,124 @@ Remember to connect to the service from at least two browser windows - to truly
125
125
 
126
126
  method names starting with an underscore ('_') will NOT be made public by the router: so while both '/hello' and '/humans.txt' are public ( [try it](http://localhost:3000/humans.txt) ), '/_send_message' will return a 404 not found error ( [try it](http://localhost:3000/_send_message) ).
127
127
 
128
+ ## Augmenting a Rails/Sinatra with Websocket broadcasting
129
+
130
+ You already have an amazing WebApp, but now you want to add websocket broadcasting and unicasting support - Plezi makes connection your existing WebApp with your Plezi Websocket backend as easy as it gets.
131
+
132
+ Simply include the Plezi App in your existing app and call `Plezi.start_placebo` - now you can access all the websocket API that you want from your existing WebApp.
133
+
134
+ For instance, add the following code to your environment on a Rails or Sinatra app:
135
+
136
+ ```ruby
137
+
138
+ require './my_plezi_app/environment.rb'
139
+ require './my_plezi_app/routes.rb'
140
+
141
+ ENV['PL_REDIS_URL'] = "redis://username:password@my.host:6379"
142
+
143
+ Plezi.start_placebo
144
+ ```
145
+
146
+ That's it!
147
+
148
+ Plezi will automatically set up the Redis connections and pub/sub to connect your existing WebApp with Plezi's Websocket backend - which you can safely scale over processes or machines.
149
+
150
+ Now you can use Plezi from withing your existing App's code. For example, if your Plezi app has a controller named `ClientPleziCtrl`, you might use:
151
+
152
+ ```ruby
153
+
154
+ class ClientsController < ApplicationController
155
+ def update
156
+ #... your original logic here
157
+ @client = Client.find(params[:id])
158
+
159
+ # now unicast data to your client on the websocket
160
+ # (assume his websocket uuid was saved in @client.ws_uuid)
161
+
162
+ ClientPleziCtrl.unicast @client.ws_uuid, :method_name, @client.attributes
163
+
164
+ # or broadcast data to your all your the clients currently connected
165
+
166
+ ClientPleziCtrl.broadcast :method_name, @client.attributes
167
+
168
+ end
169
+ end
170
+ ```
171
+
172
+ Easy.
173
+
174
+ \- "But wait...", you might say to me, "How do we get information back FROM the back end?"
175
+
176
+ Oh, that's easy too.
177
+
178
+ With a few more lines of code, we can have the websocket connections _broadcast_ back to us using the `Plezi::Placebo` API.
179
+
180
+ On your Rails app, add:
181
+
182
+ ```ruby
183
+
184
+ class MyReciever
185
+ def my_reciever_method arg1, arg2, arg3, arg4...
186
+ # your app's logic
187
+ end
188
+ end
189
+
190
+ Plezi::Placebo.new MyReciever
191
+
192
+ ```
193
+
194
+ Plezi will now take your class and add mimick an IO connection (the Placebo connection) on it's GRHttp serever. This Placebo connection will answer the Redis broadcasts just as if your class was a websocket controller...
195
+
196
+ On the Plezi side, use multicasting, from ANY controller:
197
+
198
+ ```ruby
199
+
200
+ class ClientPleziCtrl
201
+ def on_message data
202
+ # app logic here
203
+ multicast :my_reciever_method, arg1, arg2, arg3, arg4...
204
+ end
205
+ end
206
+ ```
207
+
208
+ That's it! Now you have your listening object... but careful - to saafely scale up this communication you might consider using unicasting instead of broadcasting...
209
+
210
+ On your Rails app, add:
211
+
212
+ ```ruby
213
+ #...
214
+ class MyReciever
215
+ def get_controller sender
216
+ ClientPleziCtrl.unicast sender, :_set_controller_uuid, uuid
217
+ end
218
+ def my_reciever_method arg1, arg2, arg3, arg4...
219
+ # ...
220
+ end
221
+ end
222
+
223
+ Plezi::Placebo.new MyReciever
224
+
225
+ ```
226
+ On the Plezi, save the data and use unicasting when possible:
227
+
228
+ ```ruby
229
+ class ClientPleziCtrl
230
+ def on_open
231
+ multicast :get_controller, uuid
232
+ end
233
+ def on_message data
234
+ # app logic here
235
+ unicast @main_controller, :my_reciever_method, arg1, arg2, arg3, arg4... if @main_controller
236
+ end
237
+ def _controller_uuid controller_uuid
238
+ @main_controller = controller_uuid
239
+ # send ready flag to client using JSON?
240
+ response << "{\"state\":\"ready\""
241
+ end
242
+ end
243
+
244
+ ```
245
+
128
246
  ## Native HTTP streaming with Asynchronous events
129
247
 
130
248
  Plezi comes with native HTTP streaming support, alowing you to use Plezi Events and Timers to send an Asynchronous response.
data/lib/plezi.rb CHANGED
@@ -46,6 +46,7 @@ require 'plezi/handlers/http_router.rb'
46
46
  require 'plezi/handlers/route.rb'
47
47
  require 'plezi/handlers/controller_magic.rb'
48
48
  require 'plezi/handlers/controller_core.rb'
49
+ require 'plezi/handlers/placebo.rb'
49
50
  require 'plezi/handlers/stubs.rb'
50
51
 
51
52
 
@@ -72,7 +72,8 @@ module Plezi
72
72
  @listeners[parameters[:port]] = parameters
73
73
 
74
74
  # make sure the protocol exists.
75
- parameters[:upgrade_handler] = parameters[:http_handler] = HTTPRouter.new
75
+ parameters[:http_handler] = HTTPRouter.new
76
+ parameters[:upgrade_handler] = parameters[:http_handler].upgrade_proc
76
77
 
77
78
  GRHttp.listen parameters
78
79
  # set the active router to the handler or the protocol.
@@ -126,14 +127,30 @@ module Plezi
126
127
  end
127
128
  end
128
129
 
130
+ # starts the Plezi framework server and hangs until the exit signal is given.
129
131
  def self.start
130
- return GReactor.start if GReactor.running?
132
+ start_async
133
+ puts "\nPress ^C to exit.\n"
134
+ GReactor.join { puts "\r\nStarting shutdown sequesnce. Press ^C to force quit."}
135
+ end
136
+ # starts the Plezi framework and returns immidiately,
137
+ # allowing you to run the Plezi framework along side another framework.
138
+ def self.start_async
131
139
  Object.const_set("NO_PLEZI_AUTO_START", true) unless defined?(NO_PLEZI_AUTO_START)
140
+ return GReactor.start if GReactor.running?
132
141
  puts "Starting Plezi #{Plezi::VERSION} Services using the GRHttp #{GRHttp::VERSION} server."
133
- puts "Press ^C to exit."
134
142
  GReactor.on_shutdown { puts "Plezi shutdown. It was fun to serve you." }
135
143
  GReactor.start Plezi::Settings.max_threads
136
- GReactor.join { puts "\r\nStarting shutdown sequesnce. Press ^C to force quit."}
144
+ end
145
+ # This allows you to run the Plezi framework along side another framework - WITHOUT running the actual server.
146
+ #
147
+ # The server will not be initiatet and instead you will be able to use Plezi controllers and the Redis auto-config
148
+ # to broadcast Plezi messages to other Plezi processes - allowing for scalable intigration of Plezi into other frameworks.
149
+ def self.start_placebo
150
+ GReactor.clear_listeners
151
+ redis_connection # make sure the redis connection is activated
152
+ puts "* Plezi #{Plezi::VERSION} Services will start with no Server...\n"
153
+ start_async
137
154
  end
138
155
  end
139
156
 
@@ -13,29 +13,33 @@ module Plezi
13
13
  def redis_connection
14
14
  return @redis if (@redis_sub_thread && @redis_sub_thread.alive?) && @redis
15
15
  return false unless defined?(Redis) && ENV['PL_REDIS_URL']
16
- @redis_uri ||= URI.parse(ENV['PL_REDIS_URL'])
17
- @redis ||= Redis.new(host: @redis_uri.host, port: @redis_uri.port, password: @redis_uri.password)
18
- raise "Redis connction failed for: #{ENV['PL_REDIS_URL']}" unless @redis
19
- @redis_sub_thread = Thread.new do
20
- begin
21
- Redis.new(host: @redis_uri.host, port: @redis_uri.port, password: @redis_uri.password).subscribe(Plezi::Settings.redis_channel_name) do |on|
22
- on.message do |channel, msg|
23
- begin
24
- data = YAML.load(msg)
25
- next if data[:server] == Plezi::Settings.uuid
26
- if data[:target]
27
- GRHttp::Base::WSHandler.unicast data[:target], data
28
- else
29
- GRHttp::Base::WSHandler.broadcast data
16
+ @redis_locker ||= Mutex.new
17
+ @redis_locker.synchronize do
18
+ return @redis if (@redis_sub_thread && @redis_sub_thread.alive?) && @redis # repeat the test once syncing is done.
19
+ @redis_uri ||= URI.parse(ENV['PL_REDIS_URL'])
20
+ @redis ||= Redis.new(host: @redis_uri.host, port: @redis_uri.port, password: @redis_uri.password)
21
+ raise "Redis connction failed for: #{ENV['PL_REDIS_URL']}" unless @redis
22
+ @redis_sub_thread = Thread.new do
23
+ begin
24
+ Redis.new(host: @redis_uri.host, port: @redis_uri.port, password: @redis_uri.password).subscribe(Plezi::Settings.redis_channel_name) do |on|
25
+ on.message do |channel, msg|
26
+ begin
27
+ data = YAML.load(msg)
28
+ next if data[:server] == Plezi::Settings.uuid
29
+ if data[:target]
30
+ GRHttp::Base::WSHandler.unicast data[:target], data
31
+ else
32
+ GRHttp::Base::WSHandler.broadcast data
33
+ end
34
+ rescue => e
35
+ Reactor.error e
30
36
  end
31
- rescue => e
32
- Reactor.error e
33
37
  end
34
38
  end
39
+ rescue => e
40
+ Reactor.error e
41
+ retry
35
42
  end
36
- rescue => e
37
- Reactor.error e
38
- retry
39
43
  end
40
44
  end
41
45
  @redis
@@ -56,7 +56,7 @@ module Plezi
56
56
  def on_close ws
57
57
  super() if defined? super
58
58
  end
59
- # handles websocket being closed.
59
+ # handles websocket multicasting/broadcasting/unicasting.
60
60
  def on_broadcast ws
61
61
  data = ws.data
62
62
  unless (data[:type] || data[:target]) && data[:method] && data[:data]
@@ -64,7 +64,8 @@ module Plezi
64
64
  return super(data) if defined? super
65
65
  return false
66
66
  end
67
- return false if data[:type] && !self.is_a?(data[:type])
67
+ return false if data[:type] && data[:type] != :all && !self.is_a?(data[:type])
68
+ return false if data[:target] && data[:target] != ws.uuid
68
69
  return false unless self.class.has_method?(data[:method])
69
70
  self.method(data[:method]).call *data[:data]
70
71
  end
@@ -237,6 +237,18 @@ module Plezi
237
237
  self.class._inner_broadcast method: method_name, data: args, target: target_uuid
238
238
  end
239
239
 
240
+ # Use this to multicast an event to ALL websocket connections on EVERY controller, including Placebo controllers.
241
+ #
242
+ # Accepts:
243
+ # method_name:: a Symbol with the method's name that should respond to the broadcast.
244
+ # args*:: The method's argumenst - It MUST be possible to stringify the arguments into a YAML string, or broadcasting and unicasting will fail when scaling beyond one process / one machine.
245
+ #
246
+ # The method will be called asynchrnously for ALL websocket connections.
247
+ #
248
+ def multicast method_name, *args
249
+ self.class._inner_broadcast({ method: method_name, data: args, type: :all}, @response.io)
250
+ end
251
+
240
252
 
241
253
  # # will (probably NOT), in the future, require authentication or, alternatively, return an Array [user_name, password]
242
254
  # #
@@ -280,6 +292,18 @@ module Plezi
280
292
  _inner_broadcast method: method_name, data: args, target: target_uuid
281
293
  end
282
294
 
295
+ # Use this to multicast an event to ALL websocket connections on EVERY controller, including Placebo controllers.
296
+ #
297
+ # Accepts:
298
+ # method_name:: a Symbol with the method's name that should respond to the broadcast.
299
+ # args*:: The method's argumenst - It MUST be possible to stringify the arguments into a YAML string, or broadcasting and unicasting will fail when scaling beyond one process / one machine.
300
+ #
301
+ # The method will be called asynchrnously for ALL websocket connections.
302
+ #
303
+ def multicast method_name, *args
304
+ _inner_broadcast({ method: method_name, data: args, type: :all}, @response.io)
305
+ end
306
+
283
307
  # This class method behaves the same way as the instance method #url_for. See the instance method's documentation for more details.
284
308
  def url_for dest
285
309
  get_pl_route.url_for dest
@@ -15,6 +15,20 @@ module Plezi
15
15
  end
16
16
  end
17
17
 
18
+ # return the upgrade handler (the self.on_upgrade method)
19
+ def upgrade_proc
20
+ self.method :on_upgrade
21
+ end
22
+ #handles websocket connection requests.
23
+ def on_upgrade request, response
24
+ host = get_host(request[:host_name].to_s.downcase) || @hosts[:default]
25
+ return false unless host
26
+ request.io[:params] = host.params
27
+ # return if a route answered the request
28
+ host.routes.each {|r| a = r.on_request(request, response); return a if a}
29
+ # websockets should cut out here
30
+ false
31
+ end
18
32
  # initializes an HTTP router (the normal Handler for HTTP requests)
19
33
  #
20
34
  # the router holds the different hosts and sends them messages/requests.
@@ -0,0 +1,123 @@
1
+ module Plezi
2
+
3
+ # This API wil allows you to listen to Websocket Broadcasts sent to any object and to accept unicasts
4
+ # even when NOT connected to a websocket.
5
+ #
6
+ # Simpley create a class to handle any events and call `Plezi::Placebo.new ClassName` :
7
+ #
8
+ # class MyListener
9
+ # def _my_method_name *args
10
+ # #logic
11
+ # end
12
+ # end
13
+ #
14
+ # Plezi::Placebo.new MyListener
15
+ #
16
+ # A new instance will be created and that instance will answer any broadcasts, for ALL possible
17
+ # Plezi controllers, as long as it had a method defined that is capable to handle the broadcast.
18
+ #
19
+ # The new instance will also accept unicasts sent to it's unique UUID.
20
+ #
21
+ # Returns an instance that is a member of the class passed, after that class was inherited by Plezi and
22
+ # more methods were injected into it's subclass.
23
+ module Placebo
24
+
25
+ # the base module exposes some of the core functionality, but shouldn't be relied upon as far as it's API goes.
26
+ module Base
27
+ #the methods here will be injected to the Placebo controller.
28
+ module Core
29
+ def self.included base
30
+ base.send :include, InstanceMethods
31
+ base.extend ClassMethods
32
+ end
33
+
34
+ #the methods here will be injected to the Placebo controller as Instance methods.
35
+ module InstanceMethods
36
+ public
37
+ attr_accessor :io
38
+ def initialize io
39
+ @io = io
40
+ @io[:websocket_handler] = self
41
+ super()
42
+ end
43
+ # handles broadcasts / unicasts
44
+ def on_broadcast ws
45
+ data = ws.data
46
+ unless (data[:type] || data[:target]) && data[:method] && data[:data]
47
+ GReactor.warn "Broadcast message unknown... falling back on base broadcasting"
48
+ return super(data) if defined? super
49
+ return false
50
+ end
51
+ # return false if data[:type] && !self.is_a?(data[:type])
52
+ return false if data[:target] && data[:target] != ws.uuid
53
+ return false unless self.class.has_super_method?(data[:method])
54
+ self.method(data[:method]).call *data[:data]
55
+ end
56
+ # Returns the websocket connection's UUID, used for unicasting.
57
+ def uuid
58
+ io[:uuid] ||= SecureRandom.uuid
59
+ end
60
+
61
+ # Performs a websocket unicast to the specified target.
62
+ def unicast target_uuid, method_name, *args
63
+ GRHttp::Base::WSHandler.unicast target_uuid, data: args, target: target_uuid, method: method_name
64
+ __send_to_redis data: args, target: target_uuid, method: method_name
65
+ end
66
+ # broadcast to a specific controller
67
+ def broadcast controller_class, method_name, *args
68
+ GRHttp::Base::WSHandler.broadcast({data: args, type: controller_class, method: method_name}, self)
69
+ __send_to_redis data: args, type: controller_class, method: method_name
70
+ end
71
+ # multicast to all handlers.
72
+ def multicast method_name, *args
73
+ GRHttp::Base::WSHandler.broadcast({method: method_name, data: args, type: :all}, self)
74
+ __send_to_redis method: method_name, data: args, type: :all
75
+ end
76
+ protected
77
+ def __send_to_redis data
78
+ raise "Wrong method name for websocket broadcasting - expecting type Symbol" unless data[:method].is_a?(Symbol) || data[:method].is_a?(Symbol)
79
+ conn = Plezi.redis_connection
80
+ data[:server] = Plezi::Settings.uuid
81
+ return conn.publish( Plezi::Settings.redis_channel_name, data.to_yaml ) if conn
82
+ false
83
+ end
84
+ end
85
+ #the methods here will be injected to the Placebo controller as class methods.
86
+ module ClassMethods
87
+ public
88
+ def has_super_method? method_name
89
+ @super_methods_list ||= self.superclass.instance_methods.to_set
90
+ @super_methods_list.include? method_name
91
+ end
92
+ end
93
+ end
94
+ end
95
+ module_function
96
+ def new placebo_class
97
+ new_class_name = "PlaceboPlezi__#{placebo_class.name.gsub /[\:\-\#\<\>\{\}\(\)\s]/, '_'}"
98
+ new_class = nil
99
+ new_class = Module.const_get new_class_name if Module.const_defined? new_class_name
100
+ unless new_class
101
+ new_class = Class.new(placebo_class) do
102
+ include Placebo::Base::Core
103
+ end
104
+ Object.const_set(new_class_name, new_class)
105
+ end
106
+ i, o = IO.pipe
107
+ o.close
108
+ io = GReactor.add_io i, handler: (Proc.new {|io| io.read })
109
+ new_class.new(io)
110
+ end
111
+ end
112
+ end
113
+
114
+
115
+ # class A
116
+ # def _hi
117
+ # 'hi'
118
+ # end
119
+ # end
120
+ # Plezi::Placebo.new A
121
+ # a = nil
122
+ # GReactor.each {|h| a= h}
123
+ # a[:websocket_handler].on_broadcast GRHttp::WSEvent.new(nil, type: true, data: [], method: :_hi)
@@ -141,4 +141,4 @@ module Plezi
141
141
  end
142
142
 
143
143
  end
144
- end
144
+ end
data/lib/plezi/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Plezi
2
- VERSION = "0.10.6"
2
+ VERSION = "0.10.8"
3
3
  end
data/plezi.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "grhttp", "~> 0.0.9"
21
+ spec.add_dependency "grhttp", "~> 0.0.11"
22
22
  spec.add_development_dependency "bundler", "~> 1.7"
23
23
  spec.add_development_dependency "rake", "~> 10.0"
24
24
 
data/test/plezi_tests.rb CHANGED
@@ -17,6 +17,8 @@ def report_after_filter(result= true)
17
17
  true
18
18
  end
19
19
 
20
+ class Nothing
21
+ end
20
22
  class TestCtrl
21
23
 
22
24
 
@@ -239,6 +241,15 @@ module PleziTestTasks
239
241
  puts " **** #url_for test FAILED TO RUN!!!"
240
242
  puts e
241
243
  end
244
+ def test_placebo
245
+ puts " * Starting placebo tests..."
246
+ ws = GRHttp::WSClient.connect_to("ws://localhost:3000/ws/placebo") {|ws| 'ME?'}
247
+ ws << " * Placebo WS connected."
248
+ sleep 2
249
+ rescue => e
250
+ puts " **** Placebo test FAILED TO RUN!!!"
251
+ puts e
252
+ end
242
253
  def test_websocket
243
254
  connection_test = broadcast_test = echo_test = unicast_test = false
244
255
  begin
@@ -343,7 +354,38 @@ module PleziTestTasks
343
354
  end
344
355
  end
345
356
 
346
- NO_PLEZI_AUTO_START = true
357
+ class PlaceboTestCtrl
358
+ # called when new Websocket data is recieved
359
+ #
360
+ # data is a string that contains binary or UTF8 (message dependent) data.
361
+ def index
362
+ false
363
+ end
364
+ def on_open
365
+ puts " * Placebo multicasting to placebo test: #{PleziTestTasks::RESULTS[ multicast :send_back, uuid: uuid, test: true, type: 'multicast' ] }"
366
+ end
367
+ def on_message data
368
+ puts data
369
+ end
370
+ def _get_uuid data
371
+ puts " * Placebo send #{data[:type]} test: #{PleziTestTasks::RESULTS[data[:test]]}"
372
+ unicast( data[:uuid], :send_back, {test: true, type: 'unicast'}) if data[:uuid]
373
+ end
374
+ end
375
+
376
+ class PlaceboCtrl
377
+ def send_back data
378
+ puts " * Placebo recieve test for #{data[:type]}: #{PleziTestTasks::RESULTS[data[:test]]}"
379
+ if data[:uuid]
380
+ unicast( data[:uuid], :_get_uuid, {test: true, uuid: uuid, type: 'unicast'})
381
+ else
382
+ broadcast WSsizeTestCtrl, :_get_uuid, test: true, type: 'broadcast'
383
+ multicast :_get_uuid, test: true, type: 'multicast'
384
+ end
385
+ end
386
+ end
387
+ r = Plezi::Placebo.new PlaceboCtrl
388
+ puts " * Create Placebo test: #{PleziTestTasks::RESULTS[r && true]}"
347
389
 
348
390
  PL.create_logger '/dev/null'
349
391
  # PL::Settings.max_threads = 4
@@ -354,18 +396,21 @@ route("/ssl") {|req, res| res << "false" }
354
396
  listen port: 3030, ssl: true
355
397
  route("/ssl") {|req, res| res << "true" }
356
398
 
399
+ shared_route 'ws/no', Nothing
400
+ shared_route 'ws/placebo', PlaceboTestCtrl
357
401
  shared_route 'ws/size', WSsizeTestCtrl
358
402
 
359
403
  shared_route '/some/:multi{path|another_path}/(:option){route|test}/(:id)/(:optional)', TestCtrl
360
404
  shared_route '/', TestCtrl
361
405
 
362
406
 
363
- GReactor.run_async do
364
- puts " --- Starting tests"
365
- puts " --- Failed tests should read: #{PleziTestTasks::RESULTS[false]}"
366
- PleziTestTasks.run_tests
367
- puts "\n --- Press ^C to complete tests."
368
- end
407
+ Plezi.start_async
408
+ puts " --- Plezi will ran async, performing some tests that than hang"
409
+
410
+ puts " --- Starting tests"
411
+ puts " --- Failed tests should read: #{PleziTestTasks::RESULTS[false]}"
412
+ PleziTestTasks.run_tests
413
+ puts "\n --- Press ^C to complete tests."
369
414
 
370
415
  # start_services
371
416
 
@@ -373,7 +418,6 @@ shoutdown_test = false
373
418
  # GReactor::Settings.set_forking 4
374
419
  Plezi.on_shutdown { shoutdown_test = true }
375
420
 
376
-
377
421
  Plezi.start
378
422
  # Plezi::EventMachine.clear_timers
379
423
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plezi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.6
4
+ version: 0.10.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-20 00:00:00.000000000 Z
11
+ date: 2015-07-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: grhttp
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.0.9
19
+ version: 0.0.11
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.0.9
26
+ version: 0.0.11
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -77,6 +77,7 @@ files:
77
77
  - lib/plezi/handlers/controller_core.rb
78
78
  - lib/plezi/handlers/controller_magic.rb
79
79
  - lib/plezi/handlers/http_router.rb
80
+ - lib/plezi/handlers/placebo.rb
80
81
  - lib/plezi/handlers/route.rb
81
82
  - lib/plezi/handlers/stubs.rb
82
83
  - lib/plezi/helpers/http_sender.rb