plezi 0.12.22 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/LICENSE.txt +17 -18
  4. data/README.md +54 -698
  5. data/Rakefile +7 -4
  6. data/bin/config.ru +22 -0
  7. data/{test → bin}/console +4 -6
  8. data/bin/hello_world +52 -0
  9. data/bin/setup +8 -0
  10. data/exe/plezi +145 -0
  11. data/lib/plezi.rb +24 -137
  12. data/lib/plezi/activation.rb +28 -0
  13. data/lib/plezi/api.rb +62 -0
  14. data/lib/plezi/controller/controller.rb +259 -0
  15. data/lib/plezi/controller/controller_class.rb +176 -0
  16. data/lib/plezi/controller/cookies.rb +40 -0
  17. data/lib/plezi/helpers.rb +60 -0
  18. data/lib/plezi/rake.rb +2 -24
  19. data/lib/plezi/render/erb.rb +34 -0
  20. data/lib/plezi/render/has_cache.rb +36 -0
  21. data/lib/plezi/render/markdown.rb +63 -0
  22. data/lib/plezi/render/render.rb +49 -0
  23. data/lib/plezi/render/sass.rb +55 -0
  24. data/lib/plezi/render/slim.rb +33 -0
  25. data/lib/plezi/router/adclient.rb +23 -0
  26. data/lib/plezi/router/assets.rb +67 -0
  27. data/lib/plezi/router/errors.rb +29 -0
  28. data/lib/plezi/router/route.rb +112 -0
  29. data/lib/plezi/router/router.rb +120 -0
  30. data/lib/plezi/version.rb +1 -1
  31. data/lib/plezi/websockets/message_dispatch.rb +91 -0
  32. data/lib/plezi/websockets/redis.rb +55 -0
  33. data/plezi.gemspec +25 -16
  34. data/resources/404.erb +5 -4
  35. data/resources/500.erb +5 -4
  36. data/resources/{500.html → 503.html} +8 -9
  37. data/resources/client.js +253 -0
  38. data/resources/config.ru +5 -36
  39. data/resources/ctrlr.rb +34 -0
  40. data/resources/gemfile +4 -0
  41. data/resources/mini_app.rb +28 -82
  42. data/resources/mini_exec +7 -0
  43. data/resources/mini_welcome_page.html +0 -0
  44. data/resources/procfile +3 -0
  45. data/resources/rakefile +4 -8
  46. data/resources/routes.rb +9 -26
  47. data/resources/{websockets.js → simple-client.js} +3 -3
  48. metadata +60 -85
  49. data/bin/plezi +0 -104
  50. data/docs/async_helpers.md +0 -245
  51. data/docs/controllers.md +0 -27
  52. data/docs/logging.md +0 -49
  53. data/docs/routes.md +0 -209
  54. data/docs/websockets.md +0 -213
  55. data/lib/plezi/builders/ac_model.rb +0 -59
  56. data/lib/plezi/builders/app_builder.rb +0 -137
  57. data/lib/plezi/builders/builder.rb +0 -43
  58. data/lib/plezi/builders/form_builder.rb +0 -27
  59. data/lib/plezi/common/api.rb +0 -92
  60. data/lib/plezi/common/cache.rb +0 -122
  61. data/lib/plezi/common/defer.rb +0 -21
  62. data/lib/plezi/common/dsl.rb +0 -94
  63. data/lib/plezi/common/redis.rb +0 -65
  64. data/lib/plezi/common/renderer.rb +0 -141
  65. data/lib/plezi/common/settings.rb +0 -52
  66. data/lib/plezi/handlers/controller_core.rb +0 -106
  67. data/lib/plezi/handlers/controller_magic.rb +0 -284
  68. data/lib/plezi/handlers/http_router.rb +0 -205
  69. data/lib/plezi/handlers/placebo.rb +0 -112
  70. data/lib/plezi/handlers/route.rb +0 -216
  71. data/lib/plezi/handlers/session.rb +0 -109
  72. data/lib/plezi/handlers/stubs.rb +0 -156
  73. data/lib/plezi/handlers/ws_identity.rb +0 -253
  74. data/lib/plezi/handlers/ws_object.rb +0 -308
  75. data/lib/plezi/helpers/http_sender.rb +0 -84
  76. data/lib/plezi/helpers/magic_helpers.rb +0 -104
  77. data/lib/plezi/helpers/mime_types.rb +0 -1995
  78. data/lib/plezi/oauth.rb +0 -5
  79. data/lib/plezi/oauth/auth_controller.rb +0 -229
  80. data/logo/dark.png +0 -0
  81. data/logo/light.png +0 -0
  82. data/logo/sign.png +0 -0
  83. data/resources/404.haml +0 -121
  84. data/resources/404.html +0 -124
  85. data/resources/404.slim +0 -120
  86. data/resources/500.haml +0 -120
  87. data/resources/500.slim +0 -120
  88. data/resources/Gemfile +0 -86
  89. data/resources/code.rb +0 -8
  90. data/resources/controller.rb +0 -142
  91. data/resources/database.yml +0 -33
  92. data/resources/db_ac_config.rb +0 -59
  93. data/resources/db_dm_config.rb +0 -51
  94. data/resources/db_sequel_config.rb +0 -33
  95. data/resources/en.yml +0 -204
  96. data/resources/haml_config.rb +0 -6
  97. data/resources/i18n_config.rb +0 -14
  98. data/resources/initialize.rb +0 -49
  99. data/resources/mini_exec.rb +0 -7
  100. data/resources/oauth_config.rb +0 -24
  101. data/resources/plezi_client.js +0 -198
  102. data/resources/plezi_websockets.html +0 -47
  103. data/resources/redis_config.rb +0 -42
  104. data/resources/slim_config.rb +0 -11
  105. data/resources/welcome_page.html +0 -272
  106. data/test/dispatch +0 -58
  107. data/test/hello_world +0 -13
  108. data/test/plezi_tests.rb +0 -581
data/Rakefile CHANGED
@@ -1,7 +1,10 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rake/testtask"
2
3
 
3
- # create a default task
4
- desc "Tests most of the basic features for the Plezi framework."
5
- task :test do
6
- load "./test/plezi_tests.rb"
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
7
8
  end
9
+
10
+ task :default => :test
data/bin/config.ru ADDED
@@ -0,0 +1,22 @@
1
+ require 'benchmark'
2
+
3
+ require 'plezi'
4
+ # our Plezi application
5
+ class MyCtrl
6
+ def index
7
+ 'Hello from Plezi!'
8
+ end
9
+ end
10
+ # rewites
11
+ Plezi.route '(:format)', /^(json|html)$/
12
+ # Our Plezi route
13
+ Plezi.route 'plezi/*', MyCtrl
14
+ # The Rack application
15
+ app = proc { |env| req = Rack::Request.new(env); str = "Params: #{req.params}"; [200, { 'Content-Length' => str.bytesize.to_s }, [str]] }
16
+ # Use Plezi as Middleware
17
+ use Plezi
18
+ # run our Rack application
19
+ run app
20
+
21
+ # ab -n 1000000 -c 2000 -k http://127.0.0.1:3000/
22
+ # wrk -c400 -d5 -t12 http://localhost:3000/
@@ -1,10 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
2
 
4
- require 'benchmark'
5
- $LOAD_PATH.unshift File.expand_path(File.join('..', '..', 'lib'), __FILE__ )
6
- require "plezi"
7
- require "bundler/setup"
3
+ Dir.chdir(File.expand_path(File.join('..', '..', 'lib'), __FILE__))
4
+ require 'bundler/setup'
5
+ require 'plezi'
8
6
 
9
7
  # You can add fixtures and/or initialization code here to make experimenting
10
8
  # with your gem easier. You can also use a different console, if you like.
@@ -13,5 +11,5 @@ require "bundler/setup"
13
11
  # require "pry"
14
12
  # Pry.start
15
13
 
16
- require "irb"
14
+ require 'irb'
17
15
  IRB.start
data/bin/hello_world ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+ require 'benchmark'
3
+ Dir.chdir(File.expand_path(File.join('..', '..', 'lib'), __FILE__))
4
+ require 'bundler/setup'
5
+ require 'plezi'
6
+ class WebsocketSample
7
+ # every request that routes to this controller will create a new instance
8
+ def initialize
9
+ end
10
+
11
+ # Http methods are available
12
+ def index
13
+ 'Hello World!'
14
+ end
15
+
16
+ # RESTful methods are available
17
+ def show
18
+ "showing object with id: #{params['id']}..."
19
+ end
20
+
21
+ # called before the protocol is swithed from HTTP to WebSockets.
22
+ #
23
+ # this allows setting headers, cookies and other data (such as authentication)
24
+ # prior to opening a WebSocket.
25
+ #
26
+ # if the method returns false, the connection will be refused and the remaining routes will be attempted.
27
+ def pre_connect
28
+ true
29
+ end
30
+
31
+ # called immediately after a WebSocket connection has been established.
32
+ # it blocks all the connection's actions until the `on_open` initialization is finished.
33
+ def on_open
34
+ end
35
+
36
+ # called when new data is recieved
37
+ #
38
+ # data is a string that contains binary or UTF8 (message dependent) data.
39
+ def on_message(data)
40
+ Plezi.info "Websocket got: #{data}"
41
+ end
42
+
43
+ # called once, AFTER the connection was closed.
44
+ def on_close
45
+ end
46
+
47
+ # called once, during **server shutdown**, BEFORE the connection is closed.
48
+ # this will only be called for connections that are open while the server is shutting down.
49
+ def on_shutdown
50
+ end
51
+ end
52
+ Plezi.route '/', WebsocketSample
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/exe/plezi ADDED
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env ruby
2
+ $0 = 'Plezi Builder'
3
+ # count lines of code with: ^[ \t]*[\w\d\"\(\{\@\[\]\}\)\:\'\.\*\&]+.*$
4
+ require 'pathname'
5
+ require 'securerandom'
6
+ ######################################################################
7
+ # tweek the string class for termial coloring options
8
+ class String
9
+ # colorization
10
+ def colorize(color_code)
11
+ "\e[#{color_code}m#{self}\e[0m"
12
+ end
13
+
14
+ def red
15
+ colorize(31)
16
+ end
17
+
18
+ def green
19
+ colorize(32)
20
+ end
21
+
22
+ def yellow
23
+ colorize(33)
24
+ end
25
+
26
+ def pink
27
+ colorize(35)
28
+ end
29
+ end
30
+
31
+ module Builder
32
+ Root ||= Pathname.new(File.dirname(__FILE__)).expand_path.join('..')
33
+
34
+ def self.app_tree
35
+ @app_tree ||= {}.dup
36
+ end
37
+
38
+ def self.write_files(files, parent = '.')
39
+ if files.is_a? Hash
40
+ files.each do |k, v|
41
+ if v.is_a? Hash
42
+ begin
43
+ Dir.mkdir k
44
+ puts " created #{parent}/#{k}".green
45
+ rescue => e
46
+ puts " exists #{parent}/#{k}".red
47
+ end
48
+ Dir.chdir k
49
+ write_files v, (parent + '/' + k)
50
+ Dir.chdir '..'
51
+ elsif v.is_a? String
52
+ if ::File.exist? k
53
+ puts " EXISTS(!) #{parent}/#{k}".red
54
+ else
55
+ IO.write k, v
56
+ puts " wrote #{parent}/#{k}".yellow
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ def self.create_app(app_name = ARGV[1])
64
+ require Root.join('lib', 'plezi', 'version')
65
+ app_tree[app_name.to_s] ||= IO.read(Root.join('resources', 'mini_exec')).gsub('appname', app_name)
66
+ app_tree["#{app_name}.rb"] ||= IO.read(Root.join('resources', 'mini_app.rb')).gsub('appname', app_name).gsub('appsecret', "#{app_name}_#{SecureRandom.hex}")
67
+ app_tree['routes.rb'] ||= IO.read(Root.join('resources', 'routes.rb')).gsub('appname', app_name)
68
+ app_tree['config.ru'] ||= IO.read(Root.join('resources', 'config.ru')).gsub('appname', app_name)
69
+ app_tree['Procfile'] ||= IO.read(Root.join('resources', 'procfile')).gsub('appname', app_name)
70
+ app_tree['Gemfile'] ||= ''
71
+ app_tree['Gemfile'] << "source 'https://rubygems.org'\n\n# include the basic plezi framework and server\ngem 'plezi', '~> #{Plezi::VERSION}'\n"
72
+ app_tree['Gemfile'] << IO.read(Root.join('resources', 'gemfile'))
73
+ app_tree['Gemfile'] << "\n\nruby '#{RUBY_VERSION}'\n"
74
+ app_tree['rakefile'] ||= IO.read(Root.join('resources', 'rakefile'))
75
+ app_tree['app'] ||= {}
76
+ app_tree['app']['my_controler.rb'] ||= IO.read(Root.join('resources', 'ctrlr.rb')).gsub('appname', app_name)
77
+ app_tree['views'] ||= {}
78
+ app_tree['views']['welcome.html.erb'] ||= IO.read(Root.join('resources', 'mini_welcome_page.html')).gsub('appname', app_name)
79
+ app_tree['views']['404.html.erb'] ||= IO.read(Root.join('resources', '404.erb'))
80
+ app_tree['views']['500.html.erb'] ||= IO.read(Root.join('resources', '500.erb'))
81
+ app_tree['views']['503.html'] ||= IO.read(Root.join('resources', '503.html'))
82
+ app_tree['public'] ||= {}
83
+ app_tree['public']['javascripts'] ||= {}
84
+ app_tree['public']['javascripts']['client.js'] ||= IO.read(Root.join('resources', 'client.js')).gsub('appname', app_name)
85
+ app_tree['public']['javascripts']['simple-client.js'] ||= IO.read(Root.join('resources', 'simple-client.js')).gsub('appname', app_name)
86
+
87
+ begin
88
+ Dir.mkdir app_name
89
+ puts "created the #{app_name} application directory.".green
90
+ rescue => e
91
+ puts "the #{app_name} application directory exists - trying to rebuild (no overwrite).".pink
92
+ end
93
+ Dir.chdir app_name
94
+ puts 'starting to write template data...'.red
95
+ puts ''
96
+ Builder.write_files app_tree
97
+ begin
98
+ File.chmod 0o775, app_name.to_s
99
+ rescue
100
+ true
101
+ end
102
+ puts 'done.'
103
+ puts ''
104
+ puts "please change directory into the app directory: cd #{app_name}"
105
+ puts ''
106
+ puts "run the #{app_name} app using: ./#{app_name} or using the iodine / rackup commands."
107
+ puts ''
108
+ end
109
+ end
110
+
111
+ ######################################################################
112
+ ######################################################################
113
+ ##
114
+ ## Start the Build script
115
+ ##
116
+ ######################################################################
117
+ ######################################################################
118
+
119
+ # update with http://ruby-doc.org/stdlib-2.2.0/libdoc/optparse/rdoc/OptionParser.html
120
+
121
+ # require 'optparser'
122
+
123
+ if ARGV[0] == 'new' || ARGV[0] == 'n' || ARGV[0] == 'force'
124
+ #########
125
+ ## set up building environment
126
+ ARGV[1] = ARGV[1].gsub(/[^a-zA-Z0-9]/, '_')
127
+ ARGV[1].downcase!
128
+ if Dir.exist?(ARGV[1]) && ARGV[0] != 'force'
129
+ puts ''
130
+ puts "WARNING: app/folder alread exists, use `plezi fource #{ARGV[1]}` to attempt rebuild (no files will be overwritten).".red
131
+ puts ''
132
+ exit
133
+ end
134
+ Builder.create_app
135
+ else
136
+ puts ''
137
+ puts 'Plezi fast web app starter.'.pink
138
+ puts 'use: plezi new appname'
139
+ puts 'or: plezi n appname'
140
+ puts ''
141
+ puts "Run the app using the app's script with an optional: -p {port number}. i.e."
142
+ puts ' cd ./appname'.pink
143
+ puts ' ./appname -p 8080'.pink
144
+ puts ''
145
+ end
data/lib/plezi.rb CHANGED
@@ -1,147 +1,34 @@
1
- ### Ruby core extentions
1
+ require 'plezi/version'
2
+ require 'iodine'
2
3
 
3
- require 'singleton'
4
- require 'pathname'
5
- require 'base64'
6
- require 'digest/sha1'
7
- require 'securerandom'
8
- require 'time'
9
- require 'json'
10
- require 'yaml'
11
- require 'uri'
12
- require 'set'
13
-
14
- # Iodine server
15
- require 'iodine/http'
16
-
17
- ### version
18
-
19
- require "plezi/version"
20
-
21
- ### common
22
-
23
- require 'plezi/common/defer.rb'
24
- require 'plezi/common/cache.rb'
25
- require 'plezi/common/api.rb'
26
- require 'plezi/common/dsl.rb'
27
- require 'plezi/common/redis.rb'
28
- require 'plezi/common/settings.rb'
29
- require 'plezi/common/renderer.rb'
30
-
31
- ### helpers
32
- require 'plezi/helpers/magic_helpers.rb'
33
- require 'plezi/helpers/mime_types.rb'
34
-
35
- ### HTTP and WebSocket Handlers
36
- require 'plezi/handlers/http_router.rb'
37
- require 'plezi/handlers/route.rb'
38
- require 'plezi/handlers/ws_object.rb'
39
- require 'plezi/handlers/ws_identity.rb'
40
- require 'plezi/handlers/controller_magic.rb'
41
- require 'plezi/handlers/controller_core.rb'
42
- require 'plezi/handlers/placebo.rb'
43
- require 'plezi/handlers/stubs.rb'
44
- require 'plezi/handlers/session.rb'
45
-
46
- # error and last resort handling
47
- require 'plezi/helpers/http_sender.rb'
48
-
49
- ## erb templating
50
- begin
51
- require 'erb'
52
- rescue
4
+ require 'plezi/api'
5
+ require 'plezi/controller/controller'
53
6
 
7
+ # Plezi is amazing. Read the {README}
8
+ module Plezi
9
+ # Shhh... the modules and classes defined under the {Base} namespace are sleeping...
10
+ #
11
+ # The namespace signifies that Plezi uses these modules and classes internally.
12
+ # We don't need to worry about these unless we're monkey-patching stuff or contributing to the Plezi project.
13
+ module Base
14
+ end
54
15
  end
55
16
 
56
- ##############################################################################
57
- #
58
- # 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.
59
- #
60
- # Plezi is a wonderful alternative to Socket.io which makes writing the server using Ruby a breeze.
61
- #
62
- # Plezi is multi-threaded by default (you can change this) and supports asynchronous callbacks,
63
- # so it will keep going even if some requests take a while to compute.
64
- #
65
- # Plezi routes accept controller classes, which makes RESTful and WebSocket applications easy to write.
66
- # For example, open your Ruby terminal (the `irb` command) and type:
67
- #
68
- # require 'plezi'
69
- # route "*", Plezi::StubRESTCtrl
70
- # exit # will start the service.
71
- #
72
- # Controller classes don't need to inherit anything :-)
73
- #
74
- # Plezi's routing systems inherits the Controller class, allowing you more freedom in your code.
75
- #
76
- # require 'plezi'
77
- # class MyController
78
- # def index
79
- # "Hello World!"
80
- # end
81
- # end
82
- # route "*", MyController
17
+ ###############
18
+ ## Dev notes.
19
+ ###############
83
20
  #
84
- # exit # I'll stop writing this line every time.
21
+ # Plezi 0.13.0 is heaviliy Rack based. Whenever Possible, Rack middleware was preffered.
22
+ # The is a list of available Rack middleware:
23
+ # * https://github.com/rack/rack/wiki/List-of-Middleware
85
24
  #
86
- # Amazing(!), right? - You can read more in the documentation for Plezi::StubWSCtrl and Plezi::StubRESTCtrl, which are stub classes used for testing routes.
87
25
  #
88
- # Plezi routes accept Regexp's (regular exceptions) for route paths.
89
- # Plezi also accepts an optional block instead of the conrtoller Class object for example:
90
26
  #
91
- # require 'plezi'
92
- # route(/[.]*/) {|request, response| response << "Your request, master: #{request.path}."}
93
27
  #
94
- # As you may have noticed before, the catch-all route (/[.]*/) has a shortcut: '*'.
95
28
  #
96
- # class routes that have a specific path (including root, but not a catch-all or Regexp path)
97
- # accept an implied `params[:id]` variable. the following path ('/'):
98
- #
99
- # require 'plezi'
100
- # route "/", Plezi::StubWSCtrl
101
- # # go to: http://localhost:3000/1
102
- # # => Plezi::StubRESTCtrl.new.show() # where params[:id] == 1
103
- #
104
- # it is possible to use "magic" routes (i.e. `/resource/:type/(:id)/(:date){/[0-9]{8}}/:foo`) and it is also possible to set the appropriate parameters within the `before` method of the Conltroller.
105
- #
106
- # Routes are handled in the order they are created. If overlapping routes exist, the first will execute first:
107
- #
108
- # require 'plezi'
109
- # route('*') do |request, response|
110
- # response << "Your request, master: #{request.path}." unless request.path.match /cats/
111
- # end
112
- # route('*') {|request, response| response.body << "Ahhh... I love cats!"}
113
- #
114
- # The Plezi module (also `PL`) also has methods to help with asynchronous tasking, callbacks, timers and customized shutdown cleanup.
115
- #
116
- # Heres a short demo fir asynchronous callbacks (works only while services are active and running):
117
- #
118
- # require 'plezi'
119
- #
120
- # def my_shutdown_proc time_start
121
- # puts "Services were running for #{Time.now - time_start} ms."
122
- # end
123
- #
124
- # # shutdown callbacks
125
- # PL.on_shutdown(Kernel, :my_shutdown_proc, Time.now) { puts "this will run after shutdown." }
126
- # PL.on_shutdown() { puts "this will run too." }
127
- #
128
- # # a timer
129
- # PL.run_after 2, -> {puts "this will wait 2 seconds to run... too late. for this example"}
130
- #
131
- # # remember to exit to make it all start
132
- # exit
133
- #
134
- # all the examples above shoold be good to run from irb. updated examples can be found at the Readme file in the Github project: https://github.com/boazsegev/plezi
135
- #
136
- # thanks to Russ Olsen for his ideas for a DSL and his blog post at:
137
- # http://www.jroller.com/rolsen/entry/building_a_dsl_in_ruby1
138
- #
139
- # ...he doesn't know it, but he inspired a revolution.
140
- ##############################################################################
141
- module Plezi
142
- end
143
-
144
- Iodine.threads = 30
145
- Iodine.run { puts "Plezi is feeling optimistic running version #{::Plezi::VERSION}.\n\n"}
146
- # PL is a shortcut for the Plezi module, so that `PL == Plezi`.
147
- PL = Plezi
29
+ # def uuid
30
+ # @uuid ||= SecureRandom.uuid
31
+ # end
32
+ # def redis_channel_name
33
+ # @redis_channel_name ||= "#{File.basename($0, '.*')}_redis_channel"
34
+ # end
@@ -0,0 +1,28 @@
1
+ require 'plezi/websockets/message_dispatch' unless defined?(::Plezi::Base::MessageDispatch)
2
+
3
+ module Plezi
4
+ protected
5
+
6
+ @plezi_finalize = nil
7
+ def plezi_finalize
8
+ if @plezi_finalize.nil?
9
+ @plezi_finalize = true
10
+ @plezi_finalize = 1
11
+ end
12
+ end
13
+ @plezi_initialize = nil
14
+ def self.plezi_initialize
15
+ ::Plezi::Base::MessageDispatch._init
16
+ if @plezi_initialize.nil?
17
+ @plezi_initialize = true
18
+ @plezi_autostart = true if @plezi_autostart.nil?
19
+ at_exit do
20
+ next if @plezi_autostart == false
21
+ ::Iodine::Rack.app = ::Plezi.app
22
+ ::Iodine.threads ||= 16
23
+ ::Iodine.start
24
+ end
25
+ end
26
+ true
27
+ end
28
+ end