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 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