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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MjIyODVkMGEwYjYzNmI2YzdjMjcyYjFhZDM2MmY5Mzk1M2QxMWRiYg==
4
+ MmRkYzNlYTU4Njg0OTk1YmQ1OWI2NjgyNzJmYTRhMmNjMzQyZTM4Mw==
5
5
  data.tar.gz: !binary |-
6
- MTEyMDI5YzlkZTQ0NmEwMjI3NWZjYmEyYjVlZjMyMzJlOTU3ZGE2OA==
7
- !binary "U0hBNTEy":
6
+ MTQyOTQ3MTdmMjRkYzA1NGU4OGI5M2I0NTVkNjg4YjVmMDM3ODMzNw==
7
+ SHA512:
8
8
  metadata.gz: !binary |-
9
- MjA4YmI5YTFjZDllNjYyM2RiMTJmNjNlZTZkNzFkNDJmMDQwYTViODc3NTE5
10
- NDA1YTZiYTI0MzBlMzlkNjIwNWZjZTgxOGZmODIwZjI0NjM4Yzg3MjczY2Q1
11
- YTI2MmZlMzNiOWEzMWU2MTgxOWY5ZmYwZWQ5MmE2ZjRjZTlhYjI=
9
+ N2Y2MzI5MjhmOTllZjgyODhhNjdlNjVlYjI0YTU1MGJlMmEzODgzNWViNGEy
10
+ NjUwNDVkMmFkZTE5NDY2NzNhYjgyOGE0N2QyNjM0ZWNjYzlhNjI1YTA4ZmQ3
11
+ MjUzYzc0NGUwYTk0NGNkOTQ5NTUwNmU1MGUxMmJhMjE4MDRlZDI=
12
12
  data.tar.gz: !binary |-
13
- YWRiYjczMWRhMDdmMTQ3ZDNhODc2ZWNkYzJhNjFjOWViMWZkODA5YzM3OTk1
14
- ZGZkNDQwY2Y4MTVlMTk0MWYwNGU1OTI4Y2Y4OWYyMjExOTAyODljODdkMTZm
15
- MmI3NTdjY2QwNGU4NGNjNmMzMmFmYTM5ZWNiY2ZkNjBiZTczODY=
13
+ ODQ2MjkyMWUxNmEwOWE2NTlmMjFiZTE0NTE2ZWEyOTA5NGViMjA3YTE1OTJl
14
+ YWYwOTNiMGZjODcwY2M0NGVlMmZjYzNiNTMxNmM2YmZmODExZDU1N2VkODcx
15
+ YjA4MmVjNTk1MTIwYTNjMGE5Njg3MzlkOWQ0OWQwZDJiY2MyYjM=
data/.travis.yml CHANGED
@@ -6,6 +6,7 @@ rvm:
6
6
  - 1.9.3
7
7
 
8
8
  gemfile:
9
+ - ci/Gemfile.rails-4.1.x
9
10
  - ci/Gemfile.rails-4.0.x
10
11
  - ci/Gemfile.rails-3.2.x
11
12
  # - ci/Gemfile.rails-3.1.x
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.0.0 when used with
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.
@@ -1,5 +1,4 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec :path => '..'
3
3
 
4
- # rspec-rails reverts to 2.3.1 (old and broken) unless you fetch the whole rails enchilada:
5
- gem 'rails', '~> 4.0.0'
4
+ gem 'activerecord', '~> 4.0.0'
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+ gemspec :path => '..'
3
+
4
+ gem 'activerecord', '~> 4.1.0.beta1'
@@ -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
- @numeric_lock ||= stable_hashcode(lock_name)
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
@@ -1,3 +1,3 @@
1
1
  module WithAdvisoryLock
2
- VERSION = Gem::Version.new('0.0.10')
2
+ VERSION = Gem::Version.new('0.0.11')
3
3
  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?
@@ -20,6 +20,10 @@ require 'mocha/setup'
20
20
 
21
21
  Thread.abort_on_exception = true
22
22
 
23
+ def test_lock_exists?
24
+ %w{mysql postgres}.include? env_db
25
+ end
26
+
23
27
  class MiniTest::Spec
24
28
  before do
25
29
  ENV['FLOCK_DIR'] = Dir.mktmpdir
data/test/nesting_test.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'minitest_helper'
2
2
 
3
3
  describe "lock nesting" do
4
+ # This simplifies what we expect from the lock name:
4
5
  before :each do
5
6
  @prior_prefix = ENV['WITH_ADVISORY_LOCK_PREFIX']
6
7
  ENV['WITH_ADVISORY_LOCK_PREFIX'] = nil
data/tests.sh CHANGED
@@ -1,14 +1,10 @@
1
1
  #!/bin/sh -e
2
- export BUNDLE_GEMFILE RMI DB
2
+ export BUNDLE_GEMFILE DB
3
3
 
4
- for RMI in ree-1.8.7-2011.03 1.9.3-p327 ; do
5
- for BUNDLE_GEMFILE in ci/Gemfile.rails-3.0.x ci/Gemfile.rails-3.1.x ci/Gemfile.rails-3.2.x ; do
6
- rbenv local $RMI
7
- bundle --quiet
8
- for DB in sqlite mysql postgresql
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
@@ -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 = ["Matthew McEachen"]
10
- gem.email = ["matthew+github@mceachen.org"]
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.10
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: 2013-07-14 00:00:00.000000000 Z
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.3
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