plezi 0.10.13 → 0.10.14

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: 7f37f01622fbcda6cf86ca9575aafb2145b5479f
4
- data.tar.gz: cbdf67890ad9995b11d058cbe821c62fad863995
3
+ metadata.gz: 2487750b4f8cbcb1de42a7bc91e065da2f94c212
4
+ data.tar.gz: 7f39f9de1020bc8f3d80113b2dc01d7c59c9d706
5
5
  SHA512:
6
- metadata.gz: f940d9e1731e9708228c8519a3be967762c427db4d3644aac6ceb439db8a9e44ac1de7bdfd4d3e998039f70452e1e2ffe02dc4ab444c4445793a017c1c02b432
7
- data.tar.gz: 9a336108299a74946dd97b6718f2440f80df3d5ec6dc33a925c35e5f82eb0d15c21571bbdd6a79c7c1b3cbfafd7ee79a89b3b449773e467018667a21948be1c0
6
+ metadata.gz: c97f85a27d0cce6a6d1df74e31ed9c8fef44377cfb9f0646d097f8917d80137dcddbe951631b2ab2126827595ad9028b53c01ffa3e1d3e1662440c710754ceb3
7
+ data.tar.gz: 79c93625fcc681835f0db3c87919fa4e4a906a4f4747c42ef3093155ac02489e3d834b2307c1b621a9a5cff43ea0481ecdab6f26b18488ef3dd8068d86ee94a4
@@ -1,5 +1,15 @@
1
1
  #Change Log
2
2
 
3
+ Change log v.0.10.14
4
+
5
+ **Deprecation notice**: Setting the public root folder is now done using the option `public` instead of the option `root`.
6
+
7
+ **Fix**: Yard documentation failed due to duplicate entries. The issue was fixed.
8
+
9
+ **Update**: removed duplicate code and updated the server for better Rack support.
10
+
11
+ ***
12
+
3
13
  Change log v.0.10.13
4
14
 
5
15
  **Fix**: The Placebo API was tested and an issue with the new Placebo class broadcast method was fixed.
data/README.md CHANGED
@@ -12,7 +12,7 @@ With Plezi, you can easily:
12
12
 
13
13
  3. Create a full fledged Ruby web application, taking full advantage of RESTful routing, HTTP streaming and scalable Websocket features.
14
14
 
15
- Plezi leverages [GRHttp server](https://github.com/boazsegev/GRHttp)'s new architecture. GRHttp is a pure Ruby HTTP and Websocket Generic Server built using [GReactor](https://github.com/boazsegev/GReactor) - a multi-threaded pure ruby alternative to EventMachine with basic process forking support (enjoy forking, if your code is scaling ready).
15
+ Plezi leverages [GRHttp server's](https://github.com/boazsegev/GRHttp) new architecture. GRHttp is a pure Ruby HTTP and Websocket Generic Server built using [GReactor](https://github.com/boazsegev/GReactor) - a multi-threaded pure ruby alternative to EventMachine with basic process forking support (enjoy forking, if your code is scaling ready).
16
16
 
17
17
  ## Installation
18
18
 
@@ -117,20 +117,27 @@ Remember to connect to the service from at least two browser windows - to truly
117
117
 
118
118
  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) ).
119
119
 
120
- ## Augmenting a Rails/Sinatra with Websocket broadcasting
120
+ ## Adding Websockets to your existing Rails/Sinatra/Rack application
121
121
 
122
- 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.
122
+ You already have an amazing WebApp, but now you want to add websocket broadcasting and unicasting support - Plezi makes connecting your existing WebApp with your Plezi Websocket backend as easy as it gets.
123
123
 
124
124
 
125
- There are two easy ways to augment your existing WebApp, depending on your needs and preferences:
125
+ There are two easy ways to add Plezi websockets to your existing WebApp, depending on your needs and preferences:
126
126
 
127
- 1. Let Plezi and GRHttp run your application as a fallback position, defering to your application for anything Plezi doesn't handle (Plezi Websockets and routes will recieve priority).
127
+ 1. **The super easy way - a Hybrid app**:
128
128
 
129
- 2. Run Plezi on a seperate process/server and set up communication between the two apps.
129
+ Plezi plays well with others, so you can add Plezi to your existing framework and let it catch any incoming websocket connections. Your application will still handle anything you didn't ask Plezi to handle (Plezi Websockets and routes will recieve priority, so your app can keep handling the 404 response).
130
130
 
131
- ### The super easy augmentation - run together
132
131
 
133
- The easiest way to augment your existing application is to use GRHttp's Rack adapter to run your Rack app, while Plezi will use GRHttp's native features (such as Websockets and HTTP streaming).
132
+ 2. **The Placebo API**:
133
+
134
+ Plezi has a Placebo API, allowing you to add Plezi features without running a Plezi app.
135
+
136
+ By adding the Plezi Placebo to your app, you can easily communicate between your existing app and a remote Plezi process/server. So, although websocket connections are made to a different server, your app can still send and recieve data through the websocket connection (using Redis).
137
+
138
+ ### The super easy way - a Hybrid app
139
+
140
+ The easiest way to add Plezi websockets to your existing application is to use [GRHttp's](https://github.com/boazsegev/GRHttp) Rack adapter to run your Rack app, while Plezi will use GRHttp's native features (such as Websockets and HTTP streaming).
134
141
 
135
142
  You can eaither use your existing Plezi application or create a new mini plezi application inside your existing app folder using:
136
143
 
@@ -145,22 +152,21 @@ Plezi.start_rack
145
152
 
146
153
  That's it! Now you can use the Plezi API and your existing application's API at the same time and they are both running on the same server.
147
154
 
148
- Plezi's route have priority, so that your app can keep handling the 404 (not found) error page.
155
+ Plezi's routes will be attempted first, so that your app can keep handling the 404 (not found) error page.
149
156
 
150
- In the next section we will explore how to set up the placebo API for cross process apps... since you are sharing the same space, you won't need it - but you can still use most of the Placebo API if you wish to do so (just **don't** call `Plezi.start_placebo`)
157
+ ### The Plezi Placebo API - talking from afar
151
158
 
152
- ### The easy (but not super easy) augmentation - talking from afar
159
+ To use Plezi and your App on different processes, without mixing them together, 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, but Plezi will not interfere with your WebApp in any way.
153
160
 
154
- To use Plezi and your App on different processes, without mixing them together, 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.
155
-
156
- For instance, add the following code to your environment on a Rails or Sinatra app:
161
+ For instance, add the following code to your environment setup on a Rails or Sinatra app:
157
162
 
158
163
  ```ruby
159
164
 
160
165
  require './my_plezi_app/environment.rb'
161
166
  require './my_plezi_app/routes.rb'
162
167
 
163
- ENV['PL_REDIS_URL'] = "redis://username:password@my.host:6379"
168
+ # # Make sure the following is already in your 'my_plezi_app/environment.rb' file:
169
+ # ENV['PL_REDIS_URL'] = "redis://username:password@my.host:6379"
164
170
 
165
171
  Plezi.start_placebo
166
172
  ```
@@ -172,7 +178,7 @@ Plezi will automatically set up the Redis connections and pub/sub to connect you
172
178
  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:
173
179
 
174
180
  ```ruby
175
-
181
+ # Demo a Rails Controller:
176
182
  class ClientsController < ApplicationController
177
183
  def update
178
184
  #... your original logic here
@@ -199,23 +205,20 @@ Oh, that's easy too.
199
205
 
200
206
  With a few more lines of code, we can have the websocket connections _broadcast_ back to us using the `Plezi::Placebo` API.
201
207
 
202
- On your Rails app, add:
208
+ In your Rails app, add the logic:
203
209
 
204
210
  ```ruby
205
-
206
211
  class MyReciever
207
212
  def my_reciever_method arg1, arg2, arg3, arg4...
208
213
  # your app's logic
209
214
  end
210
215
  end
211
-
212
216
  Plezi::Placebo.new MyReciever
213
-
214
217
  ```
215
218
 
216
219
  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...
217
220
 
218
- On the Plezi side, use multicasting, from ANY controller:
221
+ On the Plezi side, use multicasting or unicasting (but not broadcasting), from ANY controller:
219
222
 
220
223
  ```ruby
221
224
 
@@ -227,39 +230,33 @@ class ClientPleziCtrl
227
230
  end
228
231
  ```
229
232
 
230
- 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...
233
+ That's it! Now you have your listening object... but be aware - to safely scale up this communication you might consider using unicasting instead of broadcasting.
234
+
235
+ We recommend saving the uuid of the Rails process to a Redis key and picking it up from there.
231
236
 
232
237
  On your Rails app, add:
233
238
 
234
239
  ```ruby
235
240
  #...
236
241
  class MyReciever
237
- def get_controller sender
238
- ClientPleziCtrl.unicast sender, :_set_controller_uuid, uuid
239
- end
240
242
  def my_reciever_method arg1, arg2, arg3, arg4...
241
243
  # ...
242
244
  end
243
245
  end
244
246
 
245
- Plezi::Placebo.new MyReciever
247
+ pl = Plezi::Placebo.new MyReciever
248
+
249
+ Plezi.redis_connection.set 'MainUUIDs', pl.uuid
246
250
 
247
251
  ```
248
- On the Plezi, save the data and use unicasting when possible:
252
+ In your Plezi app, use unicasting when possible:
249
253
 
250
254
  ```ruby
251
255
  class ClientPleziCtrl
252
- def on_open
253
- multicast :get_controller, uuid
254
- end
255
256
  def on_message data
256
257
  # app logic here
257
- unicast @main_controller, :my_reciever_method, arg1, arg2, arg3, arg4... if @main_controller
258
- end
259
- def _controller_uuid controller_uuid
260
- @main_controller = controller_uuid
261
- # send ready flag to client using JSON?
262
- response << "{\"state\":\"ready\""
258
+ main_uuid = Plezi.redis_connection.get 'MainUUIDs'
259
+ unicast main_uuid, :my_reciever_method, arg1, arg2, arg3, arg4... if main_uuid
263
260
  end
264
261
  end
265
262
 
data/bin/plezi CHANGED
@@ -49,6 +49,8 @@ class AppTemplate
49
49
  app_tree["Gemfile"] ||= ''
50
50
  app_tree["Gemfile"] << "source 'https://rubygems.org'\n\n####################\n# core gems\n\n# include the basic plezi framework and server\ngem 'plezi', '~> #{Plezi::VERSION}'\n"
51
51
  app_tree["Gemfile"] << "\n\n\nruby '#{RUBY_VERSION}'\n"
52
+ app_tree["404.html.erb"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"404.erb"), __FILE__))
53
+ app_tree["500.html.erb"] ||= IO.read(::File.expand_path(File.join("..", "..", "resources" ,"500.erb"), __FILE__))
52
54
  finalize
53
55
  end
54
56
 
@@ -31,7 +31,7 @@ module Plezi
31
31
  #
32
32
  # Plezi's controller.render ERB, Slim and Haml are natively supported.
33
33
  #
34
- # @returns [Plezi::Router]
34
+ # @return [Plezi::Router]
35
35
  #
36
36
  def listen parameters = {}
37
37
  # update default values
@@ -32,7 +32,8 @@ module Plezi
32
32
  raise "Can't change channel name after Redis subscription had been initiated." if @redis
33
33
  @redis_channel_name = val
34
34
  end
35
- # @return [String] Returns the Redis Channel Name.
35
+ # Returns the Redis Channel Name used by this app.
36
+ # @return [String]
36
37
  def redis_channel_name
37
38
  @redis_channel_name ||= 'Plezi_Redis_Channel'
38
39
  end
@@ -19,7 +19,7 @@ module Plezi
19
19
  @host_params = request.io[:params]
20
20
  @response = response
21
21
  @cookies = request.cookies
22
- # @response["content-type"] ||= ::Plezi.default_content_type
22
+ # # \@response["content-type"] ||= ::Plezi.default_content_type
23
23
  super()
24
24
  end
25
25
 
@@ -57,19 +57,6 @@ module Plezi
57
57
  def on_close ws
58
58
  super() if defined? super
59
59
  end
60
- # handles websocket multicasting/broadcasting/unicasting.
61
- def on_broadcast ws
62
- data = ws.data
63
- unless (data[:type] || data[:target]) && data[:method] && data[:data]
64
- GReactor.warn "Broadcast message unknown... falling back on base broadcasting"
65
- return super(data) if defined? super
66
- return false
67
- end
68
- return false if data[:type] && data[:type] != :all && !self.is_a?(data[:type])
69
- # return false if data[:target] && data[:target] != ws.uuid + Plezi::Settings.uuid # already reviewed by the GRHttp
70
- return false unless self.class.has_method?(data[:method])
71
- self.method(data[:method]).call *data[:data]
72
- end
73
60
 
74
61
  # Inner Routing
75
62
  #
@@ -20,10 +20,10 @@ module Plezi
20
20
  end
21
21
 
22
22
  module InstanceMethods
23
- module_function
23
+
24
24
  public
25
25
 
26
- # the request object, class: HTTPRequest.
26
+ # the request object, type HTTPRequest.
27
27
  attr_reader :request
28
28
 
29
29
  # the :params variable contains all the parameters set by the request (/path?locale=he => params ["locale"] == "he").
@@ -97,7 +97,7 @@ module Plezi
97
97
  request.base_url + url_for(dest)
98
98
  end
99
99
 
100
- # this method adds data to be sent.
100
+ # Send raw data to be saved as a file or viewed as an attachment. Browser should believe it had recieved a file.
101
101
  #
102
102
  # this is usful for sending 'attachments' (data to be downloaded) rather then
103
103
  # a regular response.
@@ -27,10 +27,10 @@ module Plezi
27
27
  #the methods here will be injected to the Placebo controller.
28
28
  module Core
29
29
  def self.included base
30
+ base.send :include, Plezi::Base::WSObject
30
31
  base.send :include, InstanceMethods
31
32
  base.extend ClassMethods
32
33
  base.superclass.instance_eval {extend SuperClassMethods}
33
- base.send :include, Plezi::Base::WSObject
34
34
  end
35
35
 
36
36
  #the methods here will be injected to the Placebo controller as Instance methods.
@@ -35,6 +35,7 @@ module Plezi
35
35
  return false
36
36
  end
37
37
  return false if data[:type] && data[:type] != :all && !self.is_a?(data[:type])
38
+ # return ( self.class.placebo? ? true : we.write(ws.data)) if :method == :to_client
38
39
  return ((data[:type] == :all) ? false : (raise "Broadcasting recieved but no method can handle it - dump:\r\n #{data.to_s}") ) unless self.class.has_super_method?(data[:method])
39
40
  self.method(data[:method]).call *data[:data]
40
41
  end
@@ -130,6 +131,9 @@ module Plezi
130
131
  module SuperClassMethods
131
132
  public
132
133
 
134
+ # answers the question if this is a placebo object.
135
+ def placebo?; false end
136
+
133
137
  # WebSockets: fires an event on all of this controller's active websocket connections.
134
138
  #
135
139
  # Class method.
@@ -1,3 +1,3 @@
1
1
  module Plezi
2
- VERSION = "0.10.13"
2
+ VERSION = "0.10.14"
3
3
  end
@@ -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.16"
21
+ spec.add_dependency "grhttp", "~> 0.0.17"
22
22
  spec.add_development_dependency "bundler", "~> 1.7"
23
23
  spec.add_development_dependency "rake", "~> 10.0"
24
24
 
@@ -40,7 +40,7 @@ Dir[File.join "{app}", "**" , "*.rb"].each {|file| load File.expand_path(file)}
40
40
 
41
41
  # start a web service to listen on the first default port (3000 or the port set by the command-line).
42
42
  # you can change some of the default settings here.
43
- listen root: Root.join('public').to_s,
43
+ listen public: Root.join('public').to_s,
44
44
  assets: Root.join('assets').to_s,
45
45
  assets_public: '/assets',
46
46
  templates: Root.join('app','views').to_s,
@@ -9,6 +9,8 @@
9
9
  # Dir.chdir Root.to_s
10
10
  ## load code from a subfolder called 'code'
11
11
  # Dir[File.join "{code}", "**" , "*.rb"].each {|file| load File.expand_path(file)}
12
+ ## OR load code from all the ruby files in the main forlder (subfolder inclussion will fail on PaaS)
13
+ # Dir[File.join File.dirname(__FILE__), "*.rb"].each {|file| load File.expand_path(file) unless file == __FILE__}
12
14
 
13
15
  ## If this app is independant, use bundler to load gems (including the plezi gem).
14
16
  ## Else, use the original app's Gemfile and start Plezi's Rack mode.
@@ -60,7 +62,7 @@ end
60
62
  # start a web service to listen on the first default port (3000 or the port set by the command-line).
61
63
  # you can change some of the default settings here.
62
64
  listen host: :default,
63
- # root: Root.join('public').to_s,
65
+ # public: Root.join('public').to_s,
64
66
  # assets: Root.join('assets').to_s,
65
67
  # templates: Root.join('templates').to_s,
66
68
  ssl: false
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: UTF-8
3
3
 
4
+ # set the working directory
5
+ Dir.chdir ::File.expand_path(File.join(__FILE__, ".."))
4
6
  # load the appname-app
5
7
  load ::File.expand_path(File.join("..", "appname.rb"), __FILE__)
@@ -3,7 +3,7 @@
3
3
  // Your websocket URI should be an absolute path. The following sets the base URI.
4
4
  // remember to update to the specific controller's path to your websocket URI.
5
5
  var ws_controller_path = window.location.pathname; // change to '/controller/path'
6
- var ws_uri = (window.location.protocol.match(/https/) ? 'wss' : 'ws') + '://' + window.location.hostname + (window.location.port == '' ? '' : (':' + window.location.port) ) + ws_controller_path
6
+ var ws_uri = (window.location.protocol.match(/https/) ? 'wss' : 'ws') + '://' + window.document.location.host + ws_controller_path
7
7
  // websocket variable.
8
8
  var websocket = NaN
9
9
  // count failed attempts
@@ -177,7 +177,7 @@ input[type=submit]:active
177
177
  // Your websocket URI should be an absolute path. The following sets the base URI.
178
178
  // remember to update to the specific controller's path to your websocket URI.
179
179
  var ws_controller_path = '/' // window.location.pathname; // change to '/controller/path'
180
- var ws_uri = (window.location.protocol.match(/https/) ? 'wss' : 'ws') + '://' + window.location.hostname + (window.location.port == '' ? '' : (':' + window.location.port) ) + ws_controller_path
180
+ var ws_uri = (window.location.protocol.match(/https/) ? 'wss' : 'ws') + '://' + window.document.location.host + ws_controller_path
181
181
  // websocket variable.
182
182
  var websocket = NaN
183
183
  // count failed attempts
@@ -312,28 +312,28 @@ module PleziTestTasks
312
312
  PL.on_shutdown {puts " * Websocket unicast message test: #{RESULTS[unicast_test]}"}
313
313
  end
314
314
  def test_websocket_sizes
315
- # should_disconnect = false
316
- # ws = GRHttp::WSClient.connect_to("ws://localhost:3000/ws/size") do |ws|
317
- # if should_disconnect
318
- # puts " * Websocket size disconnection test: #{RESULTS[false]}"
319
- # else
320
- # puts " * Websocket message size test: got #{ws.data.bytesize} bytes"
321
- # end
322
-
323
- # end
324
- # ws.on_close do
325
- # puts " * Websocket size disconnection test: #{RESULTS[should_disconnect]}"
326
- # end
327
- # str = 'a'
328
- # time_now = Time.now
329
- # 8.times {|i| str = str * 2**i;puts " * Websocket message size test: sending #{str.bytesize} bytes"; ws << str; }
330
- # str.clear
331
- # to_sleep = (Time.now - time_now)*2 + 1
332
- # puts "will now sleep for #{to_sleep} seconds, waiting allowing the server to respond"
333
- # sleep to_sleep rescue true
334
- # should_disconnect = true
335
- # Plezi::Settings.ws_message_size_limit = 1024
336
- # ws << ('0123'*258)
315
+ should_disconnect = false
316
+ ws = GRHttp::WSClient.connect_to("ws://localhost:3000/ws/size") do |ws|
317
+ if should_disconnect
318
+ puts " * Websocket size disconnection test: #{RESULTS[false]}"
319
+ else
320
+ puts " * Websocket message size test: got #{ws.data.bytesize} bytes"
321
+ end
322
+
323
+ end
324
+ ws.on_close do
325
+ puts " * Websocket size disconnection test: #{RESULTS[should_disconnect]}"
326
+ end
327
+ str = 'a'
328
+ time_now = Time.now
329
+ 7.times {|i| str = str * 2**i;puts " * Websocket message size test: sending #{str.bytesize} bytes"; ws << str; }
330
+ str.clear
331
+ to_sleep = (Time.now - time_now)*2 + 1
332
+ puts "will now sleep for #{to_sleep} seconds, waiting allowing the server to respond"
333
+ sleep to_sleep rescue true
334
+ should_disconnect = true
335
+ Plezi::Settings.ws_message_size_limit = 1024
336
+ ws << ('0123'*258)
337
337
  end
338
338
  def test_broadcast_stress
339
339
  PlaceboStressTestCtrl.create_listeners
@@ -464,11 +464,15 @@ puts " --- Plezi will ran async, performing some tests that than hang"
464
464
 
465
465
  puts " --- Starting tests"
466
466
  puts " --- Failed tests should read: #{PleziTestTasks::RESULTS[false]}"
467
- Plezi.start_async
468
- PleziTestTasks.run_tests
469
467
 
470
468
  r = Plezi::Placebo.new PlaceboCtrl
471
469
  puts " * Create Placebo test: #{PleziTestTasks::RESULTS[r && true]}"
470
+ puts " * Placebo admists to being placebo: #{PleziTestTasks::RESULTS[PlaceboCtrl.placebo?]}"
471
+ puts " * Regular controller answers placebo: #{PleziTestTasks::RESULTS[!PlaceboTestCtrl.placebo?]}"
472
+
473
+
474
+ Plezi.start_async
475
+ PleziTestTasks.run_tests
472
476
 
473
477
  # ENV['PL_REDIS_URL'] ||= ENV['REDIS_URL'] || ENV['REDISCLOUD_URL'] || ENV['REDISTOGO_URL'] || "redis://test:1234@pub-redis-11008.us-east-1-4.5.ec2.garantiadata.com:11008"
474
478
  # # GReactor::Settings.set_forking 4
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.13
4
+ version: 0.10.14
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-25 00:00:00.000000000 Z
11
+ date: 2015-07-27 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.16
19
+ version: 0.0.17
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.16
26
+ version: 0.0.17
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -78,7 +78,6 @@ files:
78
78
  - lib/plezi/handlers/controller_core.rb
79
79
  - lib/plezi/handlers/controller_magic.rb
80
80
  - lib/plezi/handlers/http_router.rb
81
- - lib/plezi/handlers/placebo old.rb
82
81
  - lib/plezi/handlers/placebo.rb
83
82
  - lib/plezi/handlers/route.rb
84
83
  - lib/plezi/handlers/stubs.rb
@@ -1,161 +0,0 @@
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
- base.superclass.instance_eval {extend SuperClassMethods}
33
- end
34
-
35
- #the methods here will be injected to the Placebo controller as Instance methods.
36
- module InstanceMethods
37
- public
38
- attr_accessor :io
39
- def initialize io
40
- @io = io
41
- @io[:websocket_handler] = self
42
- super()
43
- end
44
- # notice of disconnect
45
- def on_close
46
- return super() if defined? super
47
- GR.warn "Placebo #{self.class.superclass.name} disconnected. Ignore if this message appears during shutdown."
48
- end
49
-
50
- # handles broadcasts / unicasts
51
- def on_broadcast ws
52
- data = ws.data
53
- unless (data[:type] || data[:target]) && data[:method] && data[:data]
54
- GReactor.warn "Broadcast message unknown... falling back on base broadcasting"
55
- return super(data) if defined? super
56
- return false
57
- end
58
- return false if data[:type] && data[:type] != :all && !self.is_a?(data[:type])
59
- return ((data[:type] == :all) ? false : (raise "Placebo Broadcasting recieved but no method can handle it - dump:\r\n #{data.to_s}") ) unless self.class.has_super_method?(data[:method])
60
- self.method(data[:method]).call *data[:data]
61
- end
62
- # Returns the websocket connection's UUID, used for unicasting.
63
- def uuid
64
- return (@uuid ||= @response.uuid + Plezi::Settings.uuid) if @response.is_a?(GRHttp::WSEvent)
65
- end
66
-
67
- # Performs a websocket unicast to the specified target.
68
- def unicast target_uuid, method_name, *args
69
- self.class.unicast target_uuid, method_name, *args
70
- end
71
- # broadcast to a specific controller
72
- def broadcast controller_class, method_name, *args
73
- GRHttp::Base::WSHandler.broadcast({data: args, type: controller_class, method: method_name}, self)
74
- self.class.__send_to_redis data: args, type: controller_class, method: method_name
75
- end
76
- # multicast to all handlers.
77
- def multicast method_name, *args
78
- self.class.multicast method_name, *args
79
- end
80
- end
81
- #the methods here will be injected to the Placebo controller as class methods.
82
- module ClassMethods
83
- public
84
- def has_super_method? method_name
85
- @super_methods_list ||= self.superclass.instance_methods.to_set
86
- @super_methods_list.include? method_name
87
- end
88
- end
89
- module SuperClassMethods
90
- # multicast to all handlers.
91
- def multicast method_name, *args
92
- GRHttp::Base::WSHandler.broadcast({method: method_name, data: args, type: :all}, self)
93
- __send_to_redis method: method_name, data: args, type: :all
94
- end
95
- # Broadcast to all instances (usually one instance) of THIS placebo controller.
96
- #
97
- # This should be used by the real websocket connections to forward messages to the placebo controller classes.
98
- def broadcast method_name, *args
99
- @methods_list ||= self.public_instance_methods.to_set
100
- raise "No mothod defined to accept this broadcast." unless @methods_list.include? method_name
101
- GRHttp::Base::WSHandler.broadcast data: args, type: self, method: method_name
102
- __send_to_redis data: args, type: self, method: method_name
103
- end
104
- # Performs a websocket unicast to the specified target.
105
- def unicast target_uuid, method_name, *args
106
- GRHttp::Base::WSHandler.unicast target_uuid, data: args, target: target_uuid, method: method_name
107
- __send_to_redis data: args, target: target_uuid, method: method_name
108
- end
109
- protected
110
- def __send_to_redis data
111
- raise "Wrong method name for websocket broadcasting - expecting type Symbol" unless data[:method].is_a?(Symbol) || data[:method].is_a?(Symbol)
112
- conn = Plezi.redis_connection
113
- data[:server] = Plezi::Settings.uuid
114
- return conn.publish( Plezi::Settings.redis_channel_name, data.to_yaml ) if conn
115
- false
116
- end
117
- end
118
- end
119
- class PlaceboIO < GReactor::BasicIO
120
- def clear?
121
- io.closed?
122
- end
123
- def call
124
- self.read
125
- GR.warn "Placebo IO recieved IO signal - this is unexpected..."
126
- end
127
- def on_disconnect
128
- @params[:out].close rescue nil
129
- @cache[:websocket_handler].on_close if @cache[:websocket_handler]
130
- end
131
- end
132
- end
133
- module_function
134
- def new placebo_class
135
- new_class_name = "PlaceboPlezi__#{placebo_class.name.gsub /[\:\-\#\<\>\{\}\(\)\s]/, '_'}"
136
- new_class = nil
137
- new_class = Module.const_get new_class_name if Module.const_defined? new_class_name
138
- unless new_class
139
- new_class = Class.new(placebo_class) do
140
- include Placebo::Base::Core
141
- end
142
- Object.const_set(new_class_name, new_class)
143
- end
144
- i, o = IO.pipe
145
- io = Placebo::Base::PlaceboIO.new i, out: o
146
- io = GReactor.add_raw_io i, io
147
- new_class.new(io)
148
- end
149
- end
150
- end
151
-
152
-
153
- # class A
154
- # def _hi
155
- # 'hi'
156
- # end
157
- # end
158
- # Plezi::Placebo.new A
159
- # a = nil
160
- # GReactor.each {|h| a= h}
161
- # a[:websocket_handler].on_broadcast GRHttp::WSEvent.new(nil, type: true, data: [], method: :_hi)