with_advisory_lock 4.6.0 → 5.3.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 +4 -4
- data/.github/workflows/ci-mysql5.yml +61 -0
- data/.github/workflows/ci-mysql8.yml +62 -0
- data/.github/workflows/ci-postgresql.yml +64 -0
- data/.github/workflows/ci-sqlite3.yml +54 -0
- data/.github/workflows/release.yml +17 -0
- data/.gitignore +2 -0
- data/.release-please-manifest.json +1 -0
- data/.ruby-version +2 -0
- data/.tool-versions +1 -1
- data/Appraisals +34 -18
- data/CHANGELOG.md +50 -0
- data/Gemfile +0 -12
- data/LICENSE.txt +4 -4
- data/Makefile +14 -0
- data/README.md +17 -6
- data/docker-compose.yml +20 -0
- data/gemfiles/{activerecord_6.0.gemfile → activerecord_6.1.gemfile} +4 -2
- data/gemfiles/{activerecord_5.2.gemfile → activerecord_7.0.gemfile} +4 -2
- data/gemfiles/activerecord_7.1.gemfile +14 -0
- data/lib/with_advisory_lock/base.rb +18 -4
- data/lib/with_advisory_lock/concern.rb +17 -17
- data/lib/with_advisory_lock/database_adapter_support.rb +7 -47
- data/lib/with_advisory_lock/failed_to_acquire_lock.rb +9 -0
- data/lib/with_advisory_lock/flock.rb +4 -3
- data/lib/with_advisory_lock/mysql.rb +12 -7
- data/lib/with_advisory_lock/postgresql.rb +43 -18
- data/lib/with_advisory_lock/version.rb +3 -1
- data/lib/with_advisory_lock.rb +9 -10
- data/release-please-config.json +9 -0
- data/test/test_helper.rb +66 -0
- data/test/test_models.rb +16 -10
- data/test/with_advisory_lock/base_test.rb +9 -0
- data/test/with_advisory_lock/concern_test.rb +33 -0
- data/test/with_advisory_lock/lock_test.rb +111 -0
- data/test/with_advisory_lock/nesting_test.rb +28 -0
- data/test/with_advisory_lock/options_test.rb +66 -0
- data/test/with_advisory_lock/parallelism_test.rb +75 -0
- data/test/with_advisory_lock/shared_test.rb +134 -0
- data/test/with_advisory_lock/thread_test.rb +61 -0
- data/test/with_advisory_lock/transaction_test.rb +68 -0
- data/with_advisory_lock.gemspec +29 -23
- metadata +56 -47
- data/.travis.yml +0 -38
- data/gemfiles/activerecord_4.2.gemfile +0 -19
- data/gemfiles/activerecord_5.0.gemfile +0 -19
- data/gemfiles/activerecord_5.1.gemfile +0 -19
- data/lib/with_advisory_lock/mysql_no_nesting.rb +0 -20
- data/lib/with_advisory_lock/nested_advisory_lock_error.rb +0 -14
- data/test/concern_test.rb +0 -20
- data/test/database.yml +0 -17
- data/test/lock_test.rb +0 -47
- data/test/minitest_helper.rb +0 -40
- data/test/nesting_test.rb +0 -93
- data/test/options_test.rb +0 -64
- data/test/parallelism_test.rb +0 -77
- data/test/shared_test.rb +0 -131
- data/test/thread_test.rb +0 -60
- data/test/transaction_test.rb +0 -70
- data/tests.sh +0 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d65989d7502660ac5cbebd51a589fc49fb76bbeae5abb13814cb79a711fdaae8
|
|
4
|
+
data.tar.gz: 2eea1e741e2fdb100d3170ddce8c38b1d0fc59dc98f6340be51d6d5bde0591a4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8358a8783df5bcf9bd49507fc6e59d56aeaec8febd3978a4f9178950c88b254ec76925e3caa9f9f2ee18d7bc15d186512b3790dd1ba602a38fa6d1a877570887
|
|
7
|
+
data.tar.gz: d179cc20743f15a671ad822fd21e04e808336382d2eed318439e7b9c5ae9283ff4abf0576e5b0c274946863033f403d27280dfec84b3e3e4ff20f832ca62bcb5
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
name: CI Mysql 5.7
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
branches:
|
|
5
|
+
- master
|
|
6
|
+
concurrency:
|
|
7
|
+
group: ci-mysql5-${{ github.head_ref }}
|
|
8
|
+
cancel-in-progress: true
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
minitest:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
name: CI Mysql 5.7 Ruby ${{ matrix.ruby }} / Rails ${{ matrix.rails }} / Adapter ${{ matrix.adapter }}
|
|
14
|
+
services:
|
|
15
|
+
mysql:
|
|
16
|
+
image: mysql/mysql-server:5.7
|
|
17
|
+
ports:
|
|
18
|
+
- 3306
|
|
19
|
+
env:
|
|
20
|
+
MYSQL_USER: with_advisory
|
|
21
|
+
MYSQL_PASSWORD: with_advisory_pass
|
|
22
|
+
MYSQL_DATABASE: with_advisory_lock_test
|
|
23
|
+
MYSQL_ROOT_HOST: '%'
|
|
24
|
+
strategy:
|
|
25
|
+
fail-fast: false
|
|
26
|
+
matrix:
|
|
27
|
+
ruby:
|
|
28
|
+
# - '3.2'
|
|
29
|
+
# - '3.1'
|
|
30
|
+
# - '3.0'
|
|
31
|
+
# - '2.7'
|
|
32
|
+
- '3.3'
|
|
33
|
+
- 'truffleruby'
|
|
34
|
+
rails:
|
|
35
|
+
- 7.1
|
|
36
|
+
- "7.0"
|
|
37
|
+
- 6.1
|
|
38
|
+
adapter:
|
|
39
|
+
- mysql2
|
|
40
|
+
- trilogy
|
|
41
|
+
include:
|
|
42
|
+
- ruby: jruby
|
|
43
|
+
rails: 6.1
|
|
44
|
+
adapter: jdbcmysql
|
|
45
|
+
steps:
|
|
46
|
+
- name: Checkout
|
|
47
|
+
uses: actions/checkout@v4
|
|
48
|
+
- name: Setup Ruby
|
|
49
|
+
uses: ruby/setup-ruby@v1
|
|
50
|
+
with:
|
|
51
|
+
ruby-version: ${{ matrix.ruby }}
|
|
52
|
+
bundler-cache: true
|
|
53
|
+
rubygems: latest
|
|
54
|
+
env:
|
|
55
|
+
BUNDLE_GEMFILE: gemfiles/activerecord_${{ matrix.rails }}.gemfile
|
|
56
|
+
- name: Test
|
|
57
|
+
env:
|
|
58
|
+
BUNDLE_GEMFILE: gemfiles/activerecord_${{ matrix.rails }}.gemfile
|
|
59
|
+
DATABASE_URL: ${{ matrix.adapter }}://with_advisory:with_advisory_pass@0:${{ job.services.mysql.ports[3306] }}/with_advisory_lock_test
|
|
60
|
+
WITH_ADVISORY_LOCK_PREFIX: ${{ github.run_id }}
|
|
61
|
+
run: bundle exec rake
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: CI Mysql 8.0
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
branches:
|
|
5
|
+
- master
|
|
6
|
+
|
|
7
|
+
concurrency:
|
|
8
|
+
group: ci-mysql8-${{ github.head_ref }}
|
|
9
|
+
cancel-in-progress: true
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
minitest:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
name: CI Mysql 8.0 Ruby ${{ matrix.ruby }} / Rails ${{ matrix.rails }} / Adapter ${{ matrix.adapter }}
|
|
15
|
+
services:
|
|
16
|
+
mysql:
|
|
17
|
+
image: mysql/mysql-server
|
|
18
|
+
ports:
|
|
19
|
+
- 3306
|
|
20
|
+
env:
|
|
21
|
+
MYSQL_USER: with_advisory
|
|
22
|
+
MYSQL_PASSWORD: with_advisory_pass
|
|
23
|
+
MYSQL_DATABASE: with_advisory_lock_test
|
|
24
|
+
MYSQL_ROOT_HOST: '%'
|
|
25
|
+
strategy:
|
|
26
|
+
fail-fast: false
|
|
27
|
+
matrix:
|
|
28
|
+
ruby:
|
|
29
|
+
# - '3.2'
|
|
30
|
+
# - '3.1'
|
|
31
|
+
# - '3.0'
|
|
32
|
+
# - '2.7'
|
|
33
|
+
- '3.3'
|
|
34
|
+
- 'truffleruby'
|
|
35
|
+
rails:
|
|
36
|
+
- 7.1
|
|
37
|
+
- "7.0"
|
|
38
|
+
- 6.1
|
|
39
|
+
adapter:
|
|
40
|
+
- mysql2
|
|
41
|
+
# - trilogy://with_advisory:with_advisory_pass@0/with_advisory_lock_test Trilogy is not supported by mysql 8 with new encryption
|
|
42
|
+
include:
|
|
43
|
+
- ruby: jruby
|
|
44
|
+
rails: 6.1
|
|
45
|
+
adapter: jdbcmysql
|
|
46
|
+
steps:
|
|
47
|
+
- name: Checkout
|
|
48
|
+
uses: actions/checkout@v4
|
|
49
|
+
- name: Setup Ruby
|
|
50
|
+
uses: ruby/setup-ruby@v1
|
|
51
|
+
with:
|
|
52
|
+
ruby-version: ${{ matrix.ruby }}
|
|
53
|
+
bundler-cache: true
|
|
54
|
+
rubygems: latest
|
|
55
|
+
env:
|
|
56
|
+
BUNDLE_GEMFILE: gemfiles/activerecord_${{ matrix.rails }}.gemfile
|
|
57
|
+
- name: Test
|
|
58
|
+
env:
|
|
59
|
+
BUNDLE_GEMFILE: gemfiles/activerecord_${{ matrix.rails }}.gemfile
|
|
60
|
+
DATABASE_URL: ${{ matrix.adapter }}://with_advisory:with_advisory_pass@0:${{ job.services.mysql.ports[3306] }}/with_advisory_lock_test
|
|
61
|
+
WITH_ADVISORY_LOCK_PREFIX: ${{ github.run_id }}
|
|
62
|
+
run: bundle exec rake
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
name: CI Postgresql
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
branches:
|
|
5
|
+
- master
|
|
6
|
+
concurrency:
|
|
7
|
+
group: ci-postgresql-${{ github.head_ref }}
|
|
8
|
+
cancel-in-progress: true
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
minitest:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
name: CI Postgresql Ruby ${{ matrix.ruby }} / Rails ${{ matrix.rails }} / Adapter ${{ matrix.adapter }}
|
|
14
|
+
services:
|
|
15
|
+
postgres:
|
|
16
|
+
image: 'postgres:16-alpine'
|
|
17
|
+
ports:
|
|
18
|
+
- '5432'
|
|
19
|
+
env:
|
|
20
|
+
POSTGRES_USER: with_advisory
|
|
21
|
+
POSTGRES_PASSWORD: with_advisory_pass
|
|
22
|
+
POSTGRES_DB: with_advisory_lock_test
|
|
23
|
+
options: >-
|
|
24
|
+
--health-cmd pg_isready
|
|
25
|
+
--health-interval 10s
|
|
26
|
+
--health-timeout 5s
|
|
27
|
+
--health-retries 5
|
|
28
|
+
strategy:
|
|
29
|
+
fail-fast: false
|
|
30
|
+
matrix:
|
|
31
|
+
ruby:
|
|
32
|
+
# - '3.2'
|
|
33
|
+
# - '3.1'
|
|
34
|
+
# - '3.0'
|
|
35
|
+
# - '2.7'
|
|
36
|
+
- '3.3'
|
|
37
|
+
- 'truffleruby'
|
|
38
|
+
rails:
|
|
39
|
+
- 7.1
|
|
40
|
+
- "7.0"
|
|
41
|
+
- 6.1
|
|
42
|
+
adapter:
|
|
43
|
+
- postgres
|
|
44
|
+
include:
|
|
45
|
+
- ruby: jruby
|
|
46
|
+
rails: 6.1
|
|
47
|
+
adapter: jdbcpostgresql
|
|
48
|
+
steps:
|
|
49
|
+
- name: Checkout
|
|
50
|
+
uses: actions/checkout@v4
|
|
51
|
+
- name: Setup Ruby
|
|
52
|
+
uses: ruby/setup-ruby@v1
|
|
53
|
+
with:
|
|
54
|
+
ruby-version: ${{ matrix.ruby }}
|
|
55
|
+
bundler-cache: true
|
|
56
|
+
rubygems: latest
|
|
57
|
+
env:
|
|
58
|
+
BUNDLE_GEMFILE: gemfiles/activerecord_${{ matrix.rails }}.gemfile
|
|
59
|
+
- name: Test
|
|
60
|
+
env:
|
|
61
|
+
BUNDLE_GEMFILE: gemfiles/activerecord_${{ matrix.rails }}.gemfile
|
|
62
|
+
DATABASE_URL: ${{ matrix.adapter }}://with_advisory:with_advisory_pass@localhost:${{ job.services.postgres.ports[5432] }}/with_advisory_lock_test
|
|
63
|
+
WITH_ADVISORY_LOCK_PREFIX: ${{ github.run_id }}
|
|
64
|
+
run: bundle exec rake
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: CI Sqlite3
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches:
|
|
6
|
+
- master
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: ci-sqlite3-${{ github.head_ref }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
minitest:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
name: CI Sqlite3 Ruby ${{ matrix.ruby }} / Rails ${{ matrix.rails }} / Adapter ${{ matrix.adapter }}
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
ruby:
|
|
20
|
+
# - '3.2'
|
|
21
|
+
# - '3.1'
|
|
22
|
+
# - '3.0'
|
|
23
|
+
# - '2.7'
|
|
24
|
+
- '3.3'
|
|
25
|
+
- 'truffleruby'
|
|
26
|
+
rails:
|
|
27
|
+
- 7.1
|
|
28
|
+
- "7.0"
|
|
29
|
+
- 6.1
|
|
30
|
+
adapter:
|
|
31
|
+
- sqlite3
|
|
32
|
+
include:
|
|
33
|
+
- ruby: jruby
|
|
34
|
+
rails: 6.1
|
|
35
|
+
adapter: jdbcsqlite3
|
|
36
|
+
steps:
|
|
37
|
+
- name: Checkout
|
|
38
|
+
uses: actions/checkout@v4
|
|
39
|
+
|
|
40
|
+
- name: Setup Ruby
|
|
41
|
+
uses: ruby/setup-ruby@v1
|
|
42
|
+
with:
|
|
43
|
+
ruby-version: ${{ matrix.ruby }}
|
|
44
|
+
bundler-cache: true
|
|
45
|
+
rubygems: latest
|
|
46
|
+
env:
|
|
47
|
+
BUNDLE_GEMFILE: gemfiles/activerecord_${{ matrix.rails }}.gemfile
|
|
48
|
+
|
|
49
|
+
- name: Test
|
|
50
|
+
env:
|
|
51
|
+
BUNDLE_GEMFILE: gemfiles/activerecord_${{ matrix.rails }}.gemfile
|
|
52
|
+
DATABASE_URL: ${{ matrix.adapter }}:///tmp/test.sqlite3
|
|
53
|
+
WITH_ADVISORY_LOCK_PREFIX: ${{ github.run_id }}
|
|
54
|
+
run: bundle exec rake
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
name: release-please
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- master
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: write
|
|
11
|
+
pull-requests: write
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
release-please:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: googleapis/release-please-action@v4
|
data/.gitignore
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{".":"5.3.0"}
|
data/.ruby-version
ADDED
data/.tool-versions
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
ruby
|
|
1
|
+
ruby 3.4.4
|
data/Appraisals
CHANGED
|
@@ -1,29 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
appraise 'activerecord-7.1' do
|
|
4
|
+
gem 'activerecord', '~> 7.1.0'
|
|
3
5
|
platforms :ruby do
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
gem 'sqlite3'
|
|
7
|
+
gem 'mysql2'
|
|
8
|
+
gem 'trilogy'
|
|
9
|
+
gem 'pg'
|
|
7
10
|
end
|
|
8
11
|
end
|
|
9
12
|
|
|
10
|
-
appraise
|
|
11
|
-
gem
|
|
13
|
+
appraise 'activerecord-7.0' do
|
|
14
|
+
gem 'activerecord', '~> 7.0.0'
|
|
12
15
|
platforms :ruby do
|
|
13
|
-
gem
|
|
16
|
+
gem 'sqlite3'
|
|
17
|
+
gem 'mysql2'
|
|
18
|
+
gem 'trilogy'
|
|
19
|
+
gem "activerecord-trilogy-adapter"
|
|
20
|
+
gem 'pg'
|
|
21
|
+
end
|
|
22
|
+
platforms :jruby do
|
|
23
|
+
gem "activerecord-jdbcmysql-adapter"
|
|
24
|
+
gem "activerecord-jdbcpostgresql-adapter"
|
|
25
|
+
gem "activerecord-jdbcsqlite3-adapter"
|
|
14
26
|
end
|
|
15
27
|
end
|
|
16
28
|
|
|
17
|
-
appraise
|
|
18
|
-
gem
|
|
19
|
-
gem "sqlite3", "~> 1.3.6"
|
|
20
|
-
end
|
|
29
|
+
appraise 'activerecord-6.1' do
|
|
30
|
+
gem 'activerecord', '~> 6.1.0'
|
|
21
31
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
32
|
+
platforms :ruby do
|
|
33
|
+
gem 'sqlite3'
|
|
34
|
+
gem 'mysql2'
|
|
35
|
+
gem 'trilogy'
|
|
36
|
+
gem "activerecord-trilogy-adapter"
|
|
37
|
+
gem 'pg'
|
|
38
|
+
end
|
|
39
|
+
platforms :jruby do
|
|
40
|
+
gem "activerecord-jdbcmysql-adapter"
|
|
41
|
+
gem "activerecord-jdbcpostgresql-adapter"
|
|
42
|
+
gem "activerecord-jdbcsqlite3-adapter"
|
|
43
|
+
end
|
|
25
44
|
end
|
|
26
45
|
|
|
27
|
-
appraise "activerecord-6.0" do
|
|
28
|
-
gem "activerecord", "~> 6.0.0"
|
|
29
|
-
end
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,55 @@
|
|
|
1
1
|
## Changelog
|
|
2
2
|
|
|
3
|
+
## [5.3.0](https://github.com/ClosureTree/with_advisory_lock/compare/with_advisory_lock/v5.2.0...with_advisory_lock/v5.3.0) (2025-04-25)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add #current_advisory_locks method ([#111](https://github.com/ClosureTree/with_advisory_lock/issues/111)) ([ccbd3b2](https://github.com/ClosureTree/with_advisory_lock/commit/ccbd3b23465f7fa1fc3800334159986c31d5c351))
|
|
9
|
+
|
|
10
|
+
## [5.2.0](https://github.com/ClosureTree/with_advisory_lock/compare/with_advisory_lock/v5.1.0...with_advisory_lock/v5.2.0) (2025-04-24)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* use current connnection instead of the one in ActiveRecord::Base ([#90](https://github.com/ClosureTree/with_advisory_lock/issues/90)) ([c28a172](https://github.com/ClosureTree/with_advisory_lock/commit/c28a172a5a64594448b6090501fc0b8cbace06f6))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* Removed MySQL unused lock variable and broaden SQLite detection. ([#94](https://github.com/ClosureTree/with_advisory_lock/issues/94)) ([f818a18](https://github.com/ClosureTree/with_advisory_lock/commit/f818a181dde6711c8439c4cbf67c4525a09d346e))
|
|
21
|
+
|
|
22
|
+
## [5.1.0](https://github.com/ClosureTree/with_advisory_lock/compare/with_advisory_lock/v5.0.1...with_advisory_lock/v5.1.0) (2024-01-21)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
* use zeitwerk loader instead of ActiveSupport::Autoload ([b5082fd](https://github.com/ClosureTree/with_advisory_lock/commit/b5082fddacacacff48139f5bf509601a37945a0e))
|
|
28
|
+
|
|
29
|
+
## 5.0.1 (2024-01-21)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### Features
|
|
33
|
+
|
|
34
|
+
* add release workflow ([5d32520](https://github.com/ClosureTree/with_advisory_lock/commit/5d325201c82974991381a9fbc4d1714c9739dc4f))
|
|
35
|
+
* add ruby 3.1 test/support ([#60](https://github.com/ClosureTree/with_advisory_lock/issues/60)) ([514f042](https://github.com/ClosureTree/with_advisory_lock/commit/514f0420d957ef30911a00d54685385bec5867c3))
|
|
36
|
+
* Add testing for activerecord 7.1 and support for trilogy adapter ([#77](https://github.com/ClosureTree/with_advisory_lock/issues/77)) ([69c23fe](https://github.com/ClosureTree/with_advisory_lock/commit/69c23fe09887fc5d97ac7b0194825c21efe244a5))
|
|
37
|
+
* add truffleruby support ([#62](https://github.com/ClosureTree/with_advisory_lock/issues/62)) ([ec34bd4](https://github.com/ClosureTree/with_advisory_lock/commit/ec34bd448e3505e5df631daaf47bb83f2f5316dc))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
### Bug Fixes
|
|
41
|
+
|
|
42
|
+
* User may sometimes pass in non-strings, such as integers ([#55](https://github.com/ClosureTree/with_advisory_lock/issues/55)) ([9885597](https://github.com/ClosureTree/with_advisory_lock/commit/988559747363ef00958fcf782317e76c40ffa2a3))
|
|
43
|
+
|
|
44
|
+
### 5.0.0
|
|
45
|
+
- Drop support for EOL rubies and activerecord (ruby below 2.7 and activerecord below 6.1).
|
|
46
|
+
- Allow lock name to be integer
|
|
47
|
+
- Jruby support
|
|
48
|
+
- Truffleruby support
|
|
49
|
+
- Add `with_advisory_lock!`, which raises an error if the lock acquisition fails
|
|
50
|
+
- Add `disable_query_cache` option to `with_advisory_lock`
|
|
51
|
+
- Drop support for mysql < 5.7.5
|
|
52
|
+
|
|
3
53
|
### 4.6.0
|
|
4
54
|
|
|
5
55
|
- Support for ActiveRecord 6
|
data/Gemfile
CHANGED
|
@@ -1,15 +1,3 @@
|
|
|
1
1
|
source 'https://rubygems.org'
|
|
2
2
|
|
|
3
3
|
gemspec
|
|
4
|
-
|
|
5
|
-
platforms :ruby do
|
|
6
|
-
gem 'mysql2'
|
|
7
|
-
gem 'pg'
|
|
8
|
-
gem 'sqlite3'
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
platforms :jruby do
|
|
12
|
-
gem 'activerecord-jdbcmysql-adapter'
|
|
13
|
-
gem 'activerecord-jdbcpostgresql-adapter'
|
|
14
|
-
gem 'activerecord-jdbcsqlite3-adapter'
|
|
15
|
-
end
|
data/LICENSE.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
SPDX-License-Identifier: MIT
|
|
2
|
+
SPDX-FileCopyrightText: 2013 Matthew McEachen
|
|
3
|
+
SPDX-FileCopyrightText: 2013-2025 Abdelkader Boudih
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
6
|
a copy of this software and associated documentation files (the
|
|
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
19
19
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
20
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
21
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Makefile
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
.PHONY: test-pg test-mysql
|
|
2
|
+
|
|
3
|
+
test-pg:
|
|
4
|
+
docker compose up -d pg
|
|
5
|
+
sleep 10 # give some time for the service to start
|
|
6
|
+
DATABASE_URL=postgres://with_advisory:with_advisory_pass@localhost/with_advisory_lock_test appraisal rake test
|
|
7
|
+
|
|
8
|
+
test-mysql:
|
|
9
|
+
docker compose up -d mysql
|
|
10
|
+
sleep 10 # give some time for the service to start
|
|
11
|
+
DATABASE_URL=mysql2://with_advisory:with_advisory_pass@0.0.0.0:3306/with_advisory_lock_test appraisal rake test
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
test: test-pg test-mysql
|
data/README.md
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
# with_advisory_lock
|
|
2
2
|
|
|
3
|
-
Adds advisory locking (mutexes) to ActiveRecord
|
|
4
|
-
2.4, 2.5 and 2.6, when used with
|
|
3
|
+
Adds advisory locking (mutexes) to ActiveRecord 6.0+, with ruby 2.7+, jruby or truffleruby, when used with
|
|
5
4
|
[MySQL](https://dev.mysql.com/doc/refman/8.0/en/miscellaneous-functions.html#function_get-lock)
|
|
6
5
|
or
|
|
7
6
|
[PostgreSQL](https://www.postgresql.org/docs/current/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS).
|
|
8
7
|
SQLite resorts to file locking.
|
|
9
8
|
|
|
10
|
-
[](https://travis-ci.org/ClosureTree/with_advisory_lock)
|
|
11
9
|
[](https://badge.fury.io/rb/with_advisory_lock)
|
|
10
|
+
[](https://github.com/ClosureTree/with_advisory_lock/actions/workflows/ci.yml)
|
|
12
11
|
|
|
13
12
|
## What's an "Advisory Lock"?
|
|
14
13
|
|
|
@@ -45,8 +44,10 @@ A value of zero will try the lock only once. If the lock is acquired, the block
|
|
|
45
44
|
will be yielded to. If the lock is currently being held, the block will not be
|
|
46
45
|
called.
|
|
47
46
|
|
|
48
|
-
Note
|
|
49
|
-
|
|
47
|
+
> **Note**
|
|
48
|
+
>
|
|
49
|
+
> If a non-nil value is provided for `timeout_seconds`, the block will
|
|
50
|
+
*not* be invoked if the lock cannot be acquired within that time-frame. In this case, `with_advisory_lock` will return `false`, while `with_advisory_lock!` will raise a `WithAdvisoryLock::FailedToAcquireLock` error.
|
|
50
51
|
|
|
51
52
|
For backwards compatability, the timeout value can be specified directly as the
|
|
52
53
|
second parameter.
|
|
@@ -80,6 +81,8 @@ block, if the lock was able to be acquired and the block yielded, or `false`, if
|
|
|
80
81
|
you provided a timeout_seconds value and the lock was not able to be acquired in
|
|
81
82
|
time.
|
|
82
83
|
|
|
84
|
+
`with_advisory_lock!` is similar to `with_advisory_lock`, but raises a `WithAdvisoryLock::FailedToAcquireLock` error if the lock was not able to be acquired in time.
|
|
85
|
+
|
|
83
86
|
### Testing for the current lock status
|
|
84
87
|
|
|
85
88
|
If you needed to check if the advisory lock is currently being held, you can
|
|
@@ -91,6 +94,14 @@ If you want to see if the current Thread is holding a lock, you can call
|
|
|
91
94
|
`Tag.current_advisory_lock` which will return the name of the current lock. If
|
|
92
95
|
no lock is currently held, `.current_advisory_lock` returns `nil`.
|
|
93
96
|
|
|
97
|
+
### ActiveRecord Query Cache
|
|
98
|
+
|
|
99
|
+
You can optionally pass `disable_query_cache: true` to the options hash of
|
|
100
|
+
`with_advisory_lock` in order to disable ActiveRecord's query cache. This can
|
|
101
|
+
prevent problems when you query the database from within the lock and it returns
|
|
102
|
+
stale results. More info on why this can be a problem can be
|
|
103
|
+
[found here](https://github.com/ClosureTree/with_advisory_lock/issues/52)
|
|
104
|
+
|
|
94
105
|
## Installation
|
|
95
106
|
|
|
96
107
|
Add this line to your application's Gemfile:
|
|
@@ -123,7 +134,7 @@ row-level locks prevent concurrent modification to a given model.
|
|
|
123
134
|
|
|
124
135
|
**If you're building a
|
|
125
136
|
[CRUD](http://en.wikipedia.org/wiki/Create,_read,_update_and_delete)
|
|
126
|
-
application, this will be your most commonly used lock.**
|
|
137
|
+
application, this will be 2.4, 2.5 and your most commonly used lock.**
|
|
127
138
|
|
|
128
139
|
### Table-level locks
|
|
129
140
|
|
data/docker-compose.yml
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
version: "3.9"
|
|
2
|
+
services:
|
|
3
|
+
pg:
|
|
4
|
+
image: postgres:16
|
|
5
|
+
environment:
|
|
6
|
+
POSTGRES_USER: with_advisory
|
|
7
|
+
POSTGRES_PASSWORD: with_advisory_pass
|
|
8
|
+
POSTGRES_DB: with_advisory_lock_test
|
|
9
|
+
ports:
|
|
10
|
+
- "5432:5432"
|
|
11
|
+
mysql:
|
|
12
|
+
image: mysql:8
|
|
13
|
+
environment:
|
|
14
|
+
MYSQL_USER: with_advisory
|
|
15
|
+
MYSQL_PASSWORD: with_advisory_pass
|
|
16
|
+
MYSQL_DATABASE: with_advisory_lock_test
|
|
17
|
+
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
|
|
18
|
+
MYSQL_ROOT_HOST: '%'
|
|
19
|
+
ports:
|
|
20
|
+
- "3306:3306"
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
source "https://rubygems.org"
|
|
4
4
|
|
|
5
|
-
gem "activerecord", "~> 6.
|
|
5
|
+
gem "activerecord", "~> 6.1.0"
|
|
6
6
|
|
|
7
7
|
platforms :ruby do
|
|
8
|
+
gem "sqlite3"
|
|
8
9
|
gem "mysql2"
|
|
10
|
+
gem "trilogy"
|
|
11
|
+
gem "activerecord-trilogy-adapter"
|
|
9
12
|
gem "pg"
|
|
10
|
-
gem "sqlite3"
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
platforms :jruby do
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
source "https://rubygems.org"
|
|
4
4
|
|
|
5
|
-
gem "activerecord", "~>
|
|
5
|
+
gem "activerecord", "~> 7.0.0"
|
|
6
6
|
|
|
7
7
|
platforms :ruby do
|
|
8
|
+
gem "sqlite3"
|
|
8
9
|
gem "mysql2"
|
|
10
|
+
gem "trilogy"
|
|
11
|
+
gem "activerecord-trilogy-adapter"
|
|
9
12
|
gem "pg"
|
|
10
|
-
gem "sqlite3", "~> 1.3.6"
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
platforms :jruby do
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'zlib'
|
|
2
4
|
|
|
3
5
|
module WithAdvisoryLock
|
|
@@ -19,21 +21,22 @@ module WithAdvisoryLock
|
|
|
19
21
|
LockStackItem = Struct.new(:name, :shared)
|
|
20
22
|
|
|
21
23
|
class Base
|
|
22
|
-
attr_reader :connection, :lock_name, :timeout_seconds, :shared, :transaction
|
|
24
|
+
attr_reader :connection, :lock_name, :timeout_seconds, :shared, :transaction, :disable_query_cache
|
|
23
25
|
|
|
24
26
|
def initialize(connection, lock_name, options)
|
|
25
27
|
options = { timeout_seconds: options } unless options.respond_to?(:fetch)
|
|
26
|
-
options.assert_valid_keys :timeout_seconds, :shared, :transaction
|
|
28
|
+
options.assert_valid_keys :timeout_seconds, :shared, :transaction, :disable_query_cache
|
|
27
29
|
|
|
28
30
|
@connection = connection
|
|
29
31
|
@lock_name = lock_name
|
|
30
32
|
@timeout_seconds = options.fetch(:timeout_seconds, nil)
|
|
31
33
|
@shared = options.fetch(:shared, false)
|
|
32
34
|
@transaction = options.fetch(:transaction, false)
|
|
35
|
+
@disable_query_cache = options.fetch(:disable_query_cache, false)
|
|
33
36
|
end
|
|
34
37
|
|
|
35
38
|
def lock_str
|
|
36
|
-
@lock_str ||= "#{ENV[
|
|
39
|
+
@lock_str ||= "#{ENV[LOCK_PREFIX_ENV]}#{lock_name}"
|
|
37
40
|
end
|
|
38
41
|
|
|
39
42
|
def lock_stack_item
|
|
@@ -51,6 +54,16 @@ module WithAdvisoryLock
|
|
|
51
54
|
end
|
|
52
55
|
|
|
53
56
|
def with_advisory_lock_if_needed(&block)
|
|
57
|
+
if disable_query_cache
|
|
58
|
+
return lock_and_yield do
|
|
59
|
+
connection.uncached(&block)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
lock_and_yield(&block)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def lock_and_yield(&block)
|
|
54
67
|
if already_locked?
|
|
55
68
|
Result.new(true, yield)
|
|
56
69
|
elsif timeout_seconds == 0
|
|
@@ -66,7 +79,7 @@ module WithAdvisoryLock
|
|
|
66
79
|
else
|
|
67
80
|
# Ruby MRI's String#hash is randomly seeded as of Ruby 1.9 so
|
|
68
81
|
# make sure we use a deterministic hash.
|
|
69
|
-
Zlib.crc32(input.to_s)
|
|
82
|
+
Zlib.crc32(input.to_s, 0)
|
|
70
83
|
end
|
|
71
84
|
end
|
|
72
85
|
|
|
@@ -75,6 +88,7 @@ module WithAdvisoryLock
|
|
|
75
88
|
while @timeout_seconds.nil? || Time.now < give_up_at
|
|
76
89
|
r = yield_with_lock(&block)
|
|
77
90
|
return r if r.lock_was_acquired?
|
|
91
|
+
|
|
78
92
|
# Randomizing sleep time may help reduce contention.
|
|
79
93
|
sleep(rand(0.05..0.15))
|
|
80
94
|
end
|