openstax_transaction_retry 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c9efa231f44b802b7971bc7f31fb06e0f01bb47c40d16fd56a4c0843f99c72f
4
- data.tar.gz: 8b415b5023c270aa9dec5000eb0c60f2d2dbb0f26fd5b4f489b20c7d6842b9f9
3
+ metadata.gz: 8454103b320f693e3cab50ae57dc9de433089328baa396405dc89b19d58cac14
4
+ data.tar.gz: 4d7404ecbfb74328d6d75052f1ef9bbd6732476021cfb40467dab5a2d27f90f4
5
5
  SHA512:
6
- metadata.gz: 155c201291db2070d61814d2ea73dbdc69c58d284552a7bd84c1be367a3b33aa5e9dfc78cd8be24aa8e1d51f1cac15f74087da33b1314d91d72b19bd7682c28b
7
- data.tar.gz: 5ca4998b159bf2a83a9839d4cb2f57aeb20a16c33730320e233a7733af712189fea737b969628937c88c97c553520a062042a913ab0d65dc43c31930be85447e
6
+ metadata.gz: 8febebd64c85b5a9c25a875489bafb728a246549a8784895c49320ecdf15163bf3e703eba6050888df496fb7d27a3cf97a822cd57653e739fdf1e3bb5be74a63
7
+ data.tar.gz: 1dcd1c4e8c8f71b567d0acc08a24d72f56111a5d40a0b7d1ec41346fe53240bf71bdc6229231ceb744c07640217a18f74ce2bd5451d9762a73f84ddc2763d010
data/.rubocop.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.6
2
+ TargetRubyVersion: 3.0
3
3
  SuggestExtensions: false
4
4
  NewCops: enable
5
5
  Exclude:
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OpenStaxTransactionRetry
4
- VERSION = '1.2.0'
4
+ VERSION = '2.0.0'
5
5
  end
@@ -11,13 +11,12 @@ Gem::Specification.new do |s|
11
11
  s.homepage = 'https://github.com/openstax/transaction_retry'
12
12
  s.summary = 'Retries database transaction on deadlock and transaction serialization errors. Supports MySQL, PostgreSQL and SQLite.'
13
13
  s.description = 'Retries database transaction on deadlock and transaction serialization errors. Supports MySQL, PostgreSQL and SQLite (as long as you are using new drivers mysql2, pg, sqlite3).'
14
- s.required_ruby_version = '>= 2.6'
14
+ s.required_ruby_version = '>= 3.0'
15
15
 
16
- s.files = `git ls-files`.split("\n")
17
- s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
16
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f == 'd' || f.start_with?('test') }
18
17
  s.require_paths = ['lib']
19
18
 
20
- s.add_runtime_dependency 'activerecord', '>= 5.1'
21
- s.add_runtime_dependency 'transaction_isolation', '>= 1.0.5'
19
+ s.add_dependency 'activerecord', '>= 6'
20
+ s.add_dependency 'openstax_transaction_isolation', '>= 2'
22
21
  s.metadata['rubygems_mfa_required'] = 'true'
23
22
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openstax_transaction_retry
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Stitt
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-08-28 00:00:00.000000000 Z
13
+ date: 2025-01-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -18,28 +18,28 @@ dependencies:
18
18
  requirements:
19
19
  - - ">="
20
20
  - !ruby/object:Gem::Version
21
- version: '5.1'
21
+ version: '6'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
- version: '5.1'
28
+ version: '6'
29
29
  - !ruby/object:Gem::Dependency
30
- name: transaction_isolation
30
+ name: openstax_transaction_isolation
31
31
  requirement: !ruby/object:Gem::Requirement
32
32
  requirements:
33
33
  - - ">="
34
34
  - !ruby/object:Gem::Version
35
- version: 1.0.5
35
+ version: '2'
36
36
  type: :runtime
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
40
  - - ">="
41
41
  - !ruby/object:Gem::Version
42
- version: 1.0.5
42
+ version: '2'
43
43
  description: Retries database transaction on deadlock and transaction serialization
44
44
  errors. Supports MySQL, PostgreSQL and SQLite (as long as you are using new drivers
45
45
  mysql2, pg, sqlite3).
@@ -58,22 +58,10 @@ files:
58
58
  - LICENSE
59
59
  - README.md
60
60
  - Rakefile
61
- - d
62
61
  - lib/open_stax_transaction_retry.rb
63
62
  - lib/open_stax_transaction_retry/active_record/base.rb
64
63
  - lib/open_stax_transaction_retry/version.rb
65
64
  - open_stax_transaction_retry.gemspec
66
- - test/db/all.rb
67
- - test/db/db.rb
68
- - test/db/migrations.rb
69
- - test/db/queued_job.rb
70
- - test/integration/active_record/base/transaction_with_retry_test.rb
71
- - test/library_setup.rb
72
- - test/log/.gitkeep
73
- - test/test_console.rb
74
- - test/test_helper.rb
75
- - test/test_runner.rb
76
- - tests
77
65
  homepage: https://github.com/openstax/transaction_retry
78
66
  licenses: []
79
67
  metadata:
@@ -86,14 +74,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
86
74
  requirements:
87
75
  - - ">="
88
76
  - !ruby/object:Gem::Version
89
- version: '2.6'
77
+ version: '3.0'
90
78
  required_rubygems_version: !ruby/object:Gem::Requirement
91
79
  requirements:
92
80
  - - ">="
93
81
  - !ruby/object:Gem::Version
94
82
  version: '0'
95
83
  requirements: []
96
- rubygems_version: 3.4.7
84
+ rubygems_version: 3.4.6
97
85
  signing_key:
98
86
  specification_version: 4
99
87
  summary: Retries database transaction on deadlock and transaction serialization errors.
data/d DELETED
@@ -1 +0,0 @@
1
- bundle exec ruby test/test_console.rb
data/test/db/all.rb DELETED
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_record'
4
- require_relative 'db'
5
- require_relative 'migrations'
6
- require_relative 'queued_job'
data/test/db/db.rb DELETED
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'fileutils'
4
-
5
- module OpenStaxTransactionRetry
6
- module Test
7
- module Db
8
- def self.connect_to_mysql2
9
- ::ActiveRecord::Base.establish_connection(
10
- adapter: 'mysql2',
11
- database: 'transaction_retry_test',
12
- username: ENV.fetch('DB_USERNAME'),
13
- password: ENV.fetch('DB_PASSWORD', nil)
14
- )
15
- end
16
-
17
- def self.connect_to_postgresql
18
- ::ActiveRecord::Base.establish_connection(
19
- adapter: 'postgresql',
20
- host: ENV.fetch('DB_HOST', nil),
21
- port: ENV.fetch('DB_PORT', nil),
22
- database: ENV.fetch('DB_NAME', nil),
23
- user: ENV.fetch('DB_USERNAME', nil),
24
- password: ENV.fetch('DB_PASSWORD', nil)
25
- )
26
- end
27
-
28
- def self.connect_to_sqlite3
29
- ActiveRecord::Base.establish_connection(
30
- adapter: 'sqlite3',
31
- database: ':memory:',
32
- verbosity: 'silent'
33
- )
34
- end
35
- end
36
- end
37
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module OpenStaxTransactionRetry
4
- module Test
5
- module Migrations
6
- def self.run!
7
- c = ::ActiveRecord::Base.connection
8
-
9
- # Queued Jobs
10
-
11
- c.create_table 'queued_jobs', force: true do |t|
12
- t.text 'job', null: false
13
- t.integer 'status', default: 0, null: false
14
- t.timestamps
15
- end
16
- end
17
- end
18
- end
19
- end
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class QueuedJob < ActiveRecord::Base
4
- end
@@ -1,209 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class TransactionWithRetryTest < Minitest::Test
6
- class CustomError < StandardError
7
- end
8
-
9
- def setup
10
- @original_max_retries = OpenStaxTransactionRetry.max_retries
11
- @original_wait_times = OpenStaxTransactionRetry.wait_times
12
- @original_retry_on = OpenStaxTransactionRetry.retry_on
13
- @original_before_retry = OpenStaxTransactionRetry.before_retry
14
- end
15
-
16
- def teardown
17
- OpenStaxTransactionRetry.max_retries = @original_max_retries
18
- OpenStaxTransactionRetry.wait_times = @original_wait_times
19
- OpenStaxTransactionRetry.retry_on = @original_retry_on
20
- OpenStaxTransactionRetry.before_retry = @original_before_retry
21
- QueuedJob.delete_all
22
- end
23
-
24
- def test_does_not_break_transaction
25
- ActiveRecord::Base.transaction do
26
- QueuedJob.create!(job: 'is fun!')
27
- assert_equal(1, QueuedJob.count)
28
- end
29
- assert_equal(1, QueuedJob.count)
30
- QueuedJob.first.destroy
31
- end
32
-
33
- def test_does_not_break_transaction_rollback
34
- ActiveRecord::Base.transaction do
35
- QueuedJob.create!(job: 'gives money!')
36
- raise ActiveRecord::Rollback
37
- end
38
- assert_equal(0, QueuedJob.count)
39
- end
40
-
41
- def test_retries_transaction_on_transaction_isolation_conflict
42
- first_run = true
43
-
44
- ActiveRecord::Base.transaction do
45
- if first_run
46
- first_run = false
47
- message = 'Deadlock found when trying to get lock'
48
- raise ActiveRecord::TransactionIsolationConflict, message
49
- end
50
- QueuedJob.create!(job: 'is cool!')
51
- end
52
- assert_equal(1, QueuedJob.count)
53
-
54
- QueuedJob.first.destroy
55
- end
56
-
57
- def test_does_not_retry_on_unknown_error
58
- first_run = true
59
-
60
- assert_raises(CustomError) do
61
- ActiveRecord::Base.transaction do
62
- if first_run
63
- first_run = false
64
- raise CustomError, 'random error'
65
- end
66
- QueuedJob.create!(job: 'is cool!')
67
- end
68
- end
69
- assert_equal(0, QueuedJob.count)
70
- end
71
-
72
- def test_retries_on_custom_error
73
- first_run = true
74
- ActiveRecord::Base.transaction(retry_on: CustomError) do
75
- if first_run
76
- first_run = false
77
- raise CustomError, 'random error'
78
- end
79
- QueuedJob.create!(job: 'is cool!')
80
- end
81
- assert_equal(1, QueuedJob.count)
82
- QueuedJob.first.destroy
83
- end
84
-
85
- def test_retries_on_configured_retry_on
86
- OpenStaxTransactionRetry.retry_on = CustomError
87
- first_run = true
88
- ActiveRecord::Base.transaction do
89
- if first_run
90
- first_run = false
91
- raise CustomError, 'random error'
92
- end
93
- QueuedJob.create!(job: 'is cool!')
94
- end
95
- assert_equal(1, QueuedJob.count)
96
- QueuedJob.first.destroy
97
- end
98
-
99
- def test_retries_transaction_on_transaction_isolation_when_retry_on_set
100
- OpenStaxTransactionRetry.retry_on = CustomError
101
- first_run = true
102
- ActiveRecord::Base.transaction do
103
- if first_run
104
- first_run = false
105
- message = 'Deadlock found when trying to get lock'
106
- raise ActiveRecord::TransactionIsolationConflict, message
107
- end
108
- QueuedJob.create!(job: 'is cool!')
109
- end
110
- assert_equal(1, QueuedJob.count)
111
- QueuedJob.first.destroy
112
- end
113
-
114
- def test_does_not_retry_transaction_more_than_max_retries_times
115
- OpenStaxTransactionRetry.max_retries = 1
116
- run = 0
117
-
118
- assert_raises(ActiveRecord::TransactionIsolationConflict) do
119
- ActiveRecord::Base.transaction do
120
- run += 1
121
- message = 'Deadlock found when trying to get lock'
122
- raise ActiveRecord::TransactionIsolationConflict, message
123
- end
124
- end
125
-
126
- assert_equal(2, run) # normal run + one retry
127
-
128
- OpenStaxTransactionRetry.max_retries = 3
129
-
130
- run = 0
131
-
132
- assert_raises(ActiveRecord::TransactionIsolationConflict) do
133
- ActiveRecord::Base.transaction(max_retries: 1) do
134
- run += 1
135
- message = 'Deadlock found when trying to get lock'
136
- raise ActiveRecord::TransactionIsolationConflict, message
137
- end
138
- end
139
-
140
- assert_equal(2, run) # normal run + one retry
141
- end
142
-
143
- def test_does_not_retry_nested_transaction
144
- first_try = true
145
-
146
- ActiveRecord::Base.transaction do
147
- assert_raises(ActiveRecord::TransactionIsolationConflict) do
148
- ActiveRecord::Base.transaction(requires_new: true) do
149
- if first_try
150
- first_try = false
151
- message = 'Deadlock found when trying to get lock'
152
- raise ActiveRecord::TransactionIsolationConflict, message
153
- end
154
- QueuedJob.create!(job: 'is cool!')
155
- end
156
- end
157
- end
158
-
159
- assert_equal(0, QueuedJob.count)
160
- end
161
-
162
- def test_run_custom_lambda_before_retry
163
- code_run = false
164
- retry_id = nil
165
- error_instance = nil
166
- first_try = true
167
- lambda_code = lambda do |retry_num, error|
168
- code_run = true
169
- retry_id = retry_num
170
- error_instance = error
171
- end
172
-
173
- ActiveRecord::Base.transaction(before_retry: lambda_code) do
174
- if first_try
175
- first_try = false
176
- raise ActiveRecord::TransactionIsolationConflict
177
- end
178
- QueuedJob.create!(job: 'is cool!')
179
- end
180
- assert_equal 1, QueuedJob.count
181
- assert code_run
182
- assert_equal 1, retry_id
183
- assert_equal ActiveRecord::TransactionIsolationConflict, error_instance.class
184
- end
185
-
186
- def test_run_custom_global_lambda_before_retry
187
- code_run = false
188
- retry_id = nil
189
- error_instance = nil
190
- OpenStaxTransactionRetry.before_retry = lambda { |retry_num, error|
191
- code_run = true
192
- retry_id = retry_num
193
- error_instance = error
194
- }
195
- first_try = true
196
-
197
- ActiveRecord::Base.transaction do
198
- if first_try
199
- first_try = false
200
- raise ActiveRecord::TransactionIsolationConflict
201
- end
202
- QueuedJob.create!(job: 'is cool!')
203
- end
204
- assert_equal 1, QueuedJob.count
205
- assert code_run
206
- assert_equal 1, retry_id
207
- assert_equal ActiveRecord::TransactionIsolationConflict, error_instance.class
208
- end
209
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Prepares application to be tested (requires files, connects to db, resets schema and data, applies patches, etc.)
4
-
5
- # Initialize database
6
- require 'db/all'
7
-
8
- case ENV.fetch('db', 'sqlite3')
9
- when 'mysql2'
10
- OpenStaxTransactionRetry::Test::Db.connect_to_mysql2
11
- when 'postgresql'
12
- OpenStaxTransactionRetry::Test::Db.connect_to_postgresql
13
- when 'sqlite3'
14
- OpenStaxTransactionRetry::Test::Db.connect_to_sqlite3
15
- else
16
- raise "Unknown database: #{ENV.fetch('db', nil)}"
17
- end
18
-
19
- require 'logger'
20
- ActiveRecord::Base.logger = Logger.new(File.expand_path("#{File.dirname(__FILE__)}/log/test.log"))
21
-
22
- OpenStaxTransactionRetry::Test::Migrations.run!
23
-
24
- # Load the code that will be tested
25
- require 'open_stax_transaction_retry'
26
-
27
- OpenStaxTransactionRetry.apply_activerecord_patch
data/test/log/.gitkeep DELETED
File without changes
data/test/test_console.rb DELETED
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Ensure that LOAD_PATH is the same as when running "rake test"; normally rake takes care of that
4
- $LOAD_PATH << File.expand_path('.', File.dirname(__FILE__))
5
- $LOAD_PATH << File.expand_path('./lib', File.dirname(__FILE__))
6
- $LOAD_PATH << File.expand_path('./test', File.dirname(__FILE__))
7
-
8
- # Boot the app
9
- require_relative 'library_setup'
10
-
11
- # Fire the console
12
- require 'pry'
13
-
14
- binding.pry # rubocop:disable Lint/Debugger
data/test/test_helper.rb DELETED
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Load test coverage tool (must be loaded before any code)
4
- # require 'simplecov'
5
- # SimpleCov.start do
6
- # add_filter '/test/'
7
- # add_filter '/config/'
8
- # end
9
-
10
- # Load and initialize the application to be tested
11
- require 'library_setup'
12
-
13
- # Load test frameworks
14
- require 'minitest/autorun'
data/test/test_runner.rb DELETED
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- # Load all tests
6
- Dir.glob('./**/*_test.rb').sort.each { |test_file| require test_file }
data/tests DELETED
@@ -1,6 +0,0 @@
1
-
2
- db=mysql2 bundle exec rake
3
-
4
- db=postgresql bundle exec rake
5
-
6
- db=sqlite3 bundle exec rake