Skip to content

Commit 107b23e

Browse files
authored
Merge pull request #321 from openstax/retry_prepared_statement_cache_expired
Retry ActiveRecord::PreparedStatementCacheExpired exceptions
2 parents 7effe11 + 1c20681 commit 107b23e

File tree

5 files changed

+62
-4
lines changed

5 files changed

+62
-4
lines changed

Gemfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ gem 'openstax_api'
7171
gem 'apipie-rails'
7272
gem 'maruku'
7373

74+
# Retry failed database transactions
75+
gem 'transaction_retry', github: 'openstax/transaction_retry'
76+
7477
# Lev framework
7578
gem 'lev'
7679

Gemfile.lock

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
GIT
2+
remote: https://github.com/openstax/transaction_retry.git
3+
revision: 5a148396c3b332a7e6a1ad5c7e6eb86b68f09829
4+
specs:
5+
transaction_retry (1.0.3)
6+
activerecord (>= 3.0.11)
7+
transaction_isolation (>= 1.0.2)
8+
19
GEM
210
remote: https://rubygems.org/
311
specs:
@@ -480,9 +488,6 @@ GEM
480488
timecop (0.9.2)
481489
transaction_isolation (1.0.5)
482490
activerecord (>= 3.0.11)
483-
transaction_retry (1.0.3)
484-
activerecord (>= 3.0.11)
485-
transaction_isolation (>= 1.0.2)
486491
turbolinks (5.2.1)
487492
turbolinks-source (~> 5.2)
488493
turbolinks-source (5.2.0)
@@ -575,6 +580,7 @@ DEPENDENCIES
575580
sortability
576581
thin
577582
timecop
583+
transaction_retry!
578584
turbolinks
579585
uglifier (>= 1.3.0)
580586
web-console
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# TransactionRetry.max_retries = 3
2+
# TransactionRetry.wait_times = [0, 1, 2, 4, 8, 16, 32] # seconds to sleep after retry n
3+
TransactionRetry.retry_on = ActiveRecord::PreparedStatementCacheExpired # or an array of classes is valid too (ActiveRecord::TransactionIsolationConflict is by default always included)
4+
# TransactionRetry.before_retry = ->(retry_num, error) { ... }

spec/lib/transaction_retry_spec.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
require 'rails_helper'
2+
3+
# Need truncation: true because transaction_retry only retries top-level transactions
4+
RSpec.describe TransactionRetry, type: :lib, truncation: true do
5+
it 'retries ActiveRecord::PreparedStatementCacheExpired' do
6+
result = nil
7+
8+
ActiveRecord::Base.transaction do
9+
if result.nil?
10+
result = 21
11+
12+
raise ActiveRecord::PreparedStatementCacheExpired.new('test')
13+
else
14+
result = 42
15+
end
16+
end
17+
18+
expect(result).to eq 42
19+
end
20+
end

spec/rails_helper.rb

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
# If you're not using ActiveRecord, or you'd prefer not to run each of your
4444
# examples within a transaction, remove the following line or assign false
4545
# instead of true.
46-
config.use_transactional_fixtures = true
46+
config.use_transactional_fixtures = false
4747

4848
# RSpec Rails can automatically mix in different behaviours to your tests
4949
# based on their file location, for example enabling you to call `get` and
@@ -59,6 +59,31 @@
5959
# The different available types are documented in the features, such as in
6060
# https://relishapp.com/rspec/rspec-rails/docs
6161
config.infer_spec_type_from_file_location!
62+
63+
config.prepend_before(:suite) do
64+
DatabaseCleaner.clean_with(:truncation)
65+
end
66+
67+
config.prepend_before(:all) do
68+
metadata = self.class.metadata
69+
DatabaseCleaner.strategy = metadata[:js] || metadata[:truncation] ? :truncation : :transaction
70+
DatabaseCleaner.start
71+
end
72+
73+
config.prepend_before(:each) do
74+
DatabaseCleaner.start
75+
end
76+
77+
# https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example says:
78+
# "It's also recommended to use append_after to ensure DatabaseCleaner.clean
79+
# runs after the after-test cleanup capybara/rspec installs."
80+
config.append_after(:each) do
81+
DatabaseCleaner.clean
82+
end
83+
84+
config.append_after(:all) do
85+
DatabaseCleaner.clean
86+
end
6287
end
6388

6489
# Adds a convenience method to get interpret the body as JSON and convert to a hash;

0 commit comments

Comments
 (0)