with_transactional_lock 2.3.0 → 3.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: 5e23e87e0f583421cd8059c2357cb938189754803f981411f6dac9111ba128df
4
- data.tar.gz: 7294f251168099acfad4122609c6a0d5b2debb17edb6a66ebc65e5ea87f1efdb
3
+ metadata.gz: 5a37a429d4501cab5013a8adda04f58543f9dfa1ce272669fb3e77b50ba41ba1
4
+ data.tar.gz: 21c127ebf79c22c6e6b658b0bd3084553af9f0f0a414171438912d6f3f32b63a
5
5
  SHA512:
6
- metadata.gz: 1e4984a3ea1ceda7c6a163b99eff34f6364ab37038da8a26e15ed01d5527a8775ac70b33db4c6dcbb8a8385528a62bdadb39a2983e05036a269f630a94b72338
7
- data.tar.gz: 7f1a85d1c4372eaee6406cb95a8c3c7b45bd35b8ac3248d321c212e06b37f033a4628a4d29ce358d6fcef200e90a671405c9537b3bcf791f0f56f3d787aa5a0b
6
+ metadata.gz: 6f177f997f70e2b22c426ca79281a537ef4a058e6baaf31bbe34730700b451c06fc5c2e81b3f809d5c525feab6c3e5427cc6650051f08ff5ca63c26d9242d5b4
7
+ data.tar.gz: fef780d0e0805babed56e1e6f2f64642c13afcc27ac1ada1b71a2e4b9ed9b24aa523ca571f02b5c711d6ac47159569240a853fa8aedbac4d0eb06507c6690dbd
data/README.md CHANGED
@@ -1,14 +1,14 @@
1
1
  # with_transactional_lock
2
2
 
3
3
  A simple extension to ActiveRecord for performing advisory locking on
4
- MySQL and PostgreSQL.
4
+ PostgreSQL.
5
5
 
6
6
  An advisory lock is a database-level mutex that can be used to prevent
7
7
  concurrent access to a shared resource or to prevent two workers from
8
8
  performing the same process concurrently.
9
9
 
10
10
  This gem is different from other advisory locking gems because it
11
- uses advisory transaction locks instead of advisory session locks.
11
+ uses advisory transaction locks instead of advisory session locks.
12
12
 
13
13
  ## Why transactional?
14
14
 
@@ -31,7 +31,7 @@ preventing leaks.
31
31
  Additionally, application developers tend to think about discrete units
32
32
  of database work in terms of transactions. By leveraging the transaction
33
33
  boundary, we ensure the advisory lock is released at the earliest
34
- possible moment that it can be and no sooner.
34
+ possible moment that it can be and no sooner.
35
35
 
36
36
  ## Lock acquisition efficiency & fairness
37
37
 
@@ -60,25 +60,16 @@ waiting on I/O (possibly allowing another thread to use the CPU).
60
60
 
61
61
  Add this line to your application's Gemfile:
62
62
 
63
- ``` ruby
63
+ ```ruby
64
64
  gem 'with_transactional_lock'
65
65
  ```
66
66
 
67
67
  And then bundle install:
68
68
 
69
69
  ```
70
- $ bundle install
71
- ```
72
-
73
- And then if you're using MySQL, you will need to run the installer:
74
-
75
- ```
76
- $ rails g with_transactional_lock:install
70
+ bundle install
77
71
  ```
78
72
 
79
- This will create a migration that will add an
80
- `transactional_advisory_locks` table to your database.
81
-
82
73
  ## Usage
83
74
 
84
75
  Because transactional locks are meaningless outside of the context of a
@@ -92,12 +83,12 @@ ActiveRecord::Base.with_transactional_lock('name_of_a_resource') do
92
83
  end
93
84
  ```
94
85
 
95
- This call will attempt to acquire an exclusive lock using the provided
86
+ This call will attempt to acquire an exclusive lock using the provided
96
87
  lock name. It will wait indefinitely for that lock -- or at least as
97
88
  long as your database connection timeout is willing to allow. Once the
98
89
  lock is acquired you will have exclusive ownership of the advisory lock
99
90
  with the name that you provided. Your block is free to execute its
100
- critical work. Upon completion of your transaction, the lock will be
91
+ critical work. Upon completion of your transaction, the lock will be
101
92
  released.
102
93
 
103
94
  ## Supported databases
@@ -109,15 +100,6 @@ PostgreSQL has first-class support for transactional advisory locks via
109
100
  duration of a given transaction and automatically released upon
110
101
  transaction commit.
111
102
 
112
- ### MySQL
113
-
114
- MySQL does not have built-in support for transactional advisory locks.
115
- So, MySQL gets a special treatment. We emulate the behavior of PostgreSQL
116
- using a special `transactional_advisory_locks` table with a unique index
117
- on the `lock_id` column. This allows us to provide the same transactional
118
- and mutual exclusivity guarantees as PostgreSQL. The trade-off is that
119
- you need to add another table to your database.
120
-
121
103
  ## License
122
104
 
123
105
  Any contributions made to this project are covered under the MIT License, found [here](LICENSE)
@@ -23,8 +23,6 @@ module WithTransactionalLock
23
23
  def self.locate(connection)
24
24
  adapter = connection.adapter_name.downcase.to_sym
25
25
  case adapter
26
- when :mysql, :mysql2
27
- MySqlAdvisoryLock
28
26
  when :postgresql
29
27
  PostgresAdvisoryLock
30
28
  else
@@ -55,20 +53,11 @@ module WithTransactionalLock
55
53
  end
56
54
  end
57
55
 
58
- class MySqlAdvisoryLock < AdvisoryLockBase
59
- private
60
-
61
- def acquire_lock
62
- connection.execute("insert into transactional_advisory_locks values (#{connection.quote(db_lock_name)}) \
63
- on duplicate key update lock_id = lock_id")
64
- end
65
- end
66
-
67
56
  class PostgresAdvisoryLock < AdvisoryLockBase
68
57
  private
69
58
 
70
59
  def acquire_lock
71
- connection.execute("select pg_advisory_xact_lock(#{connection.quote(db_lock_name)})")
60
+ connection.execute("/* lock:#{lock_name} */ SELECT pg_advisory_xact_lock(#{connection.quote(db_lock_name)})")
72
61
  end
73
62
  end
74
63
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WithTransactionalLock
4
- VERSION = "2.3.0"
4
+ VERSION = "3.0.0"
5
5
  end
@@ -5,7 +5,6 @@ require "with_transactional_lock/engine"
5
5
  module WithTransactionalLock
6
6
  extend ActiveSupport::Autoload
7
7
  autoload :Mixin
8
- autoload :MySqlHelper
9
8
  end
10
9
 
11
10
  ActiveSupport.on_load(:active_record) { include WithTransactionalLock::Mixin }
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: with_transactional_lock
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Moore
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-11-22 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activerecord
@@ -19,7 +18,7 @@ dependencies:
19
18
  version: '7.0'
20
19
  - - "<"
21
20
  - !ruby/object:Gem::Version
22
- version: '7.2'
21
+ version: '8.1'
23
22
  type: :runtime
24
23
  prerelease: false
25
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +28,7 @@ dependencies:
29
28
  version: '7.0'
30
29
  - - "<"
31
30
  - !ruby/object:Gem::Version
32
- version: '7.2'
31
+ version: '8.1'
33
32
  - !ruby/object:Gem::Dependency
34
33
  name: railties
35
34
  requirement: !ruby/object:Gem::Requirement
@@ -39,7 +38,7 @@ dependencies:
39
38
  version: '7.0'
40
39
  - - "<"
41
40
  - !ruby/object:Gem::Version
42
- version: '7.2'
41
+ version: '8.1'
43
42
  type: :runtime
44
43
  prerelease: false
45
44
  version_requirements: !ruby/object:Gem::Requirement
@@ -49,23 +48,9 @@ dependencies:
49
48
  version: '7.0'
50
49
  - - "<"
51
50
  - !ruby/object:Gem::Version
52
- version: '7.2'
51
+ version: '8.1'
53
52
  - !ruby/object:Gem::Dependency
54
53
  name: appraisal
55
- requirement: !ruby/object:Gem::Requirement
56
- requirements:
57
- - - "~>"
58
- - !ruby/object:Gem::Version
59
- version: 2.2.0
60
- type: :development
61
- prerelease: false
62
- version_requirements: !ruby/object:Gem::Requirement
63
- requirements:
64
- - - "~>"
65
- - !ruby/object:Gem::Version
66
- version: 2.2.0
67
- - !ruby/object:Gem::Dependency
68
- name: betterlint
69
54
  requirement: !ruby/object:Gem::Requirement
70
55
  requirements:
71
56
  - - ">="
@@ -79,7 +64,7 @@ dependencies:
79
64
  - !ruby/object:Gem::Version
80
65
  version: '0'
81
66
  - !ruby/object:Gem::Dependency
82
- name: database_cleaner
67
+ name: betterlint
83
68
  requirement: !ruby/object:Gem::Requirement
84
69
  requirements:
85
70
  - - ">="
@@ -93,7 +78,7 @@ dependencies:
93
78
  - !ruby/object:Gem::Version
94
79
  version: '0'
95
80
  - !ruby/object:Gem::Dependency
96
- name: mysql2
81
+ name: database_cleaner
97
82
  requirement: !ruby/object:Gem::Requirement
98
83
  requirements:
99
84
  - - ">="
@@ -148,7 +133,7 @@ dependencies:
148
133
  - - ">="
149
134
  - !ruby/object:Gem::Version
150
135
  version: '0'
151
- description: Advisory locking support for MySQL and Postgresql done right.
136
+ description: Advisory locking support for Postgresql done right.
152
137
  email:
153
138
  - sam@betterment.com
154
139
  executables: []
@@ -158,13 +143,9 @@ files:
158
143
  - LICENSE
159
144
  - README.md
160
145
  - Rakefile
161
- - lib/generators/with_transactional_lock/install/install_generator.rb
162
- - lib/generators/with_transactional_lock/install/templates/README
163
- - lib/generators/with_transactional_lock/install/templates/db/migrate/create_transactional_advisory_locks.rb
164
146
  - lib/with_transactional_lock.rb
165
147
  - lib/with_transactional_lock/engine.rb
166
148
  - lib/with_transactional_lock/mixin.rb
167
- - lib/with_transactional_lock/my_sql_helper.rb
168
149
  - lib/with_transactional_lock/version.rb
169
150
  homepage: https://github.com/Betterment/with_transactional_lock
170
151
  licenses:
@@ -172,7 +153,6 @@ licenses:
172
153
  metadata:
173
154
  allowed_push_host: https://rubygems.org
174
155
  rubygems_mfa_required: 'true'
175
- post_install_message:
176
156
  rdoc_options: []
177
157
  require_paths:
178
158
  - lib
@@ -187,8 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
187
167
  - !ruby/object:Gem::Version
188
168
  version: '0'
189
169
  requirements: []
190
- rubygems_version: 3.5.23
191
- signing_key:
170
+ rubygems_version: 3.7.0
192
171
  specification_version: 4
193
172
  summary: Transactional advisory locks for ActiveRecord
194
173
  test_files: []
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rails/generators/base'
4
- require 'rails/generators/active_record'
5
-
6
- module WithTransactionalLock
7
- module Generators
8
- class InstallGenerator < Rails::Generators::Base
9
- include Rails::Generators::Migration
10
- source_root File.expand_path('templates', __dir__)
11
-
12
- def show_readme
13
- readme 'README'
14
- end
15
-
16
- def create_with_transactional_lock_migration
17
- if mysql?
18
- migration_template(
19
- 'db/migrate/create_transactional_advisory_locks.rb',
20
- 'db/migrate/create_transactional_advisory_locks.rb',
21
- )
22
- end
23
- end
24
-
25
- def self.next_migration_number(dir)
26
- ActiveRecord::Generators::Base.next_migration_number(dir)
27
- end
28
-
29
- private
30
-
31
- def mysql?
32
- ActiveRecord::Base.connection.adapter_name.downcase.include?('mysql')
33
- end
34
- end
35
- end
36
- end
@@ -1,8 +0,0 @@
1
- *******************************************************************************
2
-
3
- If you're using MySql, then run `rake db:migrate` to setup the `transactional_advisory_locks`
4
- table.
5
-
6
- If you're using Postgresql, then you're all set!
7
-
8
- *******************************************************************************
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class CreateTransactionalAdvisoryLocks < ActiveRecord::Migration
4
- def change
5
- create_table :transactional_advisory_locks, id: false do |t|
6
- t.integer :lock_id, null: false, limit: 8
7
- end
8
- add_index(:transactional_advisory_locks, :lock_id, unique: true, name: 'index_transactional_advisory_locks_on_lock_id')
9
- end
10
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module WithTransactionalLock
4
- class MySqlHelper
5
- def self.cleanup(klass = ActiveRecord::Base)
6
- klass.connection_pool.with_connection do |conn|
7
- target_count = conn.select_value('select count(1) from transactional_advisory_locks')
8
- count = 0
9
- count += conn.delete('delete from transactional_advisory_locks limit 1000') until count >= target_count
10
- end
11
- end
12
- end
13
- end