openstax_transaction_retry 1.2.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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