Browse Source

[ruby|sinatra] Use batch update on postgres (#9143)

Petrik de Heus 1 year ago
parent
commit
14c71fdc30

+ 6 - 6
frameworks/Ruby/sinatra/Gemfile

@@ -1,16 +1,16 @@
 source 'https://rubygems.org'
 
-gem 'activerecord', '~> 7.0', :require=>'active_record'
+gem 'activerecord', '~> 7.1', require: 'active_record'
 gem 'oj'
-gem 'passenger', '~> 6.0', :platforms=>[:ruby, :mswin], :require=>false
-gem 'puma', '~> 6.4', :require=>false
-gem 'sinatra', '~> 3.0', :require=>'sinatra/base'
-gem 'unicorn', '~> 6.1', :platforms=>[:ruby, :mswin], :require=>false
+gem 'passenger', '~> 6.0', platforms: [:ruby, :mswin], require: false
+gem 'puma', '~> 6.4', require: false
+gem 'sinatra', '~> 3.0', require: 'sinatra/base'
+gem 'unicorn', '~> 6.1', platforms: [:ruby, :mswin], require: false
 
 group :mysql do
   gem 'mysql2', '~> 0.5', :platforms=>[:ruby, :mswin]
 end
 
 group :postgresql do
-  gem 'pg', '~> 1.5', :platforms=>[:ruby, :mswin]
+  gem 'pg', '~> 1.5', platforms: [:ruby, :mswin]
 end

+ 12 - 2
frameworks/Ruby/sinatra/boot.rb

@@ -58,8 +58,18 @@ connect ENV.fetch('DBTYPE').to_sym
 class World < ActiveRecord::Base
   self.table_name = name
 
-  alias_attribute(:randomnumber, :randomNumber) \
-    if connection.adapter_name.downcase.start_with?('mysql')
+  alias_attribute(:randomNumber, :randomnumber) \
+    if connection.adapter_name.downcase.start_with?('postgres')
+
+  if connection.adapter_name.downcase.start_with?('mysql')
+    def self.upsert_all(attributes, on_duplicate: :update, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil)
+      # On MySQL Batch updates verification isn't supported yet by TechEmpower.
+      # https://github.com/TechEmpower/FrameworkBenchmarks/issues/5983
+      attributes.each do |attrs|
+        where(id: attrs[:id]).update_all(randomNumber: attrs[:randomNumber])
+      end
+    end
+  end
 end
 
 class Fortune < ActiveRecord::Base

+ 13 - 12
frameworks/Ruby/sinatra/hello_world.rb

@@ -45,7 +45,7 @@ class HelloWorld < Sinatra::Base
 
   # Test type 1: JSON serialization
   get '/json' do
-     json :message=>'Hello, World!'
+     json message: 'Hello, World!'
   end
 
   # Test type 2: Single database query
@@ -76,27 +76,28 @@ class HelloWorld < Sinatra::Base
       Fortune.all
     end.to_a
     @fortunes << Fortune.new(
-      :id=>0,
-      :message=>'Additional fortune added at request time.'
+      id: 0,
+      message: 'Additional fortune added at request time.'
     )
     @fortunes.sort_by!(&:message)
 
-    erb :fortunes, :layout=>true
+    erb :fortunes, layout: true
   end
 
   # Test type 5: Database updates
   get '/updates' do
     worlds =
-      ActiveRecord::Base.connection_pool.with_connection do
-        ALL_IDS.sample(bounded_queries).map do |id|
-          world = World.find(id)
-          new_value = rand1
-          new_value = rand1 while new_value == world.randomnumber
-          world.update_columns(randomnumber: new_value)
-          world.attributes
+      ALL_IDS.sample(bounded_queries).map do |id|
+        world = ActiveRecord::Base.connection_pool.with_connection do
+          World.find(id)
         end
+        new_value = rand1
+        new_value = rand1 until new_value != world.randomNumber
+        { id: id, randomNumber: new_value }
       end
-
+    ActiveRecord::Base.connection_pool.with_connection do
+      World.upsert_all(worlds.sort_by!{_1[:id]})
+    end
     json worlds
   end