mizuno 0.5.1 → 0.6.0
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.
- data/README.markdown +7 -11
- data/Rakefile +6 -4
- data/lib/java/{jetty-continuation-8.0.4.v20111024.jar → jetty-continuation-8.1.2.v20120308.jar} +0 -0
- data/lib/java/jetty-http-8.1.2.v20120308.jar +0 -0
- data/lib/java/jetty-io-8.1.2.v20120308.jar +0 -0
- data/lib/java/jetty-jmx-8.1.2.v20120308.jar +0 -0
- data/lib/java/jetty-security-8.1.2.v20120308.jar +0 -0
- data/lib/java/jetty-server-8.1.2.v20120308.jar +0 -0
- data/lib/java/jetty-servlet-8.1.2.v20120308.jar +0 -0
- data/lib/java/jetty-servlets-8.1.2.v20120308.jar +0 -0
- data/lib/java/jetty-util-8.1.2.v20120308.jar +0 -0
- data/lib/java/rewindable-input-stream.jar +0 -0
- data/lib/java/servlet-api-3.0.jar +0 -0
- data/lib/mizuno/choices.rb +8 -2
- data/lib/mizuno/http_server.rb +6 -3
- data/lib/mizuno/reloader.rb +147 -0
- data/lib/mizuno/runner.rb +56 -30
- data/lib/mizuno/version.rb +1 -1
- data/lib/rack/handler/mizuno.rb +4 -0
- data/mizuno.gemspec +2 -0
- metadata +13 -11
- data/lib/java/jetty-http-8.0.4.v20111024.jar +0 -0
- data/lib/java/jetty-io-8.0.4.v20111024.jar +0 -0
- data/lib/java/jetty-jmx-8.0.4.v20111024.jar +0 -0
- data/lib/java/jetty-security-8.0.4.v20111024.jar +0 -0
- data/lib/java/jetty-server-8.0.4.v20111024.jar +0 -0
- data/lib/java/jetty-servlet-8.0.4.v20111024.jar +0 -0
- data/lib/java/jetty-servlets-8.0.4.v20111024.jar +0 -0
- data/lib/java/jetty-util-8.0.4.v20111024.jar +0 -0
data/README.markdown
CHANGED
@@ -11,27 +11,23 @@ container for your Rack application to run under JRuby, because Mizuno
|
|
11
11
|
works just like Mongrel, WEBRick, Thin, or any other standard Rack
|
12
12
|
handler.
|
13
13
|
|
14
|
-
Mizuno is the fastest option for Rack applications on JRuby:
|
15
|
-
|
16
|
-
Mizuno: 6106.66 req/s (mean)
|
17
|
-
Jetty (via jruby-rack): 2011.67 req/s (mean)
|
18
|
-
Mongrel: 1479.15 req/sec (mean)
|
19
|
-
|
20
14
|
Mizuno also supports asynchronous request handling, via the Java Servlet
|
21
15
|
3.0 asynchronous processing mechanism
|
22
16
|
|
23
|
-
All the speed comes from Jetty
|
17
|
+
All the speed comes from Jetty 8; Mizuno just ties it to Rack through
|
24
18
|
JRuby's Ruby/Java integration layer.
|
25
19
|
|
26
20
|
Note that Mizuno is NOT a direct replacement for jruby-rack or Warbler,
|
27
21
|
because it doesn't produce WAR files or make any attempt to package a
|
28
22
|
Rack application for installation in a Java web container.
|
29
23
|
|
30
|
-
|
24
|
+
You can also run Mizuno via rackup:
|
25
|
+
|
26
|
+
rackup -s mizuno
|
27
|
+
|
28
|
+
Or with live reloading support:
|
31
29
|
|
32
|
-
|
33
|
-
2. Add hooks for realtime monitoring of server performance.
|
34
|
-
3. Fast restarts of the Rack application.
|
30
|
+
mizuno --reloadable
|
35
31
|
|
36
32
|
Mizuno is licensed under the Apache Public License, version 2.0; see
|
37
33
|
the LICENSE file for details, and was developed on behalf of
|
data/Rakefile
CHANGED
@@ -6,6 +6,8 @@ RSpec::Core::RakeTask.new(:spec)
|
|
6
6
|
|
7
7
|
task :default => :spec
|
8
8
|
|
9
|
+
# http://rubydoc.info/gems/pompompom/1.1.3/frames
|
10
|
+
|
9
11
|
namespace :jetty do
|
10
12
|
desc "Grab the latest Jetty from its Maven repository."
|
11
13
|
task :update do
|
@@ -40,15 +42,15 @@ namespace :jetty do
|
|
40
42
|
# Inventory contents of the tarball we picked up.
|
41
43
|
inventory = `tar tzf #{tempfile}`.split(/\n/)
|
42
44
|
|
43
|
-
#
|
45
|
+
# Figure out which JARs we should replce with tarball contents.
|
44
46
|
replacements = {}
|
45
47
|
Dir.entries(jar_path).each do |entry|
|
46
|
-
next unless (entry =~
|
48
|
+
next unless ((entry =~ /^jetty-\w.*\d\.jar$/) \
|
49
|
+
or (entry =~ /^servlet-api.*\d\.jar$/))
|
47
50
|
name = entry.sub(/\-\d.*$/, '')
|
48
51
|
matcher = /\/#{name}\-[^\/]+\d\.jar$/
|
49
52
|
archive_file = inventory.find { |i| i =~ matcher }
|
50
|
-
|
51
|
-
unless archive_file
|
53
|
+
next unless archive_file
|
52
54
|
replacements[entry] = archive_file
|
53
55
|
end
|
54
56
|
|
data/lib/java/{jetty-continuation-8.0.4.v20111024.jar → jetty-continuation-8.1.2.v20120308.jar}
RENAMED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/lib/mizuno/choices.rb
CHANGED
@@ -76,7 +76,7 @@ Choice.options do
|
|
76
76
|
end
|
77
77
|
|
78
78
|
separator ''
|
79
|
-
separator '
|
79
|
+
separator 'Mizuno-specific options: '
|
80
80
|
|
81
81
|
option :daemonize do
|
82
82
|
short '-D'
|
@@ -105,7 +105,13 @@ Choice.options do
|
|
105
105
|
|
106
106
|
option :reload do
|
107
107
|
long '--reload'
|
108
|
-
desc '
|
108
|
+
desc 'reloads a running mizuno instance'
|
109
|
+
default false
|
110
|
+
end
|
111
|
+
|
112
|
+
option :reloadable do
|
113
|
+
long '--reloadable'
|
114
|
+
desc 'sets up live reloading via mizuno/reloader'
|
109
115
|
default false
|
110
116
|
end
|
111
117
|
|
data/lib/mizuno/http_server.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'mizuno/version'
|
2
2
|
require 'mizuno/java_logger'
|
3
|
+
require 'mizuno/reloader'
|
3
4
|
|
4
5
|
module Mizuno
|
5
6
|
class HttpServer
|
@@ -73,6 +74,11 @@ module Mizuno
|
|
73
74
|
app_handler = ServletContextHandler.new(nil, "/",
|
74
75
|
ServletContextHandler::NO_SESSIONS)
|
75
76
|
|
77
|
+
# Optionally wrap with Mizuno::Reloader.
|
78
|
+
threshold = (ENV['RACK_ENV'] == 'production' ? 10 : 1)
|
79
|
+
app = Mizuno::Reloader.new(app, threshold) \
|
80
|
+
if options[:reloadable]
|
81
|
+
|
76
82
|
# The servlet itself.
|
77
83
|
rack_servlet = RackServlet.new
|
78
84
|
rack_servlet.rackup(app)
|
@@ -175,8 +181,5 @@ module Mizuno
|
|
175
181
|
end
|
176
182
|
end
|
177
183
|
|
178
|
-
# Register ourselves with Rack when this file gets loaded.
|
179
|
-
Rack::Handler.register 'mizuno', 'Mizuno::HttpServer'
|
180
|
-
|
181
184
|
# Ensure that we shutdown the server on exit.
|
182
185
|
at_exit { Mizuno::HttpServer.stop }
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
#:nodoc:
|
5
|
+
module Mizuno
|
6
|
+
#
|
7
|
+
# Middleware for reloading production applications; works exactly
|
8
|
+
# like Rack::Reloader, but rather than checking for any changed
|
9
|
+
# file, only looks at one specific file.
|
10
|
+
#
|
11
|
+
# Also allows for explicit reloading via a class method, as well as
|
12
|
+
# by sending a SIGHUP to the process.
|
13
|
+
#
|
14
|
+
class Reloader
|
15
|
+
class << self
|
16
|
+
attr_accessor :logger, :trigger, :reloaders
|
17
|
+
end
|
18
|
+
|
19
|
+
def Reloader.reload!
|
20
|
+
reloaders.each { |r| r.reload!(true) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(app, interval = 1)
|
24
|
+
Thread.exclusive do
|
25
|
+
self.class.reloaders ||= []
|
26
|
+
self.class.reloaders << self
|
27
|
+
self.class.logger ||= Mizuno::HttpServer.logger
|
28
|
+
self.class.trigger ||= "tmp/restart.txt"
|
29
|
+
end
|
30
|
+
|
31
|
+
@app = app
|
32
|
+
@interval = interval
|
33
|
+
@trigger = self.class.trigger
|
34
|
+
@logger = self.class.logger
|
35
|
+
@updated = @threshold = Time.now.to_i
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Reload @app on request.
|
40
|
+
#
|
41
|
+
def call(env)
|
42
|
+
Thread.exclusive { reload! }
|
43
|
+
@app.call(env)
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Reloads the application if (a) we haven't reloaded in
|
48
|
+
# @interval seconds, (b) the trigger file has been touched
|
49
|
+
# since our last check, and (c) some other thread hasn't handled
|
50
|
+
# the update.
|
51
|
+
#
|
52
|
+
def reload!(force = false)
|
53
|
+
return unless (Time.now.to_i > @threshold)
|
54
|
+
@threshold = Time.now.to_i + @interval
|
55
|
+
return unless (force or \
|
56
|
+
((timestamp = mtime(@trigger)).to_i > @updated))
|
57
|
+
timestamp ||= Time.now.to_i
|
58
|
+
|
59
|
+
# Check updated files to ensure they're loadable.
|
60
|
+
missing, errors = 0, 0
|
61
|
+
files = find_files_for_reload do |file, file_mtime|
|
62
|
+
next(missing += 1 and nil) unless file_mtime
|
63
|
+
next unless (file_mtime >= @updated)
|
64
|
+
next(errors += 1 and nil) unless verify(file)
|
65
|
+
file
|
66
|
+
end
|
67
|
+
|
68
|
+
# Cowardly fail if we can't load something.
|
69
|
+
@logger.debug("#{missing} files missing during reload.") \
|
70
|
+
if (missing > 0)
|
71
|
+
return(@logger.error("#{errors} errors, not reloading.")) \
|
72
|
+
if (errors > 0)
|
73
|
+
|
74
|
+
# Reload everything that's changed.
|
75
|
+
files.each do |file|
|
76
|
+
next unless file
|
77
|
+
@logger.info("Reloading #{file}")
|
78
|
+
load(file)
|
79
|
+
end
|
80
|
+
@updated = timestamp
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# Walk through the list of every file we've loaded.
|
85
|
+
#
|
86
|
+
def find_files_for_reload
|
87
|
+
paths = [ './', *$LOAD_PATH ].uniq
|
88
|
+
[ $0, *$LOADED_FEATURES ].uniq.map do |file|
|
89
|
+
next if file =~ /\.(so|bundle)$/
|
90
|
+
yield(find(file, paths))
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# Returns true if the file is loadable; uses the wrapper
|
96
|
+
# functionality of Kernel#load to protect the global namespace.
|
97
|
+
#
|
98
|
+
def verify(file)
|
99
|
+
begin
|
100
|
+
@logger.debug("Verifying #{file}")
|
101
|
+
load(file, true)
|
102
|
+
return(true)
|
103
|
+
rescue => error
|
104
|
+
@logger.error("Failed to verify #{file}: #{error.to_s}")
|
105
|
+
error.backtrace.each { |l| @logger.error(" #{l}") }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
#
|
110
|
+
# Takes a relative or absolute +file+ name, a couple possible
|
111
|
+
# +paths+ that the +file+ might reside in. Returns a tuple of
|
112
|
+
# the full path where the file was found and its modification
|
113
|
+
# time, or nil if not found.
|
114
|
+
#
|
115
|
+
def find(file, paths)
|
116
|
+
if(Pathname.new(file).absolute?)
|
117
|
+
return unless (timestamp = mtime(file))
|
118
|
+
@logger.debug("Found #{file}")
|
119
|
+
[ file, timestamp ]
|
120
|
+
else
|
121
|
+
paths.each do |path|
|
122
|
+
fullpath = File.expand_path((File.join(path, file)))
|
123
|
+
next unless (timestamp = mtime(fullpath))
|
124
|
+
@logger.debug("Found #{file} in #{fullpath}")
|
125
|
+
return([ fullpath, timestamp ])
|
126
|
+
end
|
127
|
+
return(nil)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
#
|
132
|
+
# Returns the modification time of _file_.
|
133
|
+
#
|
134
|
+
def mtime(file)
|
135
|
+
begin
|
136
|
+
return unless file
|
137
|
+
stat = File.stat(file)
|
138
|
+
stat.file? ? stat.mtime.to_i : nil
|
139
|
+
rescue Errno::ENOENT, Errno::ENOTDIR
|
140
|
+
nil
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Reload on SIGHUP.
|
147
|
+
trap("SIGHUP") { Mizuno::Reloader.reload! }
|
data/lib/mizuno/runner.rb
CHANGED
@@ -8,6 +8,59 @@ require 'etc'
|
|
8
8
|
require 'rack'
|
9
9
|
|
10
10
|
module Mizuno
|
11
|
+
require 'rbconfig'
|
12
|
+
|
13
|
+
module Daemonizer
|
14
|
+
def self.included?(base)
|
15
|
+
if(Config::CONFIG['host_os'] =~ /mswin|mingw/)
|
16
|
+
base.send(:extend, StubbedClassMethods)
|
17
|
+
else
|
18
|
+
base.send(:extend, UnixClassMethods)
|
19
|
+
base.send(:class_eval) do
|
20
|
+
extend FFI::Library
|
21
|
+
ffi_lib 'c'
|
22
|
+
attach_function :_setuid, :setuid, [ :uint ], :int
|
23
|
+
attach_function :_setgid, :setgid, [ :uint ], :int
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
module UnixClassMethods
|
30
|
+
#
|
31
|
+
# Switch the process over to a new user id; will abort the
|
32
|
+
# process if it fails. _options_ is the full list of options
|
33
|
+
# passed to a server.
|
34
|
+
#
|
35
|
+
def setuid(options)
|
36
|
+
entry = Etc.getpwnam(options[:user])
|
37
|
+
die("Can't find --user named '#{options[:user]}'") \
|
38
|
+
unless entry
|
39
|
+
return unless (_setuid(entry.uid) != 0)
|
40
|
+
die("Can't switch to user '#{options[:user]}'")
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Like setuid, but for groups.
|
45
|
+
#
|
46
|
+
def setgid(options)
|
47
|
+
entry = Etc.getgrnam(options[:group])
|
48
|
+
die("Can't find --group named '#{options[:group]}'") \
|
49
|
+
unless entry
|
50
|
+
return unless (_setgid(entry.gid) != 0)
|
51
|
+
die("Can't switch to group '#{options[:group]}'")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module StubbedClassMethods
|
56
|
+
def setuid(options)
|
57
|
+
end
|
58
|
+
|
59
|
+
def setgid(options)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
11
64
|
#
|
12
65
|
# Launches Mizuno when called from the command-line, and handles
|
13
66
|
# damonization via FFI.
|
@@ -15,35 +68,7 @@ module Mizuno
|
|
15
68
|
# Daemonization code based on Spoon.
|
16
69
|
#
|
17
70
|
class Runner
|
18
|
-
|
19
|
-
|
20
|
-
ffi_lib 'c'
|
21
|
-
|
22
|
-
attach_function :_setuid, :setuid, [ :uint ], :int
|
23
|
-
|
24
|
-
attach_function :_setgid, :setgid, [ :uint ], :int
|
25
|
-
|
26
|
-
#
|
27
|
-
# Switch the process over to a new user id; will abort the
|
28
|
-
# process if it fails. _options_ is the full list of options
|
29
|
-
# passed to a server.
|
30
|
-
#
|
31
|
-
def Runner.setuid(options)
|
32
|
-
entry = Etc.getpwnam(options[:user])
|
33
|
-
die("Can't find --user named '#{options[:user]}'") unless entry
|
34
|
-
return unless (_setuid(entry.uid) != 0)
|
35
|
-
die("Can't switch to user '#{options[:user]}'")
|
36
|
-
end
|
37
|
-
|
38
|
-
#
|
39
|
-
# Like setuid, but for groups.
|
40
|
-
#
|
41
|
-
def Runner.setgid(options)
|
42
|
-
entry = Etc.getgrnam(options[:group])
|
43
|
-
die("Can't find --group named '#{options[:group]}'") unless entry
|
44
|
-
return unless (_setgid(entry.gid) != 0)
|
45
|
-
die("Can't switch to group '#{options[:group]}'")
|
46
|
-
end
|
71
|
+
include Daemonizer
|
47
72
|
|
48
73
|
#
|
49
74
|
# Launch Jetty, optionally as a daemon.
|
@@ -75,6 +100,7 @@ module Mizuno
|
|
75
100
|
# Fire up Mizuno as if it was called from Rackup.
|
76
101
|
Dir.chdir(options[:root])
|
77
102
|
HttpServer.configure_logging(options)
|
103
|
+
ENV['RACK_ENV'] = options[:env]
|
78
104
|
server = Rack::Server.new
|
79
105
|
server.options = options.merge(:server => 'mizuno',
|
80
106
|
:environment => options[:env])
|
@@ -105,7 +131,7 @@ module Mizuno
|
|
105
131
|
File.open(options[:pidfile], 'w') { |f| f.puts(child.pid) }
|
106
132
|
|
107
133
|
# Wait until the server starts or we time out waiting for it.
|
108
|
-
exit if wait_for_server(options)
|
134
|
+
exit if wait_for_server(options, 60)
|
109
135
|
child.stop
|
110
136
|
die("Failed to start Mizuno.")
|
111
137
|
end
|
data/lib/mizuno/version.rb
CHANGED
data/mizuno.gemspec
CHANGED
@@ -23,9 +23,11 @@ Gem::Specification.new do |spec|
|
|
23
23
|
lib/mizuno/java_logger.rb
|
24
24
|
lib/mizuno/rack/chunked.rb
|
25
25
|
lib/mizuno/rack_servlet.rb
|
26
|
+
lib/mizuno/reloader.rb
|
26
27
|
lib/mizuno/runner.rb
|
27
28
|
lib/mizuno/version.rb
|
28
29
|
lib/mizuno.rb
|
30
|
+
lib/rack/handler/mizuno.rb
|
29
31
|
bin/mizuno)
|
30
32
|
jars = Dir.entries("lib/java").grep(/\.jar$/)
|
31
33
|
spec.files.concat(jars.map { |j| "lib/java/#{j}" })
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: mizuno
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.6.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Don Werve
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-04-09 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rack
|
@@ -120,19 +120,21 @@ files:
|
|
120
120
|
- lib/mizuno/java_logger.rb
|
121
121
|
- lib/mizuno/rack/chunked.rb
|
122
122
|
- lib/mizuno/rack_servlet.rb
|
123
|
+
- lib/mizuno/reloader.rb
|
123
124
|
- lib/mizuno/runner.rb
|
124
125
|
- lib/mizuno/version.rb
|
125
126
|
- lib/mizuno.rb
|
127
|
+
- lib/rack/handler/mizuno.rb
|
126
128
|
- bin/mizuno
|
127
|
-
- lib/java/jetty-continuation-8.
|
128
|
-
- lib/java/jetty-http-8.
|
129
|
-
- lib/java/jetty-io-8.
|
130
|
-
- lib/java/jetty-jmx-8.
|
131
|
-
- lib/java/jetty-security-8.
|
132
|
-
- lib/java/jetty-server-8.
|
133
|
-
- lib/java/jetty-servlet-8.
|
134
|
-
- lib/java/jetty-servlets-8.
|
135
|
-
- lib/java/jetty-util-8.
|
129
|
+
- lib/java/jetty-continuation-8.1.2.v20120308.jar
|
130
|
+
- lib/java/jetty-http-8.1.2.v20120308.jar
|
131
|
+
- lib/java/jetty-io-8.1.2.v20120308.jar
|
132
|
+
- lib/java/jetty-jmx-8.1.2.v20120308.jar
|
133
|
+
- lib/java/jetty-security-8.1.2.v20120308.jar
|
134
|
+
- lib/java/jetty-server-8.1.2.v20120308.jar
|
135
|
+
- lib/java/jetty-servlet-8.1.2.v20120308.jar
|
136
|
+
- lib/java/jetty-servlets-8.1.2.v20120308.jar
|
137
|
+
- lib/java/jetty-util-8.1.2.v20120308.jar
|
136
138
|
- lib/java/log4j-1.2.16.jar
|
137
139
|
- lib/java/rewindable-input-stream.jar
|
138
140
|
- lib/java/servlet-api-3.0.jar
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|