Merge pull request #1627 from rkmathi/rkmathi/drop-thin-support

Drop thin support
This commit is contained in:
namusyaka 2020-08-08 19:31:02 +09:00 committed by GitHub
commit f57acefdda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 153 additions and 89 deletions

View File

@ -41,7 +41,8 @@ if RUBY_ENGINE == "ruby"
gem 'puma'
gem 'yajl-ruby'
gem 'nokogiri'
gem 'puma'
gem 'rainbows'
gem 'eventmachine'
gem 'slim', '~> 2.0'
gem 'coffee-script', '>= 2.0'
gem 'rdoc'

View File

@ -34,7 +34,7 @@ The code you changed will not take effect until you restart the server.
Please restart the server every time you change or use
[sinatra/reloader](http://www.sinatrarb.com/contrib/reloader).
It is recommended to also run `gem install thin`, which Sinatra will
It is recommended to also run `gem install puma`, which Sinatra will
pick up if available.
## Table of Contents
@ -1685,36 +1685,53 @@ to `stream` finishes executing. Streaming does not work at all with Shotgun.
If the optional parameter is set to `keep_open`, it will not call `close` on
the stream object, allowing you to close it at any later point in the
execution flow. This only works on evented servers, like Thin and Rainbows.
execution flow. This only works on evented servers, like Rainbows.
Other servers will still close the stream:
```ruby
# long polling
# config.ru
require 'sinatra/base'
set :server, :thin
connections = []
class App < Sinatra::Base
connections = []
get '/subscribe' do
# register a client's interest in server events
stream(:keep_open) do |out|
connections << out
# purge dead connections
connections.reject!(&:closed?)
get '/subscribe' do
# register a client's interest in server events
stream(:keep_open) do |out|
connections << out
# purge dead connections
connections.reject!(&:closed?)
end
end
post '/:message' do
connections.each do |out|
# notify client that a new message has arrived
out << params['message'] << "\n"
# indicate client to connect again
out.close
end
# acknowledge
"message received"
end
end
post '/:message' do
connections.each do |out|
# notify client that a new message has arrived
out << params['message'] << "\n"
run App
```
# indicate client to connect again
out.close
end
# acknowledge
"message received"
```ruby
# rainbows.conf
Rainbows! do
use :EventMachine
end
````
Run:
```shell
rainbows -c rainbows.conf
```
It's also possible for the client to close the connection when trying to
@ -2377,7 +2394,7 @@ set :protection, :session => true
If you are using a WEBrick web server, presumably for your development
environment, you can pass a hash of options to <tt>server_settings</tt>,
such as <tt>SSLEnable</tt> or <tt>SSLVerifyClient</tt>. However, web
servers such as Puma and Thin do not support this, so you can set
servers such as Puma do not support this, so you can set
<tt>server_settings</tt> by defining it as a method when you call
<tt>configure</tt>.
</dd>
@ -2428,7 +2445,7 @@ set :protection, :session => true
<dt>threaded</dt>
<dd>
If set to <tt>true</tt>, will tell Thin to use
If set to <tt>true</tt>, will tell server to use
<tt>EventMachine.defer</tt> for processing the request.
</dd>
@ -3017,7 +3034,7 @@ Options are:
-p # set the port (default is 4567)
-o # set the host (default is 0.0.0.0)
-e # set the environment (default is development)
-s # specify rack server/handler (default is thin)
-s # specify rack server/handler (default is puma)
-q # turn on quiet mode for server (default is off)
-x # turn on the mutex lock (default is off)
```
@ -3029,15 +3046,15 @@ _Paraphrasing from
by Konstantin_
Sinatra doesn't impose any concurrency model, but leaves that to the
underlying Rack handler (server) like Thin, Puma or WEBrick. Sinatra
underlying Rack handler (server) like Puma or WEBrick. Sinatra
itself is thread-safe, so there won't be any problem if the Rack handler
uses a threaded model of concurrency. This would mean that when starting
the server, you'd have to specify the correct invocation method for the
specific Rack handler. The following example is a demonstration of how
to start a multi-threaded Thin server:
to start a multi-threaded Rainbows server:
```ruby
# app.rb
# config.ru
require 'sinatra/base'
@ -3047,14 +3064,22 @@ class App < Sinatra::Base
end
end
App.run!
run App
```
```ruby
# rainbows.conf
# Rainbows configurator is based on Unicorn.
Rainbows! do
use :ThreadSpawn
end
```
To start the server, the command would be:
```shell
thin --threaded start
rainbows -c rainbows.conf
```
## Requirement

View File

@ -1,7 +1,7 @@
#!/usr/bin/env ruby -I ../lib -I lib
# coding: utf-8
require 'sinatra'
set :server, 'thin'
set :server, 'puma'
connections = []
get '/' do

3
examples/rainbows.conf Normal file
View File

@ -0,0 +1,3 @@
Rainbows! do
use :EventMachine
end

View File

@ -2,10 +2,10 @@
#
# run *one* of these:
#
# rackup -s mongrel stream.ru # gem install mongrel
# thin -R stream.ru start # gem install thin
# unicorn stream.ru # gem install unicorn
# puma stream.ru # gem install puma
# rackup -s mongrel stream.ru # gem install mongrel
# unicorn stream.ru # gem install unicorn
# puma stream.ru # gem install puma
# rainbows -c rainbows.conf stream.ru # gem install rainbows eventmachine
require 'sinatra/base'

View File

@ -206,7 +206,7 @@ module Sinatra
end
end
# Some Rack handlers (Thin, Rainbows!) implement an extended body object protocol, however,
# Some Rack handlers (Rainbows!) implement an extended body object protocol, however,
# some middleware (namely Rack::Lint) will break it by not mirroring the methods in question.
# This middleware will detect an extended body object and will make sure it reaches the
# handler directly. We do this here, so our middleware and middleware set up by the app will
@ -473,7 +473,7 @@ module Sinatra
#
# The close parameter specifies whether Stream#close should be called
# after the block has been executed. This is only relevant for evented
# servers like Thin or Rainbows.
# servers like Rainbows.
def stream(keep_open = false)
scheduler = env['async.callback'] ? EventMachine : Stream
current = @params.dup
@ -1475,8 +1475,7 @@ module Sinatra
# Stop the self-hosted server if running.
def quit!
return unless running?
# Use Thin's hard #stop! if available, otherwise just #stop.
running_server.respond_to?(:stop!) ? running_server.stop! : running_server.stop
running_server.stop
$stderr.puts "== Sinatra has ended his set (crowd applauds)" unless suppress_messages?
set :running_server, nil
set :handler_name, nil
@ -1485,7 +1484,7 @@ module Sinatra
alias_method :stop!, :quit!
# Run the Sinatra app as a self-hosted server using
# Thin, Puma, Mongrel, or WEBrick (in that order). If given a block, will call
# Puma, Mongrel, or WEBrick (in that order). If given a block, will call
# with the constructed handler once we have taken the stage.
def run!(options = {}, &block)
return if running?
@ -1849,7 +1848,6 @@ module Sinatra
server.unshift 'reel'
server.unshift 'puma'
server.unshift 'mongrel' if ruby_engine.nil?
server.unshift 'thin' if ruby_engine != 'jruby'
server.unshift 'trinidad' if ruby_engine == 'jruby'
end

View File

@ -5,7 +5,7 @@ module Sinatra
require 'optparse'
parser = OptionParser.new { |op|
op.on('-p port', 'set the port (default is 4567)') { |val| ParamsConfig[:port] = Integer(val) }
op.on('-s server', 'specify rack server/handler (default is thin)') { |val| ParamsConfig[:server] = val }
op.on('-s server', 'specify rack server/handler (default is puma)') { |val| ParamsConfig[:server] = val }
op.on('-q', 'turn on quiet mode (default is off)') { ParamsConfig[:quiet] = true }
op.on('-x', 'turn on the mutex lock (default is off)') { ParamsConfig[:lock] = true }
op.on('-e env', 'set the environment (default is development)') do |val|

View File

@ -1,6 +1,8 @@
$stderr.puts "loading"
require 'sinatra'
require_relative 'rainbows' if RUBY_ENGINE == 'ruby'
configure do
set :foo, :bar
end

View File

@ -0,0 +1,3 @@
Rainbows! do
use :EventMachine
end

View File

@ -0,0 +1,20 @@
require 'rainbows'
module Rack
module Handler
class Rainbows
def self.run(app, **options)
rainbows_options = {
listeners: ["#{options[:Host]}:#{options[:Port]}"],
worker_processes: 1,
timeout: 30,
config_file: ::File.expand_path('../rainbows.conf', __FILE__),
}
::Rainbows::HttpServer.new(app, rainbows_options).start.join
end
end
register "rainbows", "Rack::Handler::Rainbows"
end
end

View File

@ -0,0 +1,14 @@
require File.expand_path('../integration_helper', __FILE__)
module IntegrationAsyncHelper
def it(message, &block)
base_port = 5100 + Process.pid % 100
%w(rainbows).each_with_index do |server_name, index|
server = IntegrationHelper::BaseServer.new(server_name, base_port + index)
next unless server.installed?
super("with #{server.name}: #{message}") { server.run_test(self, &block) }
end
end
end

View File

@ -0,0 +1,40 @@
require File.expand_path('../helper', __FILE__)
require File.expand_path('../integration_async_helper', __FILE__)
# These tests are like integration_test, but they test asynchronous streaming.
class IntegrationAsyncTest < Minitest::Test
extend IntegrationAsyncHelper
attr_accessor :server
it 'streams async' do
Timeout.timeout(3) do
chunks = []
server.get_stream '/async' do |chunk|
next if chunk.empty?
chunks << chunk
case chunk
when "hi!" then server.get "/send?msg=hello"
when "hello" then server.get "/send?close=1"
end
end
assert_equal ['hi!', 'hello'], chunks
end
end
it 'streams async from subclass' do
Timeout.timeout(3) do
chunks = []
server.get_stream '/subclass/async' do |chunk|
next if chunk.empty?
chunks << chunk
case chunk
when "hi!" then server.get "/subclass/send?msg=hello"
when "hello" then server.get "/subclass/send?close=1"
end
end
assert_equal ['hi!', 'hello'], chunks
end
end
end

View File

@ -61,7 +61,7 @@ module IntegrationHelper
file, dir = RbConfig::CONFIG.values_at('ruby_install_name', 'bindir')
cmd << File.expand_path(file, dir).inspect
end
cmd << "-w" unless thin? || net_http_server?
cmd << "-w" unless net_http_server?
cmd << "-I" << File.expand_path('../../lib', __FILE__).inspect
cmd << app_file.inspect << '-s' << server << '-o' << '127.0.0.1' << '-p' << port
cmd << "-e" << environment.to_s << '2>&1'
@ -73,8 +73,8 @@ module IntegrationHelper
name.to_s == "webrick"
end
def thin?
name.to_s == "thin"
def rainbows?
name.to_s == "rainbows"
end
def puma?

View File

@ -13,7 +13,7 @@ class IntegrationTest < Minitest::Test
it('only extends main') { assert_equal "true", server.get("/mainonly") }
it 'logs once in development mode' do
next if server.puma? or RUBY_ENGINE == 'jruby'
next if server.puma? or server.rainbows? or RUBY_ENGINE == 'jruby'
random = "%064x" % Kernel.rand(2**256-1)
server.get "/ping?x=#{random}"
count = server.log.scan("GET /ping?x=#{random}").count
@ -39,42 +39,6 @@ class IntegrationTest < Minitest::Test
assert times[2] - times[1] > 1
end
it 'streams async' do
next unless server.thin?
Timeout.timeout(3) do
chunks = []
server.get_stream '/async' do |chunk|
next if chunk.empty?
chunks << chunk
case chunk
when "hi!" then server.get "/send?msg=hello"
when "hello" then server.get "/send?close=1"
end
end
assert_equal ['hi!', 'hello'], chunks
end
end
it 'streams async from subclass' do
next unless server.thin?
Timeout.timeout(3) do
chunks = []
server.get_stream '/subclass/async' do |chunk|
next if chunk.empty?
chunks << chunk
case chunk
when "hi!" then server.get "/subclass/send?msg=hello"
when "hello" then server.get "/subclass/send?close=1"
end
end
assert_equal ['hi!', 'hello'], chunks
end
end
it 'starts the correct server' do
exp = %r{
==\sSinatra\s\(v#{Sinatra::VERSION}\)\s
@ -83,7 +47,7 @@ class IntegrationTest < Minitest::Test
}ix
# because Net HTTP Server logs to $stderr by default
assert_match exp, server.log unless server.net_http_server? || server.reel?
assert_match exp, server.log unless server.net_http_server? || server.reel? || server.rainbows?
end
it 'does not generate warnings' do

View File

@ -488,12 +488,6 @@ class SettingsTest < Minitest::Test
assert @base.server.include?('puma')
assert @application.server.include?('puma')
end
it 'includes thin' do
next if RUBY_ENGINE == 'jruby'
assert @base.server.include?('thin')
assert @application.server.include?('thin')
end
end
describe 'app_file' do