diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3440743a..9e50581e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,4 +88,4 @@ jobs: done cat ${{ github.workspace }}/setup.sql | cockroach sql --insecure - name: Test - run: bundle exec rake test TESTOPTS='--profile=5' + run: bundle exec rake test TESTOPTS='--profile=5 --name=test_concurrent_customer_insert_with_processes' diff --git a/test/cases/transactions_test.rb b/test/cases/transactions_test.rb new file mode 100644 index 00000000..01b05ae9 --- /dev/null +++ b/test/cases/transactions_test.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +require "cases/helper_cockroachdb" + +module CockroachDB + class TransactionsTest < ActiveRecord::TestCase + class Customer < ActiveRecord::Base + validate :validate_unique_username + + def validate_unique_username + duplicate = Customer.where(username: username).any? + errors.add("Duplicate username!") if duplicate + end + + def to_s + "#{id}:#{name}:#{username}" + end + end + + def setup + conn = ActiveRecord::Base.lease_connection + conn.create_table :customers, force: true do |t| + t.string :name + t.string :username + end + end + + def teardown + conn = ActiveRecord::Base.lease_connection + conn.drop_table :customers, if_exists: true + end + + def test_concurrent_customer_insert_with_processes + concurrency_level = 3 + time_to_start = 2.seconds.from_now + pids = [] + + concurrency_level.times do |i| + pids << Process.fork do + sleep_time = (time_to_start - Time.current).to_f + sleep(sleep_time) if sleep_time > 0 + + begin + c = Customer.new + c.name = "Customer #{i + 1}" + c.username = SecureRandom.uuid + c.save! + puts "Inserted customer with id #{c.id} successfully!" + rescue => e + puts "Process #{Process.pid} - Error: #{e.message}" + end + end + end + + pids.each { |pid| Process.wait(pid) } + + puts "Customers #{Customer.all.map { |c| c.to_s }}" + assert_equal concurrency_level, Customer.count + end + end +end