Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions frameworks/rage/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ source 'https://rubygems.org'

gem 'rage-rb', '~> 1.22'
gem 'pg', '~> 1.5'
gem 'redis'
gem 'concurrent-ruby'
gem 'connection_pool'
7 changes: 7 additions & 0 deletions frameworks/rage/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ GEM
erb
psych (>= 4.0.0)
tsort
redis (5.4.1)
redis-client (>= 0.22.0)
redis-client (0.29.0)
connection_pool
reline (0.6.3)
io-console (~> 0.5)
stringio (3.2.0)
Expand All @@ -55,6 +59,7 @@ DEPENDENCIES
connection_pool
pg (~> 1.5)
rage-rb (~> 1.22)
redis

CHECKSUMS
concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab
Expand All @@ -76,6 +81,8 @@ CHECKSUMS
rage-rb (1.23.0) sha256=33d2256062a2a10968dc8ba218791ffafe3c8376ddc9f67ee430cfaabb6f5ae2
rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701
rdoc (7.2.0) sha256=8650f76cd4009c3b54955eb5d7e3a075c60a57276766ebf36f9085e8c9f23192
redis (5.4.1) sha256=b5e675b57ad22b15c9bcc765d5ac26f60b675408af916d31527af9bd5a81faae
redis-client (0.29.0) sha256=0c65bf1f8f6dca22063ddb085c0bb2054feef6f03a84869f4161b18a9a15bea3
reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835
stringio (3.2.0) sha256=c37cb2e58b4ffbd33fe5cd948c05934af997b36e0b6ca6fdf43afa234cf222e1
thor (1.5.0) sha256=e3a9e55fe857e44859ce104a84675ab6e8cd59c650a49106a05f55f136425e73
Expand Down
46 changes: 46 additions & 0 deletions frameworks/rage/app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
class ApplicationController < RageController::API

CRUD_COLUMNS = 'id, name, category, price, quantity, active, tags, rating_score, rating_count'
SELECT_QUERY = "SELECT #{CRUD_COLUMNS} FROM items WHERE price BETWEEN $1 AND $2 LIMIT $3"
CRUD_GET_SQL = "SELECT #{CRUD_COLUMNS} FROM items WHERE id = $1 LIMIT 1"
CRUD_LIST_SQL = "SELECT #{CRUD_COLUMNS} FROM items WHERE category = $1 ORDER BY id LIMIT $2 OFFSET $3"
CRUD_UPDATE_SQL = "UPDATE items SET name = $1, price = $2, quantity = $3 WHERE id = $4"
CRUD_UPSERT_SQL = <<~SQL
INSERT INTO items
(#{CRUD_COLUMNS})
VALUES ($1, $2, $3, $4, $5, true, '[\"bench\"]', 0, 0)
ON CONFLICT (id) DO UPDATE SET name = $2, price = $4, quantity = $5
RETURNING id
SQL

private

def self.get_async_db
@async_db ||= begin
return unless ENV['DATABASE_URL']
ConnectionPool.new(size: pool_size, timeout: 5) do
db = PG.connect(ENV['DATABASE_URL'])
db.prepare('select', SELECT_QUERY)
db.prepare('crud_get', CRUD_GET_SQL)
db.prepare('crud_list', CRUD_LIST_SQL)
db.prepare('crud_update', CRUD_UPDATE_SQL)
db.prepare('crud_upsert', CRUD_UPSERT_SQL)
db
end
end
end

def self.redis
@redis ||= begin
return unless ENV['REDIS_URL']
ConnectionPool::Wrapper.new(size: pool_size, timeout: 10) do
Redis.new(url: ENV['REDIS_URL'])
end
end
end

def self.pool_size
processors = Integer(::Concurrent.available_processor_count)
pool_size = (2 * Math.log(256 / processors)).floor
end
end
19 changes: 1 addition & 18 deletions frameworks/rage/app/controllers/benchmark_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def symbolize_keys!
end
end

class BenchmarkController < RageController::API
class BenchmarkController < ApplicationController
DATA_DIR = ENV.fetch('DATA_DIR', '/data')

dataset_path = File.join DATA_DIR, 'dataset.json'
Expand All @@ -24,8 +24,6 @@ def self.dataset_items = @dataset_items

FileUtils.cp_r(File.join(DATA_DIR, 'static'), File.join(Rage.root, 'public', 'static'))

PG_QUERY = 'SELECT id, name, category, price, quantity, active, tags, rating_score, rating_count FROM items WHERE price BETWEEN $1 AND $2 LIMIT $3'

def baseline_one
total = params[:a].to_i + params[:b].to_i
if request.post?
Expand Down Expand Up @@ -94,19 +92,4 @@ def upload
def not_found
head 404
end

private

def self.get_async_db
@async_db ||= begin
return unless ENV['DATABASE_URL']
processors = Integer(::Concurrent.available_processor_count)
pool_size = (2 * Math.log(256 / processors)).floor
ConnectionPool.new(size: pool_size, timeout: 5) do
db = PG.connect(ENV['DATABASE_URL'])
db.prepare('select', PG_QUERY)
db
end
end
end
end
110 changes: 110 additions & 0 deletions frameworks/rage/app/controllers/items_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
class ItemsController < ApplicationController
def index
category = params[:category] || 'electronics'
page = (params[:page] || 1).to_i
limit = (params[:limit] || 10).to_i
offset = (page - 1) * limit

rows = self.class.get_async_db&.with do |connection|
connection.exec_prepared('crud_list', [category, limit, offset])
end || []

items = rows.map do |row|
map_row(row)
end
render json: { items: items, total: items.length, page: page, limit: limit }
end

def show
id = params[:id]
json = self.class.redis&.with do |connection|
connection.get(id.to_s)
end
if json
headers['x-cache'] = ' HIT'
return render json: json
else
headers['x-cache'] = ' MISS'
end

rows = self.class.get_async_db&.with do |connection|
connection.exec_prepared('crud_get', [id])
end || []

if row = rows.first
item = map_row(row)
json = JSON.generate(item)
self.class.redis&.with do |connection|
connection.set(id.to_s, json)
end
render json: item
else
head 404
end
end

def create
id = params[:id]
name = params[:name] || 'New Product'
category = params[:category] || 'electronics'
price = (params[:price] || 0).to_i
quantity = (params[:quantity] || 0).to_i

self.class.get_async_db&.with do |connection|
connection.exec_prepared('crud_upsert', [id, name, category, price, quantity])
end

self.class.redis&.with do |connection|
connection.del(id.to_s)
end

item = {
'id' => id,
'name' => name,
'category' => category,
'price' => price,
'quantity' => quantity
}

render json: item, status: 201
end

def update
id = params[:id]
name = params[:name] || 'New Product'
price = (params[:price] || 0).to_i
quantity = (params[:quantity] || 0).to_i

row = self.class.get_async_db&.with do |connection|
connection.exec_prepared('crud_update', [name, price, quantity, id])
end || []

self.class.redis&.with do |connection|
connection.del(id.to_s)
end

item = {
'id' => id,
'name' => name,
'price' => price,
'quantity' => quantity
}
render json: item
end

private

def map_row(row)
mapped_row = {
id: row['id'],
name: row['name'],
category: row['category'],
price: row['price'],
quantity: row['quantity'],
active: row['active'] == 1,
}
mapped_row[:tags] = JSON.parse(row['tags']) if row['tags']
mapped_row[:rating] = { score: row['rating_score'], count: row['rating_count'] } if row['rating_score'] && row['rating_count']
mapped_row
end
end
16 changes: 10 additions & 6 deletions frameworks/rage/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@
'content-type' => 'text/plain'
}, ['ok']]
end
get '/baseline11', to: 'benchmark#baseline_one'
post '/baseline11', to: 'benchmark#baseline_one'
get '/baseline2', to: 'benchmark#baseline_two'
get '/json/:count', to: 'benchmark#json_endpoint'
get '/async-db', to: 'benchmark#async_db'
post '/upload', to: 'benchmark#upload'
get '/baseline11', to: 'benchmark#baseline_one'
post '/baseline11', to: 'benchmark#baseline_one'
get '/baseline2', to: 'benchmark#baseline_two'
get '/json/:count', to: 'benchmark#json_endpoint'
get '/async-db', to: 'benchmark#async_db'
post '/upload', to: 'benchmark#upload'
get '/crud/items', to: 'items#index'
get '/crud/items/:id', to: "items#show"
post '/crud/items', to: 'items#create'
put '/crud/items/:id', to: 'items#update'

# Catch-all for unknown paths → 404
get '*', to: 'benchmark#not_found'
Expand Down
1 change: 1 addition & 0 deletions frameworks/rage/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"api-4",
"api-16",
"async-db",
"crud",
"static"
],
"maintainers": ["p8"]
Expand Down