with_advisory_lock 5.0.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/.release-please-manifest.json +1 -0
- data/.ruby-version +2 -0
- data/.tool-versions +1 -1
- data/CHANGELOG.md +41 -0
- data/LICENSE.txt +4 -4
- data/Makefile +14 -0
- data/docker-compose.yml +20 -0
- data/lib/with_advisory_lock/base.rb +3 -3
- data/lib/with_advisory_lock/concern.rb +5 -5
- data/lib/with_advisory_lock/database_adapter_support.rb +5 -8
- data/lib/with_advisory_lock/failed_to_acquire_lock.rb +3 -1
- data/lib/with_advisory_lock/mysql.rb +8 -3
- data/lib/with_advisory_lock/postgresql.rb +38 -15
- data/lib/with_advisory_lock/version.rb +1 -1
- data/lib/with_advisory_lock.rb +9 -9
- data/release-please-config.json +9 -0
- data/test/test_helper.rb +20 -6
- data/test/test_models.rb +8 -4
- data/test/with_advisory_lock/base_test.rb +9 -0
- data/test/{concern_test.rb → with_advisory_lock/concern_test.rb} +2 -2
- data/test/{lock_test.rb → with_advisory_lock/lock_test.rb} +31 -0
- data/test/{parallelism_test.rb → with_advisory_lock/parallelism_test.rb} +3 -3
- data/test/{shared_test.rb → with_advisory_lock/shared_test.rb} +2 -2
- data/test/{thread_test.rb → with_advisory_lock/thread_test.rb} +2 -2
- data/test/{transaction_test.rb → with_advisory_lock/transaction_test.rb} +1 -1
- data/with_advisory_lock.gemspec +7 -2
- metadata +49 -24
- data/.github/workflows/ci.yml +0 -80
- /data/test/{nesting_test.rb → with_advisory_lock/nesting_test.rb} +0 -0
- /data/test/{options_test.rb → with_advisory_lock/options_test.rb} +0 -0
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
|
@@ -0,0 +1 @@
|
|
1
|
+
{".":"5.3.0"}
|
data/.ruby-version
ADDED
data/.tool-versions
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby 3.
|
1
|
+
ruby 3.4.4
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,46 @@
|
|
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
|
+
|
3
44
|
### 5.0.0
|
4
45
|
- Drop support for EOL rubies and activerecord (ruby below 2.7 and activerecord below 6.1).
|
5
46
|
- Allow lock name to be integer
|
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/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"
|
@@ -36,7 +36,7 @@ module WithAdvisoryLock
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def lock_str
|
39
|
-
@lock_str ||= "#{ENV[
|
39
|
+
@lock_str ||= "#{ENV[LOCK_PREFIX_ENV]}#{lock_name}"
|
40
40
|
end
|
41
41
|
|
42
42
|
def lock_stack_item
|
@@ -56,7 +56,7 @@ module WithAdvisoryLock
|
|
56
56
|
def with_advisory_lock_if_needed(&block)
|
57
57
|
if disable_query_cache
|
58
58
|
return lock_and_yield do
|
59
|
-
|
59
|
+
connection.uncached(&block)
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
@@ -79,7 +79,7 @@ module WithAdvisoryLock
|
|
79
79
|
else
|
80
80
|
# Ruby MRI's String#hash is randomly seeded as of Ruby 1.9 so
|
81
81
|
# make sure we use a deterministic hash.
|
82
|
-
Zlib.crc32(input.to_s)
|
82
|
+
Zlib.crc32(input.to_s, 0)
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/concern'
|
4
|
-
|
5
3
|
module WithAdvisoryLock
|
6
4
|
module Concern
|
7
5
|
extend ActiveSupport::Concern
|
@@ -15,9 +13,7 @@ module WithAdvisoryLock
|
|
15
13
|
|
16
14
|
def with_advisory_lock!(lock_name, options = {}, &block)
|
17
15
|
result = with_advisory_lock_result(lock_name, options, &block)
|
18
|
-
unless result.lock_was_acquired?
|
19
|
-
raise WithAdvisoryLock::FailedToAcquireLock, lock_name
|
20
|
-
end
|
16
|
+
raise WithAdvisoryLock::FailedToAcquireLock, lock_name unless result.lock_was_acquired?
|
21
17
|
|
22
18
|
result.result
|
23
19
|
end
|
@@ -37,6 +33,10 @@ module WithAdvisoryLock
|
|
37
33
|
lock_stack_key && lock_stack_key[0]
|
38
34
|
end
|
39
35
|
|
36
|
+
def current_advisory_locks
|
37
|
+
WithAdvisoryLock::Base.lock_stack.map(&:name)
|
38
|
+
end
|
39
|
+
|
40
40
|
private
|
41
41
|
|
42
42
|
def impl_class
|
@@ -2,25 +2,22 @@
|
|
2
2
|
|
3
3
|
module WithAdvisoryLock
|
4
4
|
class DatabaseAdapterSupport
|
5
|
-
|
6
|
-
@@mysql_nl_cache = {}
|
7
|
-
@@mysql_nl_cache_mutex = Mutex.new
|
8
|
-
|
5
|
+
attr_reader :adapter_name
|
9
6
|
def initialize(connection)
|
10
7
|
@connection = connection
|
11
|
-
@
|
8
|
+
@adapter_name = connection.adapter_name.downcase.to_sym
|
12
9
|
end
|
13
10
|
|
14
11
|
def mysql?
|
15
|
-
%i[mysql2 trilogy].include?
|
12
|
+
%i[mysql2 trilogy].include? adapter_name
|
16
13
|
end
|
17
14
|
|
18
15
|
def postgresql?
|
19
|
-
%i[postgresql empostgresql postgis].include?
|
16
|
+
%i[postgresql empostgresql postgis].include? adapter_name
|
20
17
|
end
|
21
18
|
|
22
19
|
def sqlite?
|
23
|
-
|
20
|
+
[:sqlite3, :sqlite].include? adapter_name
|
24
21
|
end
|
25
22
|
end
|
26
23
|
end
|
@@ -2,7 +2,8 @@
|
|
2
2
|
|
3
3
|
module WithAdvisoryLock
|
4
4
|
class MySQL < Base
|
5
|
-
# See https://dev.mysql.com/doc/refman/5.7/en/
|
5
|
+
# See https://dev.mysql.com/doc/refman/5.7/en/locking-functions.html
|
6
|
+
# See https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html
|
6
7
|
def try_lock
|
7
8
|
raise ArgumentError, 'shared locks are not supported on MySQL' if shared
|
8
9
|
raise ArgumentError, 'transaction level locks are not supported on MySQL' if transaction
|
@@ -15,8 +16,12 @@ module WithAdvisoryLock
|
|
15
16
|
end
|
16
17
|
|
17
18
|
def execute_successful?(mysql_function)
|
18
|
-
|
19
|
-
|
19
|
+
execute_query(mysql_function) == 1
|
20
|
+
end
|
21
|
+
|
22
|
+
def execute_query(mysql_function)
|
23
|
+
sql = "SELECT #{mysql_function}"
|
24
|
+
connection.query_value(sql)
|
20
25
|
end
|
21
26
|
|
22
27
|
# MySQL wants a string as the lock key.
|
@@ -2,42 +2,65 @@
|
|
2
2
|
|
3
3
|
module WithAdvisoryLock
|
4
4
|
class PostgreSQL < Base
|
5
|
-
# See
|
5
|
+
# See https://www.postgresql.org/docs/16/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS
|
6
|
+
|
7
|
+
# MRI returns 't', jruby returns true. YAY!
|
8
|
+
LOCK_RESULT_VALUES = ['t', true].freeze
|
9
|
+
PG_ADVISORY_UNLOCK = 'pg_advisory_unlock'
|
10
|
+
PG_TRY_ADVISORY = 'pg_try_advisory'
|
11
|
+
ERROR_MESSAGE_REGEX = / ERROR: +current transaction is aborted,/
|
12
|
+
|
6
13
|
def try_lock
|
7
|
-
|
8
|
-
execute_successful?(pg_function)
|
14
|
+
execute_successful?(advisory_try_lock_function(transaction))
|
9
15
|
end
|
10
16
|
|
11
17
|
def release_lock
|
12
18
|
return if transaction
|
13
19
|
|
14
|
-
|
15
|
-
execute_successful?(pg_function)
|
20
|
+
execute_successful?(advisory_unlock_function)
|
16
21
|
rescue ActiveRecord::StatementInvalid => e
|
17
|
-
raise unless e.message =~
|
22
|
+
raise unless e.message =~ ERROR_MESSAGE_REGEX
|
18
23
|
|
19
24
|
begin
|
20
25
|
connection.rollback_db_transaction
|
21
|
-
execute_successful?(
|
26
|
+
execute_successful?(advisory_unlock_function)
|
22
27
|
ensure
|
23
28
|
connection.begin_db_transaction
|
24
29
|
end
|
25
30
|
end
|
26
31
|
|
32
|
+
def advisory_try_lock_function(transaction_scope)
|
33
|
+
[
|
34
|
+
'pg_try_advisory',
|
35
|
+
transaction_scope ? '_xact' : nil,
|
36
|
+
'_lock',
|
37
|
+
shared ? '_shared' : nil
|
38
|
+
].compact.join
|
39
|
+
end
|
40
|
+
|
41
|
+
def advisory_unlock_function
|
42
|
+
[
|
43
|
+
'pg_advisory_unlock',
|
44
|
+
shared ? '_shared' : nil
|
45
|
+
].compact.join
|
46
|
+
end
|
47
|
+
|
27
48
|
def execute_successful?(pg_function)
|
49
|
+
result = connection.select_value(prepare_sql(pg_function))
|
50
|
+
LOCK_RESULT_VALUES.include?(result)
|
51
|
+
end
|
52
|
+
|
53
|
+
def prepare_sql(pg_function)
|
28
54
|
comment = lock_name.to_s.gsub(%r{(/\*)|(\*/)}, '--')
|
29
|
-
|
30
|
-
result = connection.select_value(sql)
|
31
|
-
# MRI returns 't', jruby returns true. YAY!
|
32
|
-
['t', true].include?(result)
|
55
|
+
"SELECT #{pg_function}(#{lock_keys.join(',')}) AS #{unique_column_name} /* #{comment} */"
|
33
56
|
end
|
34
57
|
|
35
58
|
# PostgreSQL wants 2 32bit integers as the lock key.
|
36
59
|
def lock_keys
|
37
|
-
@lock_keys ||= [
|
38
|
-
|
39
|
-
|
40
|
-
|
60
|
+
@lock_keys ||= [
|
61
|
+
stable_hashcode(lock_name),
|
62
|
+
ENV[LOCK_PREFIX_ENV]
|
63
|
+
].map { |ea| ea.to_i & 0x7fffffff }
|
41
64
|
end
|
42
65
|
end
|
43
66
|
end
|
data/lib/with_advisory_lock.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
require 'with_advisory_lock/version'
|
2
2
|
require 'active_support'
|
3
|
-
|
3
|
+
require 'zeitwerk'
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
loader = Zeitwerk::Loader.for_gem
|
6
|
+
loader.inflector.inflect(
|
7
|
+
'mysql' => 'MySQL',
|
8
|
+
'postgresql' => 'PostgreSQL',
|
9
|
+
)
|
10
|
+
loader.setup
|
7
11
|
|
8
|
-
|
9
|
-
|
10
|
-
autoload :DatabaseAdapterSupport
|
11
|
-
autoload :Flock
|
12
|
-
autoload :MySQL, 'with_advisory_lock/mysql'
|
13
|
-
autoload :PostgreSQL, 'with_advisory_lock/postgresql'
|
12
|
+
module WithAdvisoryLock
|
13
|
+
LOCK_PREFIX_ENV = 'WITH_ADVISORY_LOCK_PREFIX'.freeze
|
14
14
|
end
|
15
15
|
|
16
16
|
ActiveSupport.on_load :active_record do
|
data/test/test_helper.rb
CHANGED
@@ -17,7 +17,8 @@ end
|
|
17
17
|
|
18
18
|
ActiveRecord::Base.configurations = {
|
19
19
|
default_env: {
|
20
|
-
url: ENV.fetch('DATABASE_URL', "sqlite3://#{Dir.tmpdir}
|
20
|
+
url: ENV.fetch('DATABASE_URL', "sqlite3://#{Dir.tmpdir}/with_advisory_lock_test#{RUBY_VERSION}-#{ActiveRecord.gem_version}.sqlite3"),
|
21
|
+
pool: 20,
|
21
22
|
properties: { allowPublicKeyRetrieval: true } # for JRuby madness
|
22
23
|
}
|
23
24
|
}
|
@@ -38,15 +39,28 @@ require 'maxitest/autorun'
|
|
38
39
|
require 'mocha/minitest'
|
39
40
|
|
40
41
|
class GemTestCase < ActiveSupport::TestCase
|
42
|
+
|
43
|
+
parallelize(workers: 1)
|
44
|
+
def adapter_support
|
45
|
+
@adapter_support ||= WithAdvisoryLock::DatabaseAdapterSupport.new(ActiveRecord::Base.connection)
|
46
|
+
end
|
47
|
+
def is_sqlite3_adapter?; adapter_support.sqlite?; end
|
48
|
+
def is_mysql_adapter?; adapter_support.mysql?; end
|
49
|
+
def is_postgresql_adapter?; adapter_support.postgresql?; end
|
50
|
+
|
41
51
|
setup do
|
42
|
-
ENV['FLOCK_DIR'] = Dir.mktmpdir
|
43
|
-
|
44
|
-
|
45
|
-
|
52
|
+
ENV['FLOCK_DIR'] = Dir.mktmpdir if is_sqlite3_adapter?
|
53
|
+
ApplicationRecord.connection.truncate_tables(
|
54
|
+
Tag.table_name,
|
55
|
+
TagAudit.table_name,
|
56
|
+
Label.table_name
|
57
|
+
)
|
46
58
|
end
|
59
|
+
|
47
60
|
teardown do
|
48
|
-
FileUtils.remove_entry_secure
|
61
|
+
FileUtils.remove_entry_secure(ENV['FLOCK_DIR'], true) if is_sqlite3_adapter?
|
49
62
|
end
|
50
63
|
end
|
51
64
|
|
52
65
|
puts "Testing with #{env_db} database, ActiveRecord #{ActiveRecord.gem_version} and #{RUBY_ENGINE} #{RUBY_ENGINE_VERSION} as #{RUBY_VERSION}"
|
66
|
+
puts "Connection Pool size: #{ActiveRecord::Base.connection_pool.size}"
|
data/test/test_models.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
ActiveRecord::Schema.define(version:
|
3
|
+
ActiveRecord::Schema.define(version: 1) do
|
4
4
|
create_table 'tags', force: true do |t|
|
5
5
|
t.string 'name'
|
6
6
|
end
|
@@ -12,15 +12,19 @@ ActiveRecord::Schema.define(version: 0) do
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
class
|
15
|
+
class ApplicationRecord < ActiveRecord::Base
|
16
|
+
self.abstract_class = true
|
17
|
+
end
|
18
|
+
|
19
|
+
class Tag < ApplicationRecord
|
16
20
|
after_save do
|
17
21
|
TagAudit.create(tag_name: name)
|
18
22
|
Label.create(name: name)
|
19
23
|
end
|
20
24
|
end
|
21
25
|
|
22
|
-
class TagAudit <
|
26
|
+
class TagAudit < ApplicationRecord
|
23
27
|
end
|
24
28
|
|
25
|
-
class Label <
|
29
|
+
class Label < ApplicationRecord
|
26
30
|
end
|
@@ -22,12 +22,12 @@ end
|
|
22
22
|
|
23
23
|
class ActiveRecordQueryCacheTest < GemTestCase
|
24
24
|
test 'does not disable quary cache by default' do
|
25
|
-
|
25
|
+
Tag.connection.expects(:uncached).never
|
26
26
|
Tag.with_advisory_lock('lock') { Tag.first }
|
27
27
|
end
|
28
28
|
|
29
29
|
test 'can disable ActiveRecord query cache' do
|
30
|
-
|
30
|
+
Tag.connection.expects(:uncached).once
|
31
31
|
Tag.with_advisory_lock('a-lock', disable_query_cache: true) { Tag.first }
|
32
32
|
end
|
33
33
|
end
|
@@ -77,4 +77,35 @@ class LockTest < GemTestCase
|
|
77
77
|
|
78
78
|
assert_equal(expected, actual)
|
79
79
|
end
|
80
|
+
|
81
|
+
test 'current_advisory_locks returns empty array outside an advisory lock request' do
|
82
|
+
assert_equal([], Tag.current_advisory_locks)
|
83
|
+
end
|
84
|
+
|
85
|
+
test 'current_advisory_locks returns an array with names of the acquired locks' do
|
86
|
+
Tag.with_advisory_lock(@lock_name) do
|
87
|
+
locks = Tag.current_advisory_locks
|
88
|
+
assert_equal(1, locks.size)
|
89
|
+
assert_match(/#{@lock_name}/, locks.first)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
test 'current_advisory_locks returns array of all nested lock names' do
|
94
|
+
first_lock = 'outer lock'
|
95
|
+
second_lock = 'inner lock'
|
96
|
+
|
97
|
+
Tag.with_advisory_lock(first_lock) do
|
98
|
+
Tag.with_advisory_lock(second_lock) do
|
99
|
+
locks = Tag.current_advisory_locks
|
100
|
+
assert_equal(2, locks.size)
|
101
|
+
assert_match(/#{first_lock}/, locks.first)
|
102
|
+
assert_match(/#{second_lock}/, locks.last)
|
103
|
+
end
|
104
|
+
|
105
|
+
locks = Tag.current_advisory_locks
|
106
|
+
assert_equal(1, locks.size)
|
107
|
+
assert_match(/#{first_lock}/, locks.first)
|
108
|
+
end
|
109
|
+
assert_equal([], Tag.current_advisory_locks)
|
110
|
+
end
|
80
111
|
end
|
@@ -15,7 +15,7 @@ class FindOrCreateWorker
|
|
15
15
|
|
16
16
|
def work_later
|
17
17
|
sleep
|
18
|
-
|
18
|
+
ApplicationRecord.connection_pool.with_connection do
|
19
19
|
if @use_advisory_lock
|
20
20
|
Tag.with_advisory_lock(@name) { work }
|
21
21
|
else
|
@@ -46,11 +46,11 @@ class ParallelismTest < GemTestCase
|
|
46
46
|
workers.each(&:join)
|
47
47
|
end
|
48
48
|
# Ensure we're still connected:
|
49
|
-
|
49
|
+
ApplicationRecord.connection_pool.connection
|
50
50
|
end
|
51
51
|
|
52
52
|
setup do
|
53
|
-
|
53
|
+
ApplicationRecord.connection.reconnect!
|
54
54
|
@workers = 10
|
55
55
|
end
|
56
56
|
|
@@ -24,7 +24,7 @@ class SharedTestWorker
|
|
24
24
|
private
|
25
25
|
|
26
26
|
def work
|
27
|
-
|
27
|
+
Tag.connection_pool.with_connection do
|
28
28
|
Tag.with_advisory_lock('test', timeout_seconds: 0, shared: @shared) do
|
29
29
|
@locked = true
|
30
30
|
sleep 0.01 until @cleanup
|
@@ -117,7 +117,7 @@ class SupportedEnvironmentTest < SharedLocksTest
|
|
117
117
|
end
|
118
118
|
|
119
119
|
def pg_lock_modes
|
120
|
-
|
120
|
+
Tag.connection.select_values("SELECT mode FROM pg_locks WHERE locktype = 'advisory';")
|
121
121
|
end
|
122
122
|
|
123
123
|
test 'allows shared lock to be upgraded to an exclusive lock' do
|
@@ -10,7 +10,7 @@ class SeparateThreadTest < GemTestCase
|
|
10
10
|
@t1_return_value = nil
|
11
11
|
|
12
12
|
@t1 = Thread.new do
|
13
|
-
|
13
|
+
Label.connection_pool.with_connection do
|
14
14
|
@t1_return_value = Label.with_advisory_lock(@lock_name) do
|
15
15
|
@mutex.synchronize { @t1_acquired_lock = true }
|
16
16
|
sleep
|
@@ -21,7 +21,7 @@ class SeparateThreadTest < GemTestCase
|
|
21
21
|
|
22
22
|
# Wait for the thread to acquire the lock:
|
23
23
|
sleep(0.1) until @mutex.synchronize { @t1_acquired_lock }
|
24
|
-
|
24
|
+
Label.connection.reconnect!
|
25
25
|
end
|
26
26
|
|
27
27
|
teardown do
|
@@ -25,7 +25,7 @@ class TransactionScopingTest < GemTestCase
|
|
25
25
|
setup do
|
26
26
|
skip unless env_db == :postgresql
|
27
27
|
@pg_lock_count = lambda do
|
28
|
-
|
28
|
+
ApplicationRecord.connection.select_value("SELECT COUNT(*) FROM pg_locks WHERE locktype = 'advisory';").to_i
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
data/with_advisory_lock.gemspec
CHANGED
@@ -16,11 +16,16 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
17
17
|
spec.test_files = spec.files.grep(%r{^test/})
|
18
18
|
spec.require_paths = %w[lib]
|
19
|
-
spec.metadata = {
|
19
|
+
spec.metadata = { 'rubygems_mfa_required' => 'true' }
|
20
20
|
spec.required_ruby_version = '>= 2.7.0'
|
21
|
-
spec.metadata[
|
21
|
+
spec.metadata['yard.run'] = 'yri'
|
22
|
+
|
23
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
24
|
+
spec.metadata['source_code_uri'] = 'https://github.com/ClosureTree/with_advisory_lock'
|
25
|
+
spec.metadata['changelog_uri'] = 'https://github.com/ClosureTree/with_advisory_lock/blob/master/CHANGELOG.md'
|
22
26
|
|
23
27
|
spec.add_runtime_dependency 'activerecord', '>= 6.1'
|
28
|
+
spec.add_runtime_dependency 'zeitwerk', '>= 2.6'
|
24
29
|
|
25
30
|
spec.add_development_dependency 'appraisal'
|
26
31
|
spec.add_development_dependency 'maxitest'
|
metadata
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: with_advisory_lock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew McEachen
|
8
8
|
- Abdelkader Boudih
|
9
|
-
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: activerecord
|
@@ -25,6 +24,20 @@ dependencies:
|
|
25
24
|
- - ">="
|
26
25
|
- !ruby/object:Gem::Version
|
27
26
|
version: '6.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: zeitwerk
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.6'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.6'
|
28
41
|
- !ruby/object:Gem::Dependency
|
29
42
|
name: appraisal
|
30
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -103,15 +116,23 @@ executables: []
|
|
103
116
|
extensions: []
|
104
117
|
extra_rdoc_files: []
|
105
118
|
files:
|
106
|
-
- ".github/workflows/ci.yml"
|
119
|
+
- ".github/workflows/ci-mysql5.yml"
|
120
|
+
- ".github/workflows/ci-mysql8.yml"
|
121
|
+
- ".github/workflows/ci-postgresql.yml"
|
122
|
+
- ".github/workflows/ci-sqlite3.yml"
|
123
|
+
- ".github/workflows/release.yml"
|
107
124
|
- ".gitignore"
|
125
|
+
- ".release-please-manifest.json"
|
126
|
+
- ".ruby-version"
|
108
127
|
- ".tool-versions"
|
109
128
|
- Appraisals
|
110
129
|
- CHANGELOG.md
|
111
130
|
- Gemfile
|
112
131
|
- LICENSE.txt
|
132
|
+
- Makefile
|
113
133
|
- README.md
|
114
134
|
- Rakefile
|
135
|
+
- docker-compose.yml
|
115
136
|
- gemfiles/activerecord_6.1.gemfile
|
116
137
|
- gemfiles/activerecord_7.0.gemfile
|
117
138
|
- gemfiles/activerecord_7.1.gemfile
|
@@ -124,24 +145,28 @@ files:
|
|
124
145
|
- lib/with_advisory_lock/mysql.rb
|
125
146
|
- lib/with_advisory_lock/postgresql.rb
|
126
147
|
- lib/with_advisory_lock/version.rb
|
127
|
-
-
|
128
|
-
- test/lock_test.rb
|
129
|
-
- test/nesting_test.rb
|
130
|
-
- test/options_test.rb
|
131
|
-
- test/parallelism_test.rb
|
132
|
-
- test/shared_test.rb
|
148
|
+
- release-please-config.json
|
133
149
|
- test/test_helper.rb
|
134
150
|
- test/test_models.rb
|
135
|
-
- test/
|
136
|
-
- test/
|
151
|
+
- test/with_advisory_lock/base_test.rb
|
152
|
+
- test/with_advisory_lock/concern_test.rb
|
153
|
+
- test/with_advisory_lock/lock_test.rb
|
154
|
+
- test/with_advisory_lock/nesting_test.rb
|
155
|
+
- test/with_advisory_lock/options_test.rb
|
156
|
+
- test/with_advisory_lock/parallelism_test.rb
|
157
|
+
- test/with_advisory_lock/shared_test.rb
|
158
|
+
- test/with_advisory_lock/thread_test.rb
|
159
|
+
- test/with_advisory_lock/transaction_test.rb
|
137
160
|
- with_advisory_lock.gemspec
|
138
161
|
homepage: https://github.com/ClosureTree/with_advisory_lock
|
139
162
|
licenses:
|
140
163
|
- MIT
|
141
164
|
metadata:
|
142
|
-
|
165
|
+
rubygems_mfa_required: 'true'
|
143
166
|
yard.run: yri
|
144
|
-
|
167
|
+
homepage_uri: https://github.com/ClosureTree/with_advisory_lock
|
168
|
+
source_code_uri: https://github.com/ClosureTree/with_advisory_lock
|
169
|
+
changelog_uri: https://github.com/ClosureTree/with_advisory_lock/blob/master/CHANGELOG.md
|
145
170
|
rdoc_options: []
|
146
171
|
require_paths:
|
147
172
|
- lib
|
@@ -156,18 +181,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
181
|
- !ruby/object:Gem::Version
|
157
182
|
version: '0'
|
158
183
|
requirements: []
|
159
|
-
rubygems_version: 3.
|
160
|
-
signing_key:
|
184
|
+
rubygems_version: 3.6.7
|
161
185
|
specification_version: 4
|
162
186
|
summary: Advisory locking for ActiveRecord
|
163
187
|
test_files:
|
164
|
-
- test/concern_test.rb
|
165
|
-
- test/lock_test.rb
|
166
|
-
- test/nesting_test.rb
|
167
|
-
- test/options_test.rb
|
168
|
-
- test/parallelism_test.rb
|
169
|
-
- test/shared_test.rb
|
170
188
|
- test/test_helper.rb
|
171
189
|
- test/test_models.rb
|
172
|
-
- test/
|
173
|
-
- test/
|
190
|
+
- test/with_advisory_lock/base_test.rb
|
191
|
+
- test/with_advisory_lock/concern_test.rb
|
192
|
+
- test/with_advisory_lock/lock_test.rb
|
193
|
+
- test/with_advisory_lock/nesting_test.rb
|
194
|
+
- test/with_advisory_lock/options_test.rb
|
195
|
+
- test/with_advisory_lock/parallelism_test.rb
|
196
|
+
- test/with_advisory_lock/shared_test.rb
|
197
|
+
- test/with_advisory_lock/thread_test.rb
|
198
|
+
- test/with_advisory_lock/transaction_test.rb
|
data/.github/workflows/ci.yml
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
---
|
2
|
-
name: CI
|
3
|
-
|
4
|
-
on:
|
5
|
-
pull_request:
|
6
|
-
branches:
|
7
|
-
- master
|
8
|
-
|
9
|
-
jobs:
|
10
|
-
minitest:
|
11
|
-
runs-on: ubuntu-latest
|
12
|
-
services:
|
13
|
-
mysql:
|
14
|
-
image: mysql/mysql-server:5.7
|
15
|
-
ports:
|
16
|
-
- "3306:3306"
|
17
|
-
env:
|
18
|
-
MYSQL_ROOT_PASSWORD: root
|
19
|
-
MYSQL_DATABASE: with_advisory_lock_test
|
20
|
-
MYSQL_ROOT_HOST: '%'
|
21
|
-
postgres:
|
22
|
-
image: 'postgres:14-alpine'
|
23
|
-
ports: ['5432:5432']
|
24
|
-
env:
|
25
|
-
POSTGRES_USER: closure_tree
|
26
|
-
POSTGRES_PASSWORD: closure_tree
|
27
|
-
POSTGRES_DB: with_advisory_lock_test
|
28
|
-
options: >-
|
29
|
-
--health-cmd pg_isready
|
30
|
-
--health-interval 10s
|
31
|
-
--health-timeout 5s
|
32
|
-
--health-retries 5
|
33
|
-
|
34
|
-
strategy:
|
35
|
-
fail-fast: false
|
36
|
-
matrix:
|
37
|
-
ruby:
|
38
|
-
- '3.2'
|
39
|
-
- '3.1'
|
40
|
-
- '3.0'
|
41
|
-
- '2.7'
|
42
|
-
- 'truffleruby'
|
43
|
-
rails:
|
44
|
-
- activerecord_7.1
|
45
|
-
- activerecord_7.0
|
46
|
-
- activerecord_6.1
|
47
|
-
adapter:
|
48
|
-
- sqlite3:///tmp/test.sqlite3
|
49
|
-
- mysql2://root:root@0/with_advisory_lock_test
|
50
|
-
- trilogy://root:root@0/with_advisory_lock_test
|
51
|
-
- postgres://closure_tree:closure_tree@0/with_advisory_lock_test
|
52
|
-
include:
|
53
|
-
- ruby: jruby
|
54
|
-
rails: activerecord_6.1
|
55
|
-
adapter: jdbcmysql://root:root@0/with_advisory_lock_test
|
56
|
-
- ruby: jruby
|
57
|
-
rails: activerecord_6.1
|
58
|
-
adapter: jdbcsqlite3:///tmp/test.sqlite3
|
59
|
-
- ruby: jruby
|
60
|
-
rails: activerecord_6.1
|
61
|
-
adapter: jdbcpostgresql://closure_tree:closure_tree@0/with_advisory_lock_test
|
62
|
-
steps:
|
63
|
-
- name: Checkout
|
64
|
-
uses: actions/checkout@v4
|
65
|
-
|
66
|
-
- name: Setup Ruby
|
67
|
-
uses: ruby/setup-ruby@v1
|
68
|
-
with:
|
69
|
-
ruby-version: ${{ matrix.ruby }}
|
70
|
-
bundler-cache: true
|
71
|
-
rubygems: latest
|
72
|
-
env:
|
73
|
-
BUNDLE_GEMFILE: gemfiles/${{ matrix.rails }}.gemfile
|
74
|
-
|
75
|
-
- name: Test
|
76
|
-
env:
|
77
|
-
BUNDLE_GEMFILE: gemfiles/${{ matrix.rails }}.gemfile
|
78
|
-
DATABASE_URL: ${{ matrix.adapter }}
|
79
|
-
WITH_ADVISORY_LOCK_PREFIX: ${{ github.run_id }}
|
80
|
-
run: bundle exec rake
|
File without changes
|
File without changes
|