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

Commit 1a6e954

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 1a6e954

6 files changed

Lines changed: 130 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: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# frozen_string_literal: true
2+
3+
require 'connection_pool'
4+
5+
def connect
6+
if defined?(Puma) || defined?(Itsi)
7+
max_connections = ENV.fetch('MAX_THREADS')
8+
elsif defined?(Iodine)
9+
max_connections = ENV.fetch('THREADS')
10+
else
11+
max_connections = 512
12+
end
13+
ConnectionPool.new(size: max_connections, timeout: 5) do
14+
url = 'postgresql://tfb-database/hello_world?user=benchmarkdbuser&password=benchmarkdbpass'
15+
if RUBY_PLATFORM == 'java'
16+
JDBCConnection.new("jdbc:" + url)
17+
else
18+
PGConnection.new(url)
19+
end
20+
end
21+
end
22+
23+
class PGConnection
24+
attr_reader :connection
25+
26+
def initialize(connection_string)
27+
require 'pg'
28+
@connection = PG::Connection.new(connection_string)
29+
@connection.set_error_verbosity(PG::PQERRORS_VERBOSE)
30+
@connection.prepare('select_world', 'SELECT id, randomNumber FROM world WHERE id = $1')
31+
end
32+
33+
def select_world(id)
34+
@connection.exec_prepared('select_world', [id]).first
35+
end
36+
37+
def select_fortunes
38+
@connection.exec('SELECT id, message FROM fortune')
39+
end
40+
41+
def exec(query)
42+
@connection.exec(query)
43+
end
44+
end
45+
46+
class JDBCConnection < PGConnection
47+
def initialize(connection_string)
48+
require 'sequel'
49+
@connection = Sequel.connect(connection_string)
50+
@world_select = @connection['SELECT id, randomNumber FROM World WHERE id = ?', :$id].prepare(:select, :select_by_id)
51+
@fortune_select = @connection['SELECT id, message FROM Fortune'].prepare(:select, :select_all)
52+
end
53+
54+
def select_world(id)
55+
@world_select.call(id: id).first.transform_keys(&:to_s)
56+
end
57+
58+
def select_fortunes
59+
@fortune_select.call.map { it.transform_keys(&:to_s) }
60+
end
61+
62+
def exec(query)
63+
@connection[query].update
64+
end
65+
end

frameworks/Ruby/rack/hello_world.rb

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

33
# Our Rack application to be executed by rackup
44

5-
require_relative 'pg_db'
5+
require_relative 'db'
66
require_relative 'config/auto_tune'
77
require 'rack'
88
require 'json'
9+
require 'time'
910
require 'erb'
1011

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
12+
$db = connect
1613

1714
class HelloWorld
1815
QUERY_RANGE = (1..10_000).freeze # range of IDs in the Fortune DB
@@ -42,30 +39,6 @@ class HelloWorld
4239
</body>
4340
</html>'
4441

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-
6942
def call(env)
7043
case env['PATH_INFO']
7144
when '/json'
@@ -74,20 +47,19 @@ def call(env)
7447
{ message: 'Hello, World!' }.to_json
7548
when '/db'
7649
# Test type 2: Single database query
77-
respond JSON_TYPE, @db.select_random_world.to_json
50+
id = random_id
51+
respond JSON_TYPE, $db.with{ _1.select_world(id) }.to_json
7852
when '/queries'
7953
# 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
54+
queries = bounded_queries(env)
55+
respond JSON_TYPE, select_worlds(queries).to_json
8356
when '/fortunes'
8457
# Test type 4: Fortunes
8558
respond HTML_TYPE, fortunes
8659
when '/updates'
8760
# 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
61+
queries = bounded_queries(env)
62+
respond JSON_TYPE, update_worlds(queries).to_json
9163
when '/plaintext'
9264
# Test type 6: Plaintext
9365
respond PLAINTEXT_TYPE, 'Hello, World!'
@@ -120,4 +92,51 @@ def headers(content_type)
12092
}
12193
end
12294
end
95+
96+
def fortunes
97+
fortunes = $db.with(&:select_fortunes).map(&:to_h)
98+
fortunes << { 'id' => 0, 'message' => 'Additional fortune added at request time.' }
99+
fortunes.sort_by! { |item| item['message'] }
100+
buffer = String.new
101+
buffer << TEMPLATE_PREFIX
102+
103+
fortunes.each do |item|
104+
buffer << "<tr><td>#{item['id']}</td><td>#{ERB::Escape.html_escape(item['message'])}</td></tr>"
105+
end
106+
buffer << TEMPLATE_POSTFIX
107+
end
108+
109+
def update_worlds(count)
110+
results = select_worlds(count)
111+
ids = []
112+
sql = String.new("UPDATE world SET randomnumber = CASE id ")
113+
results.each do |r|
114+
r['randomnumber'] = random_id
115+
ids << r['id']
116+
sql << "when #{r['id']} then #{r['randomnumber']} "
117+
end
118+
sql << "ELSE randomnumber END WHERE id IN ( #{ids.join(',')})"
119+
$db.with{ _1.exec(sql) }
120+
results
121+
end
122+
123+
def select_worlds(count)
124+
ids = ALL_IDS.sample(count)
125+
$db.with do |conn|
126+
ids.map do |id|
127+
conn.select_world(id)
128+
end
129+
end
130+
end
131+
132+
def random_id
133+
Random.rand(QUERY_RANGE)
134+
end
135+
136+
def bounded_queries(env)
137+
params = Rack::Utils.parse_query(env['QUERY_STRING'])
138+
139+
queries = params['queries'].to_i
140+
queries.clamp(MIN_QUERIES, MAX_QUERIES)
141+
end
123142
end

frameworks/Ruby/rack/pg_db.rb

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

0 commit comments

Comments
 (0)