with_advisory_lock 0.0.10 → 0.0.11
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 +9 -9
- data/.travis.yml +1 -0
- data/README.md +20 -1
- data/ci/Gemfile.rails-4.0.x +1 -2
- data/ci/Gemfile.rails-4.1.x +4 -0
- data/lib/with_advisory_lock/base.rb +9 -1
- data/lib/with_advisory_lock/concern.rb +20 -2
- data/lib/with_advisory_lock/mysql.rb +7 -0
- data/lib/with_advisory_lock/postgresql.rb +8 -2
- data/lib/with_advisory_lock/version.rb +1 -1
- data/test/concern_test.rb +9 -0
- data/test/lock_test.rb +32 -0
- data/test/minitest_helper.rb +4 -0
- data/test/nesting_test.rb +1 -0
- data/tests.sh +6 -10
- data/with_advisory_lock.gemspec +4 -4
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MmRkYzNlYTU4Njg0OTk1YmQ1OWI2NjgyNzJmYTRhMmNjMzQyZTM4Mw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
7
|
-
|
6
|
+
MTQyOTQ3MTdmMjRkYzA1NGU4OGI5M2I0NTVkNjg4YjVmMDM3ODMzNw==
|
7
|
+
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
N2Y2MzI5MjhmOTllZjgyODhhNjdlNjVlYjI0YTU1MGJlMmEzODgzNWViNGEy
|
10
|
+
NjUwNDVkMmFkZTE5NDY2NzNhYjgyOGE0N2QyNjM0ZWNjYzlhNjI1YTA4ZmQ3
|
11
|
+
MjUzYzc0NGUwYTk0NGNkOTQ5NTUwNmU1MGUxMmJhMjE4MDRlZDI=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ODQ2MjkyMWUxNmEwOWE2NTlmMjFiZTE0NTE2ZWEyOTA5NGViMjA3YTE1OTJl
|
14
|
+
YWYwOTNiMGZjODcwY2M0NGVlMmZjYzNiNTMxNmM2YmZmODExZDU1N2VkODcx
|
15
|
+
YjA4MmVjNTk1MTIwYTNjMGE5Njg3MzlkOWQ0OWQwZDJiY2MyYjM=
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# with_advisory_lock
|
2
2
|
|
3
|
-
Adds advisory locking (mutexes) to ActiveRecord 3.0, 3.1, 3.2, and 4.
|
3
|
+
Adds advisory locking (mutexes) to ActiveRecord 3.0, 3.1, 3.2, 4.0 and 4.1 when used with
|
4
4
|
[MySQL](http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_get-lock)
|
5
5
|
or [PostgreSQL](http://www.postgresql.org/docs/9.1/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS).
|
6
6
|
SQLite resorts to file locking.
|
@@ -9,6 +9,7 @@ SQLite resorts to file locking.
|
|
9
9
|
[](http://rubygems.org/gems/with_advisory_lock)
|
10
10
|
[](https://codeclimate.com/github/mceachen/with_advisory_lock)
|
11
11
|
[](https://gemnasium.com/mceachen/with_advisory_lock)
|
12
|
+
[](https://bitdeli.com/free "Bitdeli Badge")
|
12
13
|
|
13
14
|
## What's an "Advisory Lock"?
|
14
15
|
|
@@ -43,6 +44,16 @@ The return value of ```with_advisory_lock``` will be the result of the yielded b
|
|
43
44
|
if the lock was able to be acquired and the block yielded, or ```false```, if you provided
|
44
45
|
a timeout_seconds value and the lock was not able to be acquired in time.
|
45
46
|
|
47
|
+
### Testing for the current lock status
|
48
|
+
|
49
|
+
If you needed to check if the advisory lock is currently being held, you can call
|
50
|
+
```Tag.advisory_lock_exists?("foo")```, but realize the lock can be acquired between the time you
|
51
|
+
test for the lock, and the time you try to acquire the lock.
|
52
|
+
|
53
|
+
If you want to see if the current Thread is holding a lock, you can call ```Tag.current_advisory_lock```
|
54
|
+
which will return the name of the current lock. If no lock is currently held,
|
55
|
+
```.current_advisory_lock``` returns ```nil```.
|
56
|
+
|
46
57
|
## Installation
|
47
58
|
|
48
59
|
Add this line to your application's Gemfile:
|
@@ -118,6 +129,14 @@ end
|
|
118
129
|
|
119
130
|
## Changelog
|
120
131
|
|
132
|
+
|
133
|
+
### 1.0.0
|
134
|
+
|
135
|
+
* Releasing 1.0.0. The interface will be stable.
|
136
|
+
* Added ```advisory_lock_exists?```. Thanks, [Sean Devine](https://github.com/barelyknown), for the
|
137
|
+
great pull request!
|
138
|
+
* Added Travis test for Rails 4.1
|
139
|
+
|
121
140
|
### 0.0.10
|
122
141
|
|
123
142
|
* Explicitly added MIT licensing to the gemspec.
|
data/ci/Gemfile.rails-4.0.x
CHANGED
@@ -22,14 +22,22 @@ module WithAdvisoryLock
|
|
22
22
|
connection.quote(lock_name)
|
23
23
|
end
|
24
24
|
|
25
|
-
def lock_stack
|
25
|
+
def self.lock_stack
|
26
26
|
Thread.current[:with_advisory_lock_stack] ||= []
|
27
27
|
end
|
28
28
|
|
29
|
+
def lock_stack
|
30
|
+
self.class.lock_stack
|
31
|
+
end
|
32
|
+
|
29
33
|
def already_locked?
|
30
34
|
lock_stack.include? @lock_name
|
31
35
|
end
|
32
36
|
|
37
|
+
def advisory_lock_exists?(name)
|
38
|
+
raise NoMethodError, "method must be implemented in implementation subclasses"
|
39
|
+
end
|
40
|
+
|
33
41
|
def with_advisory_lock_if_needed
|
34
42
|
if already_locked?
|
35
43
|
yield
|
@@ -16,8 +16,28 @@ module WithAdvisoryLock
|
|
16
16
|
self.class.with_advisory_lock(lock_name, timeout_seconds, &block)
|
17
17
|
end
|
18
18
|
|
19
|
+
def advisory_lock_exists?(lock_name)
|
20
|
+
self.class.advisory_lock_exists?(lock_name)
|
21
|
+
end
|
22
|
+
|
19
23
|
module ClassMethods
|
20
24
|
def with_advisory_lock(lock_name, timeout_seconds=nil, &block)
|
25
|
+
impl = impl_class.new(connection, lock_name, timeout_seconds)
|
26
|
+
impl.with_advisory_lock_if_needed(&block)
|
27
|
+
end
|
28
|
+
|
29
|
+
def advisory_lock_exists?(lock_name)
|
30
|
+
impl = impl_class.new(connection, lock_name, nil)
|
31
|
+
impl.advisory_lock_exists?(lock_name)
|
32
|
+
end
|
33
|
+
|
34
|
+
def current_advisory_lock
|
35
|
+
WithAdvisoryLock::Base.lock_stack.first
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def impl_class
|
21
41
|
das = WithAdvisoryLock::DatabaseAdapterSupport.new(connection)
|
22
42
|
impl_class = if das.postgresql?
|
23
43
|
WithAdvisoryLock::PostgreSQL
|
@@ -26,8 +46,6 @@ module WithAdvisoryLock
|
|
26
46
|
else
|
27
47
|
WithAdvisoryLock::Flock
|
28
48
|
end
|
29
|
-
impl = impl_class.new(connection, lock_name, timeout_seconds)
|
30
|
-
impl.with_advisory_lock_if_needed(&block)
|
31
49
|
end
|
32
50
|
end
|
33
51
|
end
|
@@ -32,5 +32,12 @@ module WithAdvisoryLock
|
|
32
32
|
def already_locked?
|
33
33
|
lock_stack.last == @lock_name
|
34
34
|
end
|
35
|
+
|
36
|
+
def advisory_lock_exists?(name)
|
37
|
+
quoted_name = connection.quote(name)
|
38
|
+
# See http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_is-used-lock
|
39
|
+
sql = "SELECT IS_USED_LOCK(#{quoted_name})"
|
40
|
+
connection.select_value(sql).present?
|
41
|
+
end
|
35
42
|
end
|
36
43
|
end
|
@@ -16,8 +16,14 @@ module WithAdvisoryLock
|
|
16
16
|
"t" == connection.select_value(sql).to_s
|
17
17
|
end
|
18
18
|
|
19
|
-
def numeric_lock
|
20
|
-
|
19
|
+
def numeric_lock(name=lock_name)
|
20
|
+
stable_hashcode(name)
|
21
21
|
end
|
22
|
+
|
23
|
+
def advisory_lock_exists?(name)
|
24
|
+
sql = "SELECT 't'::text FROM pg_locks WHERE objid = #{numeric_lock(name)} AND locktype = 'advisory'"
|
25
|
+
"t" == connection.select_value(sql).to_s
|
26
|
+
end
|
27
|
+
|
22
28
|
end
|
23
29
|
end
|
data/test/concern_test.rb
CHANGED
@@ -8,4 +8,13 @@ describe "with_advisory_lock.concern" do
|
|
8
8
|
it "adds with_advisory_lock to ActiveRecord instances" do
|
9
9
|
assert Label.new.respond_to?(:with_advisory_lock)
|
10
10
|
end
|
11
|
+
|
12
|
+
it "adds advisory_lock_exists? to ActiveRecord classes" do
|
13
|
+
assert Tag.respond_to?(:advisory_lock_exists?)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "adds advisory_lock_exists? to ActiveRecord classes" do
|
17
|
+
assert Label.new.respond_to?(:advisory_lock_exists?)
|
18
|
+
end
|
19
|
+
|
11
20
|
end
|
data/test/lock_test.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe 'class methods' do
|
4
|
+
|
5
|
+
let(:lock_name) { "test lock #{rand(1024)}" }
|
6
|
+
let(:expected_lock_name) { "#{ENV['WITH_ADVISORY_LOCK_PREFIX']}#{lock_name}" }
|
7
|
+
|
8
|
+
describe '.current_advisory_lock' do
|
9
|
+
it "returns nil outside an advisory lock request" do
|
10
|
+
Tag.current_advisory_lock.must_be_nil
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'returns the name of the last lock acquired' do
|
14
|
+
Tag.with_advisory_lock(lock_name) do
|
15
|
+
Tag.current_advisory_lock.must_equal expected_lock_name
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '.advisory_lock_exists?' do
|
21
|
+
it "returns false for an unacquired lock" do
|
22
|
+
Tag.advisory_lock_exists?(expected_lock_name).must_equal false
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'returns the name of the last lock acquired' do
|
26
|
+
Tag.with_advisory_lock(lock_name) do
|
27
|
+
Tag.advisory_lock_exists?(expected_lock_name).must_equal true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end if test_lock_exists?
|
data/test/minitest_helper.rb
CHANGED
data/test/nesting_test.rb
CHANGED
data/tests.sh
CHANGED
@@ -1,14 +1,10 @@
|
|
1
1
|
#!/bin/sh -e
|
2
|
-
export BUNDLE_GEMFILE
|
2
|
+
export BUNDLE_GEMFILE DB
|
3
3
|
|
4
|
-
for
|
5
|
-
for
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
do
|
10
|
-
echo $DB $BUNDLE_GEMFILE `ruby -v`
|
11
|
-
bundle exec rake
|
12
|
-
done
|
4
|
+
for BUNDLE_GEMFILE in ci/Gemfile.rails-4.1.x ci/Gemfile.rails-3.2.x ; do
|
5
|
+
for DB in sqlite mysql postgresql
|
6
|
+
do
|
7
|
+
echo $DB $BUNDLE_GEMFILE `ruby -v`
|
8
|
+
bundle exec rake
|
13
9
|
done
|
14
10
|
done
|
data/with_advisory_lock.gemspec
CHANGED
@@ -6,12 +6,12 @@ require 'with_advisory_lock/version'
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
7
|
gem.name = "with_advisory_lock"
|
8
8
|
gem.version = WithAdvisoryLock::VERSION
|
9
|
-
gem.authors = [
|
10
|
-
gem.email =
|
9
|
+
gem.authors = ['Matthew McEachen']
|
10
|
+
gem.email = %w(matthew+github@mceachen.org)
|
11
|
+
gem.homepage = 'https://github.com/mceachen/with_advisory_lock'
|
12
|
+
gem.summary = %q{Advisory locking for ActiveRecord}
|
11
13
|
gem.description = %q{Advisory locking for ActiveRecord}
|
12
|
-
gem.summary = gem.description
|
13
14
|
gem.license = 'MIT'
|
14
|
-
gem.homepage = ""
|
15
15
|
|
16
16
|
gem.files = `git ls-files`.split($/)
|
17
17
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: with_advisory_lock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew McEachen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-01-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -153,6 +153,7 @@ files:
|
|
153
153
|
- ci/Gemfile.rails-3.1.x
|
154
154
|
- ci/Gemfile.rails-3.2.x
|
155
155
|
- ci/Gemfile.rails-4.0.x
|
156
|
+
- ci/Gemfile.rails-4.1.x
|
156
157
|
- lib/with_advisory_lock.rb
|
157
158
|
- lib/with_advisory_lock/base.rb
|
158
159
|
- lib/with_advisory_lock/concern.rb
|
@@ -164,6 +165,7 @@ files:
|
|
164
165
|
- lib/with_advisory_lock/version.rb
|
165
166
|
- test/concern_test.rb
|
166
167
|
- test/database.yml
|
168
|
+
- test/lock_test.rb
|
167
169
|
- test/minitest_helper.rb
|
168
170
|
- test/nesting_test.rb
|
169
171
|
- test/parallelism_test.rb
|
@@ -171,7 +173,7 @@ files:
|
|
171
173
|
- test/test_models.rb
|
172
174
|
- tests.sh
|
173
175
|
- with_advisory_lock.gemspec
|
174
|
-
homepage:
|
176
|
+
homepage: https://github.com/mceachen/with_advisory_lock
|
175
177
|
licenses:
|
176
178
|
- MIT
|
177
179
|
metadata: {}
|
@@ -191,13 +193,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
191
193
|
version: '0'
|
192
194
|
requirements: []
|
193
195
|
rubyforge_project:
|
194
|
-
rubygems_version: 2.0
|
196
|
+
rubygems_version: 2.2.0
|
195
197
|
signing_key:
|
196
198
|
specification_version: 4
|
197
199
|
summary: Advisory locking for ActiveRecord
|
198
200
|
test_files:
|
199
201
|
- test/concern_test.rb
|
200
202
|
- test/database.yml
|
203
|
+
- test/lock_test.rb
|
201
204
|
- test/minitest_helper.rb
|
202
205
|
- test/nesting_test.rb
|
203
206
|
- test/parallelism_test.rb
|