diff --git a/.circleci/config.yml b/.circleci/config.yml index f6180ad..6b330fe 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,6 +10,8 @@ jobs: # See: https://circleci.com/docs/2.0/configuration-reference/#docker-machine-macos-windows-executor docker: - image: cimg/rust:1.58.1 + environment: + RUST_LOG: info - image: cimg/postgres:14.0 auth: username: mydockerhub-user diff --git a/tests/ruby/tests.rb b/tests/ruby/tests.rb index 3ff39ab..622ac01 100644 --- a/tests/ruby/tests.rb +++ b/tests/ruby/tests.rb @@ -1,59 +1,27 @@ -require "active_record" +# frozen_string_literal: true + +require 'active_record' # Uncomment these two to see all queries. # ActiveRecord.verbose_query_logs = true # ActiveRecord::Base.logger = Logger.new(STDOUT) ActiveRecord::Base.establish_connection( - adapter: "postgresql", - host: "127.0.0.1", + adapter: 'postgresql', + host: '127.0.0.1', port: 6432, - username: "sharding_user", - password: "sharding_user", - database: "rails_dev", + username: 'sharding_user', + password: 'sharding_user', + database: 'rails_dev', prepared_statements: false, # Transaction mode - advisory_locks: false, # Same + advisory_locks: false # Same ) -class TestTable < ActiveRecord::Base - self.table_name = "test_table" -end - class TestSafeTable < ActiveRecord::Base - self.table_name = "test_safe_table" + self.table_name = 'test_safe_table' end -class ShouldNeverHappenException < Exception -end - -# # Create the table. -class CreateTestTable < ActiveRecord::Migration[7.0] - # Disable transasctions or things will fly out of order! - disable_ddl_transaction! - - SHARDS = 3 - - def change - SHARDS.times do |x| - # This will make this migration reversible! - reversible do - connection.execute "SET SHARD TO '#{x.to_i}'" - connection.execute "SET SERVER ROLE TO 'primary'" - end - - # Always wrap the entire migration inside a transaction. If that's not possible, - # execute a `SET SHARD` command before every statement and make sure AR doesn't need - # to load database information beforehand (i.e. it's not the first query in the migration). - connection.transaction do - create_table :test_table, if_not_exists: true do |t| - t.string :name - t.string :description - - t.timestamps - end - end - end - end +class ShouldNeverHappenException < RuntimeError end class CreateSafeShardedTable < ActiveRecord::Migration[7.0] @@ -85,44 +53,51 @@ class CreateSafeShardedTable < ActiveRecord::Migration[7.0] SHARDS.times do |x| connection.execute "SET SHARD TO '#{x.to_i}'" connection.execute "SET SERVER ROLE TO 'primary'" - connection.execute "DROP TABLE test_safe_table CASCADE" + connection.execute 'DROP TABLE test_safe_table CASCADE' end end end -20.times do - begin - CreateTestTable.migrate(:down) - rescue Exception - puts "Tables don't exist yet" - end +SHARDS = 3 +2.times do begin CreateSafeShardedTable.migrate(:down) rescue Exception puts "Tables don't exist yet" end - CreateTestTable.migrate(:up) CreateSafeShardedTable.migrate(:up) - 3.times do |x| + SHARDS.times do |x| TestSafeTable.connection.execute "SET SHARD TO '#{x.to_i}'" TestSafeTable.connection.execute "SET SERVER ROLE TO 'primary'" - TestSafeTable.connection.execute "TRUNCATE #{TestTable.table_name}" + TestSafeTable.connection.execute "TRUNCATE #{TestSafeTable.table_name}" end - 10.times do |x| + # Equivalent to Makara's stick_to_master! except it sticks until it's changed. + TestSafeTable.connection.execute "SET SERVER ROLE TO 'primary'" + + 200.times do |x| x += 1 # Postgres ids start at 1 TestSafeTable.connection.execute "SET SHARDING KEY TO '#{x.to_i}'" - TestSafeTable.connection.execute "SET SERVER ROLE TO 'primary'" TestSafeTable.create(id: x, name: "something_special_#{x.to_i}", description: "It's a surprise!") end - 10.times do |x| + TestSafeTable.connection.execute "SET SERVER ROLE TO 'replica'" + + 100.times do |x| x += 1 # 0 confuses our sharding function TestSafeTable.connection.execute "SET SHARDING KEY TO '#{x.to_i}'" - TestSafeTable.connection.execute "SET SERVER ROLE TO 'replica'" + TestSafeTable.find_by_id(x).id + end + + # Will use the query parser to direct reads to replicas + TestSafeTable.connection.execute "SET SERVER ROLE TO 'auto'" + + 100.times do |x| + x += 101 + TestSafeTable.connection.execute "SET SHARDING KEY TO '#{x.to_i}'" TestSafeTable.find_by_id(x).id end end @@ -130,8 +105,8 @@ end # Test wrong shard TestSafeTable.connection.execute "SET SHARD TO '1'" begin - TestSafeTable.create(id: 5, name: "test", description: "test description") - raise ShouldNeverHappenException("Uh oh") + TestSafeTable.create(id: 5, name: 'test', description: 'test description') + raise ShouldNeverHappenException('Uh oh') rescue ActiveRecord::StatementInvalid - puts "OK" + puts 'OK' end