with_advisory_lock 4.0.0 → 5.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.
Files changed (40) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +80 -0
  3. data/.gitignore +3 -0
  4. data/.tool-versions +1 -0
  5. data/Appraisals +37 -11
  6. data/CHANGELOG.md +131 -0
  7. data/Gemfile +0 -12
  8. data/README.md +85 -171
  9. data/gemfiles/{activerecord_5.1.gemfile → activerecord_6.1.gemfile} +4 -2
  10. data/gemfiles/{activerecord_5.2.gemfile → activerecord_7.0.gemfile} +4 -2
  11. data/gemfiles/activerecord_7.1.gemfile +14 -0
  12. data/lib/with_advisory_lock/base.rb +16 -2
  13. data/lib/with_advisory_lock/concern.rb +13 -2
  14. data/lib/with_advisory_lock/database_adapter_support.rb +10 -3
  15. data/lib/with_advisory_lock/failed_to_acquire_lock.rb +7 -0
  16. data/lib/with_advisory_lock/flock.rb +4 -3
  17. data/lib/with_advisory_lock/mysql.rb +6 -16
  18. data/lib/with_advisory_lock/postgresql.rb +9 -7
  19. data/lib/with_advisory_lock/version.rb +3 -1
  20. data/lib/with_advisory_lock.rb +1 -1
  21. data/test/concern_test.rb +23 -10
  22. data/test/lock_test.rb +61 -28
  23. data/test/nesting_test.rb +14 -46
  24. data/test/options_test.rb +35 -33
  25. data/test/parallelism_test.rb +35 -37
  26. data/test/shared_test.rb +93 -90
  27. data/test/test_helper.rb +52 -0
  28. data/test/test_models.rb +9 -7
  29. data/test/thread_test.rb +23 -22
  30. data/test/transaction_test.rb +34 -36
  31. data/with_advisory_lock.gemspec +24 -23
  32. metadata +27 -41
  33. data/.travis.install-mysql-5.7.sh +0 -11
  34. data/.travis.yml +0 -32
  35. data/gemfiles/activerecord_4.2.gemfile +0 -19
  36. data/gemfiles/activerecord_5.0.gemfile +0 -19
  37. data/lib/with_advisory_lock/nested_advisory_lock_error.rb +0 -14
  38. data/test/database.yml +0 -17
  39. data/test/minitest_helper.rb +0 -40
  40. data/tests.sh +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 82b0119f2158391cace745c0fa71a65497198de1
4
- data.tar.gz: eb7f626ed7db658000ad0db260a2692035ee4dc1
2
+ SHA256:
3
+ metadata.gz: 784812e261b5a57a5d3da8c878e536949245b29372b40b2baf15a52d7c65b854
4
+ data.tar.gz: ba2f6fc8bf78c89d56635c4f56500117f79a443404d3574d8b54b2a45d1811de
5
5
  SHA512:
6
- metadata.gz: efe96bf02dc09cf167ed2058c164405c4f6d6ae9e31442b46d9e9f5ceebc7add1850861d0b6bd311087a056cab5928ad27afa680a4b11884d1474bee4ae25269
7
- data.tar.gz: f9f753d910d24f6cb98fc91a47aed8dcccb82bf99f55ea193aceb8ffedf3c2732eef1c7945c64d1a5ac72aa27d89a0205307ddab72cce7113ca6c37c22496ac9
6
+ metadata.gz: bb7dc11c1f206639943daa363a4d917bfe93792e7db764c7860ef68151e99defaa03f58640fae0480b566e3d4a0697695f5b60ae8af09838bb176979c328d8ae
7
+ data.tar.gz: 10132a0c47ed8070a0661a7b6ae0409be76ef14693be65c12a8e8cdd9c5a506ba25c60bda264f7c60bd92952e4cd4c5513a5e566a3e0d757f0ab6fc4311ffcd5
@@ -0,0 +1,80 @@
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
data/.gitignore CHANGED
@@ -17,3 +17,6 @@ spec/reports
17
17
  test/tmp
18
18
  test/version_tmp
19
19
  tmp
20
+ *.iml
21
+ test/sqlite.db
22
+ .env
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 3.0.5
data/Appraisals CHANGED
@@ -1,19 +1,45 @@
1
- appraise "activerecord-4.2" do
2
- gem "activerecord", "~> 4.2.0"
1
+ # frozen_string_literal: true
2
+
3
+ appraise 'activerecord-7.1' do
4
+ gem 'activerecord', '~> 7.1.0'
3
5
  platforms :ruby do
4
- gem "pg", "~> 0.21"
5
- gem "mysql2", "< 0.5"
6
+ gem 'sqlite3'
7
+ gem 'mysql2'
8
+ gem 'trilogy'
9
+ gem 'pg'
6
10
  end
7
11
  end
8
12
 
9
- appraise "activerecord-5.0" do
10
- gem "activerecord", "~> 5.0.0"
13
+ appraise 'activerecord-7.0' do
14
+ gem 'activerecord', '~> 7.0.0'
15
+ platforms :ruby do
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"
26
+ end
11
27
  end
12
28
 
13
- appraise "activerecord-5.1" do
14
- gem "activerecord", "~> 5.1.0"
29
+ appraise 'activerecord-6.1' do
30
+ gem 'activerecord', '~> 6.1.0'
31
+
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
15
44
  end
16
45
 
17
- appraise "activerecord-5.2" do
18
- gem "activerecord", "~> 5.1.0"
19
- end
data/CHANGELOG.md ADDED
@@ -0,0 +1,131 @@
1
+ ## Changelog
2
+
3
+ ### 5.0.0
4
+ - Drop support for EOL rubies and activerecord (ruby below 2.7 and activerecord below 6.1).
5
+ - Allow lock name to be integer
6
+ - Jruby support
7
+ - Truffleruby support
8
+ - Add `with_advisory_lock!`, which raises an error if the lock acquisition fails
9
+ - Add `disable_query_cache` option to `with_advisory_lock`
10
+ - Drop support for mysql < 5.7.5
11
+
12
+ ### 4.6.0
13
+
14
+ - Support for ActiveRecord 6
15
+ - Add Support for nested locks in MySQL
16
+
17
+ ### 4.0.0
18
+
19
+ - Drop support for unsupported versions of activerecord
20
+ - Drop support for unsupported versions of ruby
21
+
22
+ ### 3.2.0
23
+
24
+ - [Joshua Flanagan](https://github.com/joshuaflanagan) [added a SQL comment to the lock query for PostgreSQL](https://github.com/ClosureTree/with_advisory_lock/pull/28). Thanks!
25
+ - [Fernando Luizão](https://github.com/fernandoluizao) found a spurious requirement for `thread_safe`. Thanks for the [fix](https://github.com/ClosureTree/with_advisory_lock/pull/27)!
26
+
27
+ ### 3.1.1
28
+
29
+ - [Joel Turkel](https://github.com/jturkel) added `require 'active_support'` (it was required, but relied on downstream gems to pull in active_support before pulling in with_advisory_lock). Thanks!
30
+
31
+ ### 3.1.0
32
+
33
+ - [Jason Weathered](https://github.com/jasoncodes) Added new shared and transaction-level lock options ([Pull request 21](https://github.com/ClosureTree/with_advisory_lock/pull/21)). Thanks!
34
+ - Added ActiveRecord 5.0 to build matrix. Dropped 3.2, 4.0, and 4.1 (which no longer get security updates: http://rubyonrails.org/security/)
35
+ - Replaced ruby 1.9 and 2.0 (both EOL) with ruby 2.2 and 2.3 (see https://www.ruby-lang.org/en/downloads/)
36
+
37
+ ### 3.0.0
38
+
39
+ - Added jruby/PostgreSQL support for Rails 4.x
40
+ - Reworked threaded tests to allow jruby tests to pass
41
+
42
+ #### API changes
43
+
44
+ - `yield_with_lock_and_timeout` and `yield_with_lock` now return instances of
45
+ `WithAdvisoryLock::Result`, so blocks that return `false` are not misinterpreted
46
+ as a failure to lock. As this changes the interface (albeit internal methods), the major version
47
+ number was incremented.
48
+ - `with_advisory_lock_result` was introduced, which clarifies whether the lock was acquired
49
+ versus the yielded block returned false.
50
+
51
+ ### 2.0.0
52
+
53
+ - Lock timeouts of 0 now attempt the lock once, as per suggested by
54
+ [Jon Leighton](https://github.com/jonleighton) and implemented by
55
+ [Abdelkader Boudih](https://github.com/seuros). Thanks to both of you!
56
+ - [Pull request 11](https://github.com/ClosureTree/with_advisory_lock/pull/11)
57
+ fixed a downstream issue with jruby support! Thanks, [Aaron Todd](https://github.com/ozzyaaron)!
58
+ - Added Travis tests for jruby
59
+ - Dropped support for Rails 3.0, 3.1, and Ruby 1.8.7, as they are no longer
60
+ receiving security patches. See http://rubyonrails.org/security/ for more information.
61
+ This required the major version bump.
62
+ - Refactored `advisory_lock_exists?` to use existing functionality
63
+ - Fixed sqlite's implementation so parallel tests could be run against it
64
+
65
+ ### 1.0.0
66
+
67
+ - Releasing 1.0.0. The interface will be stable.
68
+ - Added `advisory_lock_exists?`. Thanks, [Sean Devine](https://github.com/barelyknown), for the
69
+ great pull request!
70
+ - Added Travis test for Rails 4.1
71
+
72
+ ### 0.0.10
73
+
74
+ - Explicitly added MIT licensing to the gemspec.
75
+
76
+ ### 0.0.9
77
+
78
+ - Merged in Postgis Adapter Support to address [issue 7](https://github.com/ClosureTree/with_advisory_lock/issues/7)
79
+ Thanks for the pull request, [Abdelkader Boudih](https://github.com/seuros)!
80
+ - The database switching code had to be duplicated by [Closure Tree](https://github.com/ClosureTree/closure_tree),
81
+ so I extracted a new `WithAdvisoryLock::DatabaseAdapterSupport` one-trick pony.
82
+ - Builds were failing on Travis, so I introduced a global lock prefix that can be set with the
83
+ `WITH_ADVISORY_LOCK_PREFIX` environment variable. I'm not going to advertise this feature yet.
84
+ It's a secret. Only you and I know, now. _shhh_
85
+
86
+ ### 0.0.8
87
+
88
+ - Addressed [issue 5](https://github.com/ClosureTree/with_advisory_lock/issues/5) by
89
+ using a deterministic hash for Postgresql + MRI >= 1.9.
90
+ Thanks for the pull request, [Joel Turkel](https://github.com/jturkel)!
91
+ - Addressed [issue 2](https://github.com/ClosureTree/with_advisory_lock/issues/2) by
92
+ using a cache-busting query for MySQL and Postgres to deal with AR value caching bug.
93
+ Thanks for the pull request, [Jaime Giraldo](https://github.com/sposmen)!
94
+ - Addressed [issue 4](https://github.com/ClosureTree/with_advisory_lock/issues/4) by
95
+ adding support for `em-postgresql-adapter`.
96
+ Thanks, [lestercsp](https://github.com/lestercsp)!
97
+
98
+ (Hey, github—your notifications are WAY too easy to ignore!)
99
+
100
+ ### 0.0.7
101
+
102
+ - Added Travis tests for Rails 3.0, 3.1, 3.2, and 4.0
103
+ - Fixed MySQL bug with select_value returning a string instead of an integer when using AR 3.0.x
104
+
105
+ ### 0.0.6
106
+
107
+ - Only require ActiveRecord >= 3.0.x
108
+ - Fixed MySQL error reporting
109
+
110
+ ### 0.0.5
111
+
112
+ - Asking for the currently acquired advisory lock doesn't re-ask for the lock now.
113
+ - Introduced NestedAdvisoryLockError when asking for different, nested advisory locksMySQL
114
+
115
+ ### 0.0.4
116
+
117
+ - Moved require into on_load, which should speed loading when AR doesn't have to spin up
118
+
119
+ ### 0.0.3
120
+
121
+ - Fought with ActiveRecord 3.0.x and 3.1.x. You don't want them if you use threads—they fail
122
+ predictably.
123
+
124
+ ### 0.0.2
125
+
126
+ - Added warning log message for nested MySQL lock calls
127
+ - Randomized lock wait time, which can help ameliorate lock contention
128
+
129
+ ### 0.0.1
130
+
131
+ - First whack
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/README.md CHANGED
@@ -1,22 +1,26 @@
1
1
  # with_advisory_lock
2
2
 
3
- Adds advisory locking (mutexes) to ActiveRecord 4.2 and 5.0, with ruby 2.4, 2.3 or 2.2, when used with
4
- [MySQL](http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_get-lock)
5
- or [PostgreSQL](http://www.postgresql.org/docs/9.3/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS).
3
+ Adds advisory locking (mutexes) to ActiveRecord 6.0+, with ruby 2.7+, jruby or truffleruby, when used with
4
+ [MySQL](https://dev.mysql.com/doc/refman/8.0/en/miscellaneous-functions.html#function_get-lock)
5
+ or
6
+ [PostgreSQL](https://www.postgresql.org/docs/current/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS).
6
7
  SQLite resorts to file locking.
7
8
 
8
- [![Build Status](https://api.travis-ci.org/ClosureTree/with_advisory_lock.svg?branch=master)](http://travis-ci.org/ClosureTree/with_advisory_lock)
9
9
  [![Gem Version](https://badge.fury.io/rb/with_advisory_lock.svg)](https://badge.fury.io/rb/with_advisory_lock)
10
+ [![CI](https://github.com/ClosureTree/with_advisory_lock/actions/workflows/ci.yml/badge.svg)](https://github.com/ClosureTree/with_advisory_lock/actions/workflows/ci.yml)
10
11
 
11
12
  ## What's an "Advisory Lock"?
12
13
 
13
- An advisory lock is a [mutex](http://en.wikipedia.org/wiki/Mutual_exclusion) used to ensure no two
14
- processes run some process at the same time. When the advisory lock is powered by your database
15
- server, as long as it isn't SQLite, your mutex spans hosts.
14
+ An advisory lock is a [mutex](https://en.wikipedia.org/wiki/Mutual_exclusion)
15
+ used to ensure no two processes run some process at the same time. When the
16
+ advisory lock is powered by your database server, as long as it isn't SQLite,
17
+ your mutex spans hosts.
16
18
 
17
19
  ## Usage
18
20
 
19
- Where ```User``` is an ActiveRecord model, and ```lock_name``` is some string:
21
+ This gem automatically includes the `WithAdvisoryLock` module in all of your
22
+ ActiveRecord models. Here's an example of how to use it where `User` is an
23
+ ActiveRecord model, and `lock_name` is some string:
20
24
 
21
25
  ```ruby
22
26
  User.with_advisory_lock(lock_name) do
@@ -32,58 +36,77 @@ end
32
36
 
33
37
  ### Lock wait timeouts
34
38
 
35
- ```with_advisory_lock``` takes an options hash as the second parameter.
36
- The ```timeout_seconds``` option defaults to ```nil```, which means wait indefinitely for the lock.
39
+ `with_advisory_lock` takes an options hash as the second parameter. The
40
+ `timeout_seconds` option defaults to `nil`, which means wait indefinitely for
41
+ the lock.
37
42
 
38
43
  A value of zero will try the lock only once. If the lock is acquired, the block
39
- will be yielded to. If the lock is currently being held, the block will not be called.
44
+ will be yielded to. If the lock is currently being held, the block will not be
45
+ called.
40
46
 
41
- Note that if a non-nil value is provided for `timeout_seconds`, the block will not be invoked if
42
- the lock cannot be acquired within that time-frame.
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.
43
51
 
44
- For backwards compatability, the timeout value can be specified directly as the second parameter.
52
+ For backwards compatability, the timeout value can be specified directly as the
53
+ second parameter.
45
54
 
46
55
  ### Shared locks
47
56
 
48
- The ```shared``` option defaults to ```false``` which means an exclusive lock will be obtained.
49
- Setting ```shared``` to ```true``` will allow locks to be obtained by multiple actors
50
- as long as they are all shared locks.
57
+ The `shared` option defaults to `false` which means an exclusive lock will be
58
+ obtained. Setting `shared` to `true` will allow locks to be obtained by multiple
59
+ actors as long as they are all shared locks.
51
60
 
52
61
  Note: MySQL does not support shared locks.
53
62
 
54
63
  ### Transaction-level locks
55
64
 
56
- PostgreSQL supports transaction-level locks which remain held until the transaction completes.
57
- You can enable this by setting the ```transaction``` option to ```true```.
65
+ PostgreSQL supports transaction-level locks which remain held until the
66
+ transaction completes. You can enable this by setting the `transaction` option
67
+ to `true`.
58
68
 
59
- Note: transaction-level locks will not be reflected by `.current_advisory_lock` when the block has returned.
69
+ Note: transaction-level locks will not be reflected by `.current_advisory_lock`
70
+ when the block has returned.
60
71
 
61
72
  ### Return values
62
73
 
63
- The return value of `with_advisory_lock_result` is a `WithAdvisoryLock::Result` instance,
64
- which has a `lock_was_acquired?` method and a `result` accessor method, which is
65
- the returned value of the given block. If your block may validly return false, you should use
66
- this method.
67
-
68
- The return value of ```with_advisory_lock``` will be the result of the yielded block,
69
- if the lock was able to be acquired and the block yielded, or ```false```, if you provided
70
- a timeout_seconds value and the lock was not able to be acquired in time.
74
+ The return value of `with_advisory_lock_result` is a `WithAdvisoryLock::Result`
75
+ instance, which has a `lock_was_acquired?` method and a `result` accessor
76
+ method, which is the returned value of the given block. If your block may
77
+ validly return false, you should use this method.
78
+
79
+ The return value of `with_advisory_lock` will be the result of the yielded
80
+ block, if the lock was able to be acquired and the block yielded, or `false`, if
81
+ you provided a timeout_seconds value and the lock was not able to be acquired in
82
+ time.
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.
71
85
 
72
86
  ### Testing for the current lock status
73
87
 
74
- If you needed to check if the advisory lock is currently being held, you can call
75
- ```Tag.advisory_lock_exists?("foo")```, but realize the lock can be acquired between the time you
76
- test for the lock, and the time you try to acquire the lock.
88
+ If you needed to check if the advisory lock is currently being held, you can
89
+ call `Tag.advisory_lock_exists?("foo")`, but realize the lock can be acquired
90
+ between the time you test for the lock, and the time you try to acquire the
91
+ lock.
92
+
93
+ If you want to see if the current Thread is holding a lock, you can call
94
+ `Tag.current_advisory_lock` which will return the name of the current lock. If
95
+ no lock is currently held, `.current_advisory_lock` returns `nil`.
77
96
 
78
- If you want to see if the current Thread is holding a lock, you can call ```Tag.current_advisory_lock```
79
- which will return the name of the current lock. If no lock is currently held,
80
- ```.current_advisory_lock``` returns ```nil```.
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)
81
104
 
82
105
  ## Installation
83
106
 
84
107
  Add this line to your application's Gemfile:
85
108
 
86
- ``` ruby
109
+ ```ruby
87
110
  gem 'with_advisory_lock'
88
111
  ```
89
112
 
@@ -93,27 +116,31 @@ And then execute:
93
116
 
94
117
  ## Lock Types
95
118
 
96
- First off, know that there are **lots** of different kinds of locks available to you. **Pick the
97
- finest-grain lock that ensures correctness.** If you choose a lock that is too coarse, you are
98
- unnecessarily blocking other processes.
119
+ First off, know that there are **lots** of different kinds of locks available to
120
+ you. **Pick the finest-grain lock that ensures correctness.** If you choose a
121
+ lock that is too coarse, you are unnecessarily blocking other processes.
99
122
 
100
123
  ### Advisory locks
101
- These are named mutexes that are inherently "application level"—it is up to the application
102
- to acquire, run a critical code section, and release the advisory lock.
124
+
125
+ These are named mutexes that are inherently "application level"—it is up to the
126
+ application to acquire, run a critical code section, and release the advisory
127
+ lock.
103
128
 
104
129
  ### Row-level locks
130
+
105
131
  Whether [optimistic](http://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html)
106
132
  or [pessimistic](http://api.rubyonrails.org/classes/ActiveRecord/Locking/Pessimistic.html),
107
133
  row-level locks prevent concurrent modification to a given model.
108
134
 
109
135
  **If you're building a
110
- [CRUD](http://en.wikipedia.org/wiki/Create,_read,_update_and_delete) application, this will be your
111
- most commonly used lock.**
136
+ [CRUD](http://en.wikipedia.org/wiki/Create,_read,_update_and_delete)
137
+ application, this will be 2.4, 2.5 and your most commonly used lock.**
112
138
 
113
139
  ### Table-level locks
114
140
 
115
- Provided through something like the [monogamy](https://github.com/ClosureTree/monogamy)
116
- gem, these prevent concurrent access to **any instance of a model**. Their coarseness means they
141
+ Provided through something like the
142
+ [monogamy](https://github.com/ClosureTree/monogamy) gem, these prevent
143
+ concurrent access to **any instance of a model**. Their coarseness means they
117
144
  aren't going to be commonly applicable, and they can be a source of
118
145
  [deadlocks](http://en.wikipedia.org/wiki/Deadlock).
119
146
 
@@ -125,26 +152,31 @@ Advisory locks with MySQL and PostgreSQL ignore database transaction boundaries.
125
152
 
126
153
  You will want to wrap your block within a transaction to ensure consistency.
127
154
 
128
- ### MySQL doesn't support nesting
155
+ ### MySQL < 5.7.5 doesn't support nesting
156
+
157
+ With MySQL < 5.7.5, if you ask for a _different_ advisory lock within
158
+ a `with_advisory_lock` block, you will be releasing the parent lock (!!!). A
159
+ `NestedAdvisoryLockError`will be raised in this case. If you ask for the same
160
+ lock name, `with_advisory_lock` won't ask for the lock again, and the block
161
+ given will be yielded to.
129
162
 
130
- With MySQL (at least <= v5.5), if you ask for a *different* advisory lock within a ```with_advisory_lock``` block,
131
- you will be releasing the parent lock (!!!). A ```NestedAdvisoryLockError```will be raised
132
- in this case. If you ask for the same lock name, ```with_advisory_lock``` won't ask for the
133
- lock again, and the block given will be yielded to.
163
+ This is not an issue in MySQL >= 5.7.5, and no error will be raised for nested
164
+ lock usage. You can override this by passing `force_nested_lock_support: true`
165
+ or `force_nested_lock_support: false` to the `with_advisory_lock` options.
134
166
 
135
167
  ### Is clustered MySQL supported?
136
168
 
137
169
  [No.](https://github.com/ClosureTree/with_advisory_lock/issues/16)
138
170
 
139
- ### There are many ```lock-*``` files in my project directory after test runs
171
+ ### There are many `lock-*` files in my project directory after test runs
140
172
 
141
173
  This is expected if you aren't using MySQL or Postgresql for your tests.
142
174
  See [issue 3](https://github.com/ClosureTree/with_advisory_lock/issues/3).
143
175
 
144
- SQLite doesn't have advisory locks, so we resort to file locking, which will only work
145
- if the ```FLOCK_DIR``` is set consistently for all ruby processes.
176
+ SQLite doesn't have advisory locks, so we resort to file locking, which will
177
+ only work if the `FLOCK_DIR` is set consistently for all ruby processes.
146
178
 
147
- In your ```spec_helper.rb``` or ```minitest_helper.rb```, add a ```before``` and ```after``` block:
179
+ In your `spec_helper.rb` or `minitest_helper.rb`, add a `before` and `after` block:
148
180
 
149
181
  ```ruby
150
182
  before do
@@ -155,121 +187,3 @@ after do
155
187
  FileUtils.remove_entry_secure ENV['FLOCK_DIR']
156
188
  end
157
189
  ```
158
-
159
- ## Changelog
160
-
161
- ### 4.0.0
162
-
163
- * Drop support for unsupported versions of activerecord
164
- * Drop support for unsupported versions of ruby
165
-
166
- ### 3.2.0
167
-
168
- * [Joshua Flanagan](https://github.com/joshuaflanagan) [added a SQL comment to the lock query for PostgreSQL](https://github.com/ClosureTree/with_advisory_lock/pull/28). Thanks!
169
- * [Fernando Luizão](https://github.com/fernandoluizao) found a spurious requirement for `thread_safe`. Thanks for the [fix](https://github.com/ClosureTree/with_advisory_lock/pull/27)!
170
-
171
- ### 3.1.1
172
-
173
- * [Joel Turkel](https://github.com/jturkel) added `require 'active_support'` (it was required, but relied on downstream gems to pull in active_support before pulling in with_advisory_lock). Thanks!
174
-
175
- ### 3.1.0
176
-
177
- * [Jason Weathered](https://github.com/jasoncodes) Added new shared and transaction-level lock options ([Pull request 21](https://github.com/ClosureTree/with_advisory_lock/pull/21)). Thanks!
178
- * Added ActiveRecord 5.0 to build matrix. Dropped 3.2, 4.0, and 4.1 (which no longer get security updates: http://rubyonrails.org/security/)
179
- * Replaced ruby 1.9 and 2.0 (both EOL) with ruby 2.2 and 2.3 (see https://www.ruby-lang.org/en/downloads/)
180
-
181
- ### 3.0.0
182
-
183
- * Added jruby/PostgreSQL support for Rails 4.x
184
- * Reworked threaded tests to allow jruby tests to pass
185
-
186
- #### API changes
187
-
188
- * `yield_with_lock_and_timeout` and `yield_with_lock` now return instances of
189
- `WithAdvisoryLock::Result`, so blocks that return `false` are not misinterpreted
190
- as a failure to lock. As this changes the interface (albeit internal methods), the major version
191
- number was incremented.
192
- * `with_advisory_lock_result` was introduced, which clarifies whether the lock was acquired
193
- versus the yielded block returned false.
194
-
195
- ### 2.0.0
196
-
197
- * Lock timeouts of 0 now attempt the lock once, as per suggested by
198
- [Jon Leighton](https://github.com/jonleighton) and implemented by
199
- [Abdelkader Boudih](https://github.com/seuros). Thanks to both of you!
200
- * [Pull request 11](https://github.com/ClosureTree/with_advisory_lock/pull/11)
201
- fixed a downstream issue with jruby support! Thanks, [Aaron Todd](https://github.com/ozzyaaron)!
202
- * Added Travis tests for jruby
203
- * Dropped support for Rails 3.0, 3.1, and Ruby 1.8.7, as they are no longer
204
- receiving security patches. See http://rubyonrails.org/security/ for more information.
205
- This required the major version bump.
206
- * Refactored `advisory_lock_exists?` to use existing functionality
207
- * Fixed sqlite's implementation so parallel tests could be run against it
208
-
209
- ### 1.0.0
210
-
211
- * Releasing 1.0.0. The interface will be stable.
212
- * Added ```advisory_lock_exists?```. Thanks, [Sean Devine](https://github.com/barelyknown), for the
213
- great pull request!
214
- * Added Travis test for Rails 4.1
215
-
216
- ### 0.0.10
217
-
218
- * Explicitly added MIT licensing to the gemspec.
219
-
220
- ### 0.0.9
221
-
222
- * Merged in Postgis Adapter Support to address [issue 7](https://github.com/ClosureTree/with_advisory_lock/issues/7)
223
- Thanks for the pull request, [Abdelkader Boudih](https://github.com/seuros)!
224
- * The database switching code had to be duplicated by [Closure Tree](https://github.com/ClosureTree/closure_tree),
225
- so I extracted a new ```WithAdvisoryLock::DatabaseAdapterSupport``` one-trick pony.
226
- * Builds were failing on Travis, so I introduced a global lock prefix that can be set with the
227
- ```WITH_ADVISORY_LOCK_PREFIX``` environment variable. I'm not going to advertise this feature yet.
228
- It's a secret. Only you and I know, now. *shhh*
229
-
230
- ### 0.0.8
231
-
232
- * Addressed [issue 5](https://github.com/ClosureTree/with_advisory_lock/issues/5) by
233
- using a deterministic hash for Postgresql + MRI >= 1.9.
234
- Thanks for the pull request, [Joel Turkel](https://github.com/jturkel)!
235
- * Addressed [issue 2](https://github.com/ClosureTree/with_advisory_lock/issues/2) by
236
- using a cache-busting query for MySQL and Postgres to deal with AR value caching bug.
237
- Thanks for the pull request, [Jaime Giraldo](https://github.com/sposmen)!
238
- * Addressed [issue 4](https://github.com/ClosureTree/with_advisory_lock/issues/4) by
239
- adding support for ```em-postgresql-adapter```.
240
- Thanks, [lestercsp](https://github.com/lestercsp)!
241
-
242
- (Hey, github—your notifications are WAY too easy to ignore!)
243
-
244
- ### 0.0.7
245
-
246
- * Added Travis tests for Rails 3.0, 3.1, 3.2, and 4.0
247
- * Fixed MySQL bug with select_value returning a string instead of an integer when using AR 3.0.x
248
-
249
- ### 0.0.6
250
-
251
- * Only require ActiveRecord >= 3.0.x
252
- * Fixed MySQL error reporting
253
-
254
- ### 0.0.5
255
-
256
- * Asking for the currently acquired advisory lock doesn't re-ask for the lock now.
257
- * Introduced NestedAdvisoryLockError when asking for different, nested advisory locksMySQL
258
-
259
- ### 0.0.4
260
-
261
- * Moved require into on_load, which should speed loading when AR doesn't have to spin up
262
-
263
- ### 0.0.3
264
-
265
- * Fought with ActiveRecord 3.0.x and 3.1.x. You don't want them if you use threads—they fail
266
- predictably.
267
-
268
- ### 0.0.2
269
-
270
- * Added warning log message for nested MySQL lock calls
271
- * Randomized lock wait time, which can help ameliorate lock contention
272
-
273
- ### 0.0.1
274
-
275
- * First whack
@@ -2,12 +2,14 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", "~> 5.1.0"
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