Skip to content
This repository was archived by the owner on Mar 24, 2026. It is now read-only.

Commit baefce5

Browse files
committed
[ruby/rack] Don't use Sequel ORM
Just use the raw `pg` adapter. For JRuby fallback to Sequel as it's a lot easier.
1 parent 03cdefe commit baefce5

7 files changed

Lines changed: 142 additions & 140 deletions

File tree

frameworks/Ruby/rack/Gemfile

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,18 @@ puts "Platform: #{Gem::Platform.local}"
77

88
gem 'rack', '~> 3.0'
99
gem 'connection_pool'
10-
gem 'jdbc-postgres', '~> 42.2', platforms: :jruby, require: 'jdbc/postgres'
1110
gem 'json', '~> 2.10'
12-
gem 'pg', '~> 1.5', platforms: %i[ruby windows]
13-
gem 'sequel'
14-
gem 'sequel_pg', platforms: %i[ruby windows], require: 'sequel'
1511
gem 'tzinfo-data', '1.2023.3'
1612

13+
platforms :ruby, :windows do
14+
gem 'pg', '~> 1.5', platforms: %i[ruby windows]
15+
end
16+
17+
platforms :jruby do
18+
gem 'jdbc-postgres', '~> 42.2', require: 'jdbc/postgres'
19+
gem 'sequel'
20+
end
21+
1722
group :falcon, optional: true do
1823
gem 'falcon', '~> 0.52', platforms: %i[ruby windows]
1924
end
Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
# frozen_string_literal: true
22

33
require 'etc'
4-
require 'sequel'
54

65
worker_processes (Etc.nprocessors * 1.5).to_i
76

8-
before_fork do |_server|
9-
Sequel::DATABASES.each(&:disconnect)
10-
end
11-
127
listen "/tmp/.sock", :backlog => 4096

frameworks/Ruby/rack/config/puma.rb

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
if ENV.fetch('WEB_CONCURRENCY').to_i > 1
2-
before_fork do
3-
Sequel::DATABASES.each(&:disconnect)
4-
end
52
else
63
workers ENV.fetch('WEB_CONCURRENCY')
74
require 'concurrent/utility/processor_counter'

frameworks/Ruby/rack/db.rb

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# frozen_string_literal: true
2+
3+
require 'pg'
4+
require 'connection_pool'
5+
6+
def connect(url)
7+
if defined?(Puma) || defined?(Itsi)
8+
max_connections = ENV.fetch('MAX_THREADS')
9+
elsif defined?(Iodine)
10+
max_connections = ENV.fetch('THREADS')
11+
else
12+
max_connections = 512
13+
end
14+
ConnectionPool.new(size: max_connections, timeout: 5) do
15+
PGConnection.new(url)
16+
end
17+
end
18+
19+
class PGConnection
20+
attr_reader :connection
21+
22+
def initialize(connection_string)
23+
@connection = PG::Connection.new(connection_string)
24+
@connection.set_error_verbosity(PG::PQERRORS_VERBOSE)
25+
@connection.prepare('select_world', 'SELECT id, randomNumber FROM world WHERE id = $1')
26+
end
27+
28+
def select_world(id)
29+
@connection.exec_prepared('select_world', [id]).first
30+
end
31+
32+
def select_fortunes
33+
@connection.exec('SELECT id, message FROM fortune')
34+
end
35+
36+
def exec(query)
37+
@connection.exec(query)
38+
end
39+
end

frameworks/Ruby/rack/db_jruby.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# frozen_string_literal: true
2+
3+
require 'sequel'
4+
5+
def connect(url)
6+
JDBCConnection.new("jdbc:" + url, max_connections: 512)
7+
end
8+
9+
class JDBCConnection
10+
attr_reader :connection
11+
12+
def initialize(connection_string, max_connections:)
13+
@connection = Sequel.connect(connection_string, max_connections: max_connections)
14+
@world_select = @connection['SELECT id, randomNumber FROM World WHERE id = ?', :$id].prepare(:select, :select_by_id)
15+
@fortune_select = @connection['SELECT id, message FROM Fortune'].prepare(:select, :select_all)
16+
end
17+
18+
def select_world(id)
19+
@world_select.call(id: id).first.transform_keys(&:to_s)
20+
end
21+
22+
def select_fortunes
23+
@fortune_select.call.map { it.transform_keys(&:to_s) }
24+
end
25+
26+
def exec(query)
27+
@connection[query].update
28+
end
29+
30+
def with
31+
yield(self)
32+
end
33+
end

frameworks/Ruby/rack/hello_world.rb

Lines changed: 61 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@
22

33
# Our Rack application to be executed by rackup
44

5-
require_relative 'pg_db'
5+
if RUBY_PLATFORM == 'java'
6+
require_relative 'db_jruby'
7+
else
8+
require_relative 'db'
9+
end
610
require_relative 'config/auto_tune'
711
require 'rack'
812
require 'json'
13+
require 'time'
914
require 'erb'
1015

11-
if RUBY_PLATFORM == 'java'
12-
DEFAULT_DATABASE_URL = 'jdbc:postgresql://tfb-database/hello_world?user=benchmarkdbuser&password=benchmarkdbpass'
13-
else
14-
DEFAULT_DATABASE_URL = 'postgresql://tfb-database/hello_world?user=benchmarkdbuser&password=benchmarkdbpass'
15-
end
16+
DATABASE_URL = 'postgresql://tfb-database/hello_world?user=benchmarkdbuser&password=benchmarkdbpass'
17+
$db = connect(DATABASE_URL)
1618

1719
class HelloWorld
1820
QUERY_RANGE = (1..10_000).freeze # range of IDs in the Fortune DB
@@ -42,30 +44,6 @@ class HelloWorld
4244
</body>
4345
</html>'
4446

45-
def initialize
46-
if defined?(Puma) || defined?(Itsi)
47-
max_connections = ENV.fetch('MAX_THREADS')
48-
elsif defined?(Iodine)
49-
max_connections = ENV.fetch('THREADS')
50-
else
51-
max_connections = 512
52-
end
53-
@db = PgDb.new(DEFAULT_DATABASE_URL, max_connections)
54-
end
55-
56-
def fortunes
57-
fortunes = @db.select_fortunes
58-
fortunes << { id: 0, message: 'Additional fortune added at request time.' }
59-
fortunes.sort_by! { |item| item[:message] }
60-
buffer = String.new
61-
buffer << TEMPLATE_PREFIX
62-
63-
fortunes.each do |item|
64-
buffer << "<tr><td>#{item[:id]}</td><td>#{ERB::Escape.html_escape(item[:message])}</td></tr>"
65-
end
66-
buffer << TEMPLATE_POSTFIX
67-
end
68-
6947
def call(env)
7048
case env['PATH_INFO']
7149
when '/json'
@@ -74,20 +52,19 @@ def call(env)
7452
{ message: 'Hello, World!' }.to_json
7553
when '/db'
7654
# Test type 2: Single database query
77-
respond JSON_TYPE, @db.select_random_world.to_json
55+
id = random_id
56+
respond JSON_TYPE, $db.with{ _1.select_world(id) }.to_json
7857
when '/queries'
7958
# Test type 3: Multiple database queries
80-
params = Rack::Utils.parse_query(env['QUERY_STRING'])
81-
queries = params['queries']
82-
respond JSON_TYPE, @db.select_worlds(queries).to_json
59+
queries = bounded_queries(env)
60+
respond JSON_TYPE, select_worlds(queries).to_json
8361
when '/fortunes'
8462
# Test type 4: Fortunes
8563
respond HTML_TYPE, fortunes
8664
when '/updates'
8765
# Test type 5: Database updates
88-
params = Rack::Utils.parse_query(env['QUERY_STRING'])
89-
queries = params['queries']
90-
respond JSON_TYPE, @db.update_worlds(queries).to_json
66+
queries = bounded_queries(env)
67+
respond JSON_TYPE, update_worlds(queries).to_json
9168
when '/plaintext'
9269
# Test type 6: Plaintext
9370
respond PLAINTEXT_TYPE, 'Hello, World!'
@@ -120,4 +97,51 @@ def headers(content_type)
12097
}
12198
end
12299
end
100+
101+
def fortunes
102+
fortunes = $db.with(&:select_fortunes).map(&:to_h)
103+
fortunes << { 'id' => 0, 'message' => 'Additional fortune added at request time.' }
104+
fortunes.sort_by! { |item| item['message'] }
105+
buffer = String.new
106+
buffer << TEMPLATE_PREFIX
107+
108+
fortunes.each do |item|
109+
buffer << "<tr><td>#{item['id']}</td><td>#{ERB::Escape.html_escape(item['message'])}</td></tr>"
110+
end
111+
buffer << TEMPLATE_POSTFIX
112+
end
113+
114+
def update_worlds(count)
115+
results = select_worlds(count)
116+
ids = []
117+
sql = String.new("UPDATE world SET randomnumber = CASE id ")
118+
results.each do |r|
119+
r['randomnumber'] = random_id
120+
ids << r['id']
121+
sql << "when #{r['id']} then #{r['randomnumber']} "
122+
end
123+
sql << "ELSE randomnumber END WHERE id IN ( #{ids.join(',')})"
124+
$db.with{ _1.exec(sql) }
125+
results
126+
end
127+
128+
def select_worlds(count)
129+
ids = ALL_IDS.sample(count)
130+
$db.with do |conn|
131+
ids.map do |id|
132+
conn.select_world(id)
133+
end
134+
end
135+
end
136+
137+
def random_id
138+
Random.rand(QUERY_RANGE)
139+
end
140+
141+
def bounded_queries(env)
142+
params = Rack::Utils.parse_query(env['QUERY_STRING'])
143+
144+
queries = params['queries'].to_i
145+
queries.clamp(MIN_QUERIES, MAX_QUERIES)
146+
end
123147
end

frameworks/Ruby/rack/pg_db.rb

Lines changed: 0 additions & 91 deletions
This file was deleted.

0 commit comments

Comments
 (0)