|
@@ -3,22 +3,19 @@ SEQUEL_NO_ASSOCIATIONS = true
|
|
|
|
|
|
Bundler.require :default
|
|
|
|
|
|
-# Configure Slim templating engine
|
|
|
-Slim::Engine.set_options \
|
|
|
- :format => :html,
|
|
|
- :sort_attrs => false
|
|
|
-
|
|
|
-# Configure Sequel ORM
|
|
|
-DB = Sequel.connect \
|
|
|
- :adapter => RUBY_PLATFORM == 'java' ? 'jdbc:mysql' : 'mysql2',
|
|
|
- :host => ENV['DB_HOST'],
|
|
|
- :database => 'hello_world',
|
|
|
- :user => 'benchmarkdbuser',
|
|
|
- :password => 'benchmarkdbpass',
|
|
|
- :max_connections => 32, # == max worker threads per process
|
|
|
+# Configure Sequel ORM (Sequel::DATABASES)
|
|
|
+Sequel.connect \
|
|
|
+ '%<adapter>s://%<host>s/%<database>s?user=%<user>s&password=%<password>s' % {
|
|
|
+ :adapter => RUBY_PLATFORM == 'java' ? 'jdbc:mysql' : 'mysql2',
|
|
|
+ :host => ENV['DBHOST'],
|
|
|
+ :database => 'hello_world',
|
|
|
+ :user => 'benchmarkdbuser',
|
|
|
+ :password => 'benchmarkdbpass'
|
|
|
+ },
|
|
|
+ :max_connections => (ENV['MAX_THREADS'] || 4).to_i,
|
|
|
:pool_timeout => 5
|
|
|
|
|
|
-# Allow #to_json on models and arrays of models
|
|
|
+# Allow #to_json on models and datasets
|
|
|
Sequel::Model.plugin :json_serializer
|
|
|
|
|
|
class World < Sequel::Model(:World); end
|
|
@@ -28,17 +25,23 @@ class Fortune < Sequel::Model(:Fortune)
|
|
|
unrestrict_primary_key
|
|
|
end
|
|
|
|
|
|
+# Configure Slim templating engine
|
|
|
+Slim::Engine.set_options \
|
|
|
+ :format => :html,
|
|
|
+ :sort_attrs => false
|
|
|
+
|
|
|
# Our Rack application to be executed by rackup
|
|
|
class HelloWorld < Sinatra::Base
|
|
|
configure do
|
|
|
+ # Static file serving is ostensibly disabled in modular mode but Sinatra
|
|
|
+ # still calls an expensive Proc on every request...
|
|
|
+ disable :static
|
|
|
+
|
|
|
+ # XSS, CSRF, IP spoofing, etc. protection are not explicitly required
|
|
|
disable :protection
|
|
|
|
|
|
# Don't add ;charset= to any content types per the benchmark requirements
|
|
|
set :add_charset, []
|
|
|
-
|
|
|
- # Specify the encoder - otherwise, sinatra/json inefficiently
|
|
|
- # attempts to load one of several on each request
|
|
|
- set :json_encoder, :to_json
|
|
|
end
|
|
|
|
|
|
helpers do
|
|
@@ -55,29 +58,30 @@ class HelloWorld < Sinatra::Base
|
|
|
|
|
|
after do
|
|
|
# Add mandatory HTTP headers to every response
|
|
|
- response['Server'] = 'Puma'
|
|
|
- response['Date'] = Time.now.to_s
|
|
|
+ response['Server'] ||= 'Puma'
|
|
|
+ response['Date'] ||= Time.now.to_s
|
|
|
end
|
|
|
|
|
|
- get '/json' do
|
|
|
- json :message => 'Hello, World!'
|
|
|
+ get '/json', :provides => :json do
|
|
|
+ JSON.fast_generate :message => 'Hello, World!'
|
|
|
end
|
|
|
|
|
|
- get '/plaintext' do
|
|
|
- content_type 'text/plain'
|
|
|
+ get '/plaintext', :provides => :text do
|
|
|
'Hello, World!'
|
|
|
end
|
|
|
|
|
|
- get '/db' do
|
|
|
- json World[rand1]
|
|
|
+ get '/db', :provides => :json do
|
|
|
+ World[rand1].to_json
|
|
|
end
|
|
|
|
|
|
- get '/queries' do
|
|
|
+ get '/queries', :provides => :json do
|
|
|
queries = (params[:queries] || 1).to_i
|
|
|
queries = 1 if queries < 1
|
|
|
queries = 500 if queries > 500
|
|
|
|
|
|
- json World.where(:id => randn(queries))
|
|
|
+ World
|
|
|
+ .where(:id => randn(queries))
|
|
|
+ .to_json
|
|
|
end
|
|
|
|
|
|
get '/fortunes' do
|
|
@@ -91,26 +95,31 @@ class HelloWorld < Sinatra::Base
|
|
|
slim :fortunes
|
|
|
end
|
|
|
|
|
|
- get '/updates' do
|
|
|
+ get '/updates', :provides => :json do
|
|
|
queries = (params[:queries] || 1).to_i
|
|
|
queries = 1 if queries < 1
|
|
|
queries = 500 if queries > 500
|
|
|
|
|
|
# Prepare our updates in advance so transaction retries are idempotent
|
|
|
- updates = randn(queries).sort!.map! { |id| [id, rand1] }
|
|
|
+ updates = randn(queries).map! { |id| [id, rand1] }.to_h
|
|
|
|
|
|
worlds = nil
|
|
|
|
|
|
World.db.transaction do
|
|
|
worlds = World
|
|
|
- .where(:id => updates.transpose.first)
|
|
|
+ .where(:id => updates.keys.sort!)
|
|
|
.for_update
|
|
|
+ .all
|
|
|
+
|
|
|
+ worlds
|
|
|
+ .each { |w| w.randomNumber = updates[w.id] }
|
|
|
|
|
|
World.dataset
|
|
|
.on_duplicate_key_update(:randomNumber)
|
|
|
- .import([:id, :randomNumber], updates)
|
|
|
+ .import([:id, :randomNumber], worlds.map { |w| [w.id, w.randomNumber] })
|
|
|
end
|
|
|
|
|
|
- json worlds
|
|
|
+ # The models are dirty but OK to return if the batch update was successful
|
|
|
+ World.to_json :array => worlds
|
|
|
end
|
|
|
end
|