plezi 0.10.8 → 0.10.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c504b33f40bbc1d8235c5d48101abab00a0facac
4
- data.tar.gz: 5fad18c3d52af38f9ecc94cb899c337b54a3afdd
3
+ metadata.gz: ef2d6297c599601166b2e26a419ad02b89b10ecb
4
+ data.tar.gz: e5f255998404493dff97e3d5ab4e17583b391d10
5
5
  SHA512:
6
- metadata.gz: c4f6a25bfa2846fd8ea384b741ee754673c3ecc6384402b9bd8c0766dea71ab0cc9711723ccaf38f20934fbf0b0f05c3c409850aa427a9d87f26775467b7382e
7
- data.tar.gz: db2844de88d6dae7a1e019b4ec46fde5f33f4342484e38d5dc03f9aa9e5cc70c897ace96b4fed46f92bfd7e8c4d572f2e4bdc4952caa7dc0b283d93a01c1aaea
6
+ metadata.gz: a8a372f2af85a2f3c24985ea15db19c1b4ab7f96f31a10c0dda71a0b4f7697c934aeabfb7738877bc39d3319dc4e9d058dfd798847c745cd7d858f19837a1da9
7
+ data.tar.gz: 09c07532144ab34453cde96ba66d7b2650b85722f62aac4b724365ccfde4b010c2296e8b704021d41baeda84745a739e0ddf50f01a04d90a30e1c73998349309
@@ -2,6 +2,14 @@
2
2
 
3
3
  ***
4
4
 
5
+ Change log v.0.10.9
6
+
7
+ **Minor**: minor update to the cache system, might improve performance somewhat and might fix rare issues related to some binary files. Updated GRHttp server version required.
8
+
9
+ **Fix**: fixed an issue with Placebo listeners where they might be thrown from the IO stack and thereby stop listening ()or, alternatively, consume CPU) . This issue was caused by GReactor's 'BasicIO#clear?' code enforcing two-way connectivity.
10
+
11
+ ***
12
+
5
13
  Change log v.0.10.8
6
14
 
7
15
  **Fix**: Fixed an issue with the new websocket upgrade handler. It is unclear how come the issue did not show up during the testing.
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Plezi, The Rack Free Ruby framework for realtime web-apps
2
2
  [![Gem Version](https://badge.fury.io/rb/plezi.svg)](http://badge.fury.io/rb/plezi)
3
- [![Inline docs](http://inch-ci.org/github/boazsegev/plezi.svg?branch=master)](http://www.rubydoc.info/gems/plezi/)
3
+ [![Inline docs](http://inch-ci.org/github/boazsegev/plezi.svg?branch=master)](http://www.rubydoc.info/github/boazsegev/plezi/master)
4
4
 
5
5
  > People who are serious about their frameworks, should write their own servers...
6
6
 
7
- Find more info on [Plezi's framework documentation](http://www.rubydoc.info/gems/plezi/)
7
+ Find more info on [Plezi's framework documentation](http://www.rubydoc.info/github/boazsegev/plezi/master)
8
8
 
9
9
  ## About the Plezi framework
10
10
 
@@ -2,11 +2,15 @@
2
2
  module Plezi
3
3
 
4
4
  # File and Object Caching for Plezi
5
+ #
6
+ # Be aware that the cache is local, per process. It's possible to limit file caching by limiting the supported_types in Plezi::Cache::CACHABLE.
7
+ #
8
+ # Template rendering engines are always cached.
5
9
  module Cache
6
10
  # contains the cached data, in the format: CACHE_STORE["filename"] = CacheObject
7
11
  CACHE_STORE = {}
8
12
  CACHE_LOCK = Mutex.new
9
- CACHABLE = %w{cache object slim haml css map js html scss sass coffee txt xml json yaml rb}
13
+ CACHABLE = (%w{cache object slim haml css map js html scss sass coffee txt xml json yaml rb}).to_set
10
14
 
11
15
  @cache_to_disk = true
12
16
 
@@ -17,7 +21,8 @@ module Plezi
17
21
 
18
22
  # initialize a Cached object
19
23
  def initialize d = nil, t = Time.now
20
- @data, @mtime = d, t
24
+ @data = t
25
+ @mtime = d
21
26
  end
22
27
  end
23
28
 
@@ -34,16 +39,16 @@ module Plezi
34
39
  # force a file onto the cache (only if it is cachable - otherwise will load the file but will not cache it).
35
40
  def reload_file filename
36
41
  if CACHABLE.include? filename.match(/\.([^\.]+)$/)[1]
37
- return cache_data filename, IO.read(filename), File.mtime(filename)
42
+ return cache_data filename, IO.binread(filename), File.mtime(filename)
38
43
  else
39
- return IO.read(filename)
44
+ return IO.binread(filename)
40
45
  end
41
46
  end
42
47
  # places data into the cache, and attempts to save the data to a file name.
43
48
  def save_file filename, data, save_to_disk = false
44
49
  cache_data filename, data if CACHABLE.include? filename.match(/\.([^\.]+)$/)[1]
45
50
  begin
46
- IO.write filename, data if save_to_disk
51
+ IO.binwrite filename, data if save_to_disk
47
52
  rescue Exception => e
48
53
  Plezi.warn("File couldn't be written (#{filename}) - file system error?")
49
54
  end
@@ -14,7 +14,6 @@ module Plezi
14
14
  #
15
15
  # use the`listen`, `host` and `route` functions rather then accessing this object.
16
16
  #
17
- @servers = {}
18
17
  @active_router = nil
19
18
 
20
19
 
@@ -98,8 +97,7 @@ module Plezi
98
97
 
99
98
  # adds a host to the last server created
100
99
  #
101
- # accepts the same parameter(s) as the `listen` command (see Plezi.add_service), except :protocol and :handler are ignored:
102
- # alias:: a String or an Array of Strings which represent alternative host names (i.e. `alias: ["admin.google.com", "admin.gmail.com"]`).
100
+ # accepts a host name and a parameter(s) Hash which are the same parameter(s) as {Plezi.listen} accepts:
103
101
  def host(host_name, params)
104
102
  raise "Must define a listener before adding a route - use `Plezi.listen`." unless @active_router
105
103
  @active_router.add_host host_name, params
@@ -26,10 +26,10 @@ module Plezi
26
26
  # the request object, class: HTTPRequest.
27
27
  attr_reader :request
28
28
 
29
- # the ::params variable contains all the parameters set by the request (/path?locale=he => params["locale"] == "he").
29
+ # the :params variable contains all the parameters set by the request (/path?locale=he => params ["locale"] == "he").
30
30
  attr_reader :params
31
31
 
32
- # a cookie-jar to get and set cookies (set: `cookie\[:name] = data` or get: `cookie\[:name]`).
32
+ # a cookie-jar to get and set cookies (set: `cookie [:name] = data` or get: `cookie [ :name ]`).
33
33
  #
34
34
  # Cookies and some other data must be set BEFORE the response's headers are sent.
35
35
  attr_reader :cookies
@@ -37,7 +37,7 @@ module Plezi
37
37
  # the HTTPResponse **OR** the WSResponse object that formats the response and sends it. use `response << data`. This object can be used to send partial data (such as headers, or partial html content) in blocking mode as well as sending data in the default non-blocking mode.
38
38
  attr_reader :response
39
39
 
40
- # the ::flash is a little bit of a magic hash that sets and reads temporary cookies.
40
+ # the :flash is a little bit of a magic hash that sets and reads temporary cookies.
41
41
  # these cookies will live for one successful request to a Controller and will then be removed.
42
42
  attr_reader :flash
43
43
 
@@ -166,11 +166,11 @@ module Plezi
166
166
  I18n.locale = options[:locale] || I18n.default_locale if defined?(I18n) # sets the locale to nil for default behavior even if the locale was set by a previous action - removed: # && options[:locale]
167
167
  # find template and create template object
168
168
  filename = template.is_a?(String) ? File.join( host_params[:templates].to_s, template) : (File.join( host_params[:templates].to_s, *template.to_s.split('_')) + (options[:type].empty? ? '': ".#{options[:type]}") + '.slim')
169
- return ( Plezi.cache_needs_update?(filename) ? Plezi.cache_data( filename, ( Slim::Template.new() { IO.read filename } ) ) : (Plezi.get_cached filename) ).render(self, &block) if defined?(::Slim) && Plezi.file_exists?(filename)
169
+ return ( Plezi.cache_needs_update?(filename) ? Plezi.cache_data( filename, ( Slim::Template.new() { IO.binread filename } ) ) : (Plezi.get_cached filename) ).render(self, &block) if defined?(::Slim) && Plezi.file_exists?(filename)
170
170
  filename.gsub! /\.slim$/, '.haml'
171
- return ( Plezi.cache_needs_update?(filename) ? Plezi.cache_data( filename, ( Haml::Engine.new( IO.read(filename) ) ) ) : (Plezi.get_cached filename) ).render(self, &block) if defined?(::Haml) && Plezi.file_exists?(filename)
171
+ return ( Plezi.cache_needs_update?(filename) ? Plezi.cache_data( filename, ( Haml::Engine.new( IO.binread(filename) ) ) ) : (Plezi.get_cached filename) ).render(self, &block) if defined?(::Haml) && Plezi.file_exists?(filename)
172
172
  filename.gsub! /\.haml$/, '.erb'
173
- return ( Plezi.cache_needs_update?(filename) ? Plezi.cache_data( filename, ( ERB.new( IO.read(filename) ) ) ) : (Plezi.get_cached filename) ).result(binding, &block) if defined?(::ERB) && Plezi.file_exists?(filename)
173
+ return ( Plezi.cache_needs_update?(filename) ? Plezi.cache_data( filename, ( ERB.new( IO.binread(filename) ) ) ) : (Plezi.get_cached filename) ).result(binding, &block) if defined?(::ERB) && Plezi.file_exists?(filename)
174
174
  return false
175
175
  end
176
176
 
@@ -38,7 +38,7 @@ module Plezi
38
38
  @sass_cache = Sass::CacheStores::Memory.new if defined?(::Sass)
39
39
  end
40
40
 
41
- # adds a host to the router (or activates an existing host to add new routes). accepts a host name and any parameters not related to the service (see `Plezi.add_service`)
41
+ # adds a host to the router (or activates an existing host to add new routes). accepts a host name and any parameters not related to the actual connection (ssl etc') (see {Plezi.listen})
42
42
  def add_host host_name, params = {}
43
43
  host_name = (host_name ? host_name.to_s.downcase : :default)
44
44
  @active_host = get_host(host_name) || ( @hosts[host_name] = Host.new(params) )
@@ -142,7 +142,7 @@ module Plezi
142
142
  if defined?(::CoffeeScript) && Plezi.cache_needs_update?(coffee)
143
143
  # render coffee to cache
144
144
  Plezi.cache_data coffee, nil
145
- Plezi.save_file target_file, CoffeeScript.compile(IO.read coffee), params[:save_assets]
145
+ Plezi.save_file target_file, CoffeeScript.compile(IO.binread coffee), params[:save_assets]
146
146
  end
147
147
  # try to send the cached js file which started the request.
148
148
  return Base::HTTPSender.send_file request, response, target_file
@@ -40,6 +40,12 @@ module Plezi
40
40
  @io[:websocket_handler] = self
41
41
  super()
42
42
  end
43
+ # notice of disconnect
44
+ def on_close
45
+ return super() if defined? super
46
+ GR.warn "Placebo #{self.class.superclass.name} disconnected. Ignore if this message appears during shutdown."
47
+ end
48
+
43
49
  # handles broadcasts / unicasts
44
50
  def on_broadcast ws
45
51
  data = ws.data
@@ -91,6 +97,19 @@ module Plezi
91
97
  end
92
98
  end
93
99
  end
100
+ class PlaceboIO < GReactor::BasicIO
101
+ def clear?
102
+ io.closed?
103
+ end
104
+ def call
105
+ self.read
106
+ GR.warn "Placebo IO recieved IO signal - this is unexpected..."
107
+ end
108
+ def on_disconnect
109
+ @params[:out].close rescue nil
110
+ @cache[:websocket_handler].on_close if @cache[:websocket_handler]
111
+ end
112
+ end
94
113
  end
95
114
  module_function
96
115
  def new placebo_class
@@ -104,8 +123,8 @@ module Plezi
104
123
  Object.const_set(new_class_name, new_class)
105
124
  end
106
125
  i, o = IO.pipe
107
- o.close
108
- io = GReactor.add_io i, handler: (Proc.new {|io| io.read })
126
+ io = Placebo::Base::PlaceboIO.new i, out: o
127
+ io = GReactor.add_raw_io i, io
109
128
  new_class.new(io)
110
129
  end
111
130
  end
@@ -12,12 +12,12 @@ module Plezi
12
12
  # sends a response for an error code, rendering the relevent file (if exists).
13
13
  def send_by_code request, response, code, headers = {}
14
14
  begin
15
- base_code_path = request.io[:params][:templates] || File.expand_path('.')
15
+ base_code_path = request.io.params[:templates] || File.expand_path('.')
16
16
  if defined?(::Slim) && Plezi.file_exists?(fn = File.join(base_code_path, "#{code}.html.slim"))
17
17
  Plezi.cache_data fn, Slim::Template.new( fn ) unless Plezi.cached? fn
18
18
  return send_raw_data request, response, Plezi.get_cached( fn ).render( self, request: request ), 'text/html', code, headers
19
19
  elsif defined?(::Haml) && Plezi.file_exists?(fn = File.join(base_code_path, "#{code}.html.haml"))
20
- Plezi.cache_data fn, Haml::Engine.new( IO.read( fn ) ) unless Plezi.cached? fn
20
+ Plezi.cache_data fn, Haml::Engine.new( IO.binread( fn ) ) unless Plezi.cached? fn
21
21
  return send_raw_data request, response, Plezi.get_cached( File.join(base_code_path, "#{code}.html.haml") ).render( self ), 'text/html', code, headers
22
22
  elsif defined?(::ERB) && Plezi.file_exists?(fn = File.join(base_code_path, "#{code}.html.erb"))
23
23
  return send_raw_data request, response, ERB.new( Plezi.load_file( fn ) ).result(binding), 'text/html', code, headers
@@ -1,3 +1,3 @@
1
1
  module Plezi
2
- VERSION = "0.10.8"
2
+ VERSION = "0.10.9"
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.11"
21
+ spec.add_dependency "grhttp", "~> 0.0.12"
22
22
  spec.add_development_dependency "bundler", "~> 1.7"
23
23
  spec.add_development_dependency "rake", "~> 10.0"
24
24
 
@@ -14,7 +14,7 @@
14
14
  </style>
15
15
  <script>
16
16
  var websocket = NaN;
17
- function connect() { websocket = new WebSocket('ws://' + window.location.hostname + (window.location.port == '' ? '' : (':' + window.location.port) ) + "/" ); }
17
+ function connect() { websocket = new WebSocket( (window.location.protocol.match(/https/) ? 'wws' : 'ws') + '://' + window.location.hostname + (window.location.port == '' ? '' : (':' + window.location.port) ) + "/" ); }
18
18
  function init()
19
19
  {
20
20
  connect()
@@ -175,7 +175,7 @@ input[type=submit]:active
175
175
  </style>
176
176
  <script type="text/javascript">
177
177
  // Your websocket URI should be an absolute path. The following sets the base URI.
178
- var ws_uri = 'ws://' + window.location.hostname + (window.location.port == '' ? '' : (':' + window.location.port) );
178
+ var ws_uri = (window.location.protocol.match(/https/) ? 'wss' : 'ws') + '://' + window.location.hostname + (window.location.port == '' ? '' : (':' + window.location.port) );
179
179
  // remember to add the specific controller's path to your websocket URI.
180
180
  ws_uri += "/";
181
181
  // websocket variable.
@@ -246,6 +246,7 @@ module PleziTestTasks
246
246
  ws = GRHttp::WSClient.connect_to("ws://localhost:3000/ws/placebo") {|ws| 'ME?'}
247
247
  ws << " * Placebo WS connected."
248
248
  sleep 2
249
+ ws.close
249
250
  rescue => e
250
251
  puts " **** Placebo test FAILED TO RUN!!!"
251
252
  puts e
@@ -387,7 +388,7 @@ end
387
388
  r = Plezi::Placebo.new PlaceboCtrl
388
389
  puts " * Create Placebo test: #{PleziTestTasks::RESULTS[r && true]}"
389
390
 
390
- PL.create_logger '/dev/null'
391
+ PL.create_logger nil
391
392
  # PL::Settings.max_threads = 4
392
393
 
393
394
  listen port: 3000
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plezi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.8
4
+ version: 0.10.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.0.11
19
+ version: 0.0.12
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.11
26
+ version: 0.0.12
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement