with_advisory_lock 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/with_advisory_lock.png)](http://rubygems.org/gems/with_advisory_lock)
|
10
10
|
[![Code Climate](https://codeclimate.com/github/mceachen/with_advisory_lock.png)](https://codeclimate.com/github/mceachen/with_advisory_lock)
|
11
11
|
[![Dependency Status](https://gemnasium.com/mceachen/with_advisory_lock.png)](https://gemnasium.com/mceachen/with_advisory_lock)
|
12
|
+
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/mceachen/with_advisory_lock/trend.png)](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
|