with_advisory_lock 0.0.8 → 0.0.9

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
- YzA3MTE5YzM5MzkwMjJmZjRjOWFhMTc1ZjA0ZGNmNWFlNTE1NjM4MQ==
4
+ ODk5MWVhZjFhZmQxMzJmZjhhYWUzNTdkYWUxODNkYjM3OTRlZmFkOQ==
5
5
  data.tar.gz: !binary |-
6
- ZGViZjU2NzczOGYyMTVkZDJjYWRmZjYwMTMwOWQwMDlkNDI1ZDc3Yw==
6
+ MWI3YWVkNzI0ZDc5YzdkMmE3MDg1NGU5YjkyNjNmYjZiYjU4OWIzYg==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- NDNmYWE3ZmNhZGFlZDU3ODQzMzAyODdlNTAxZjdkZTFkYzk2NDM2N2I0Mjhm
10
- YTE0OGM0MmZlNDY1ZWMyN2YzNmZmYTIzOWE5ODRhODFjZmE2MjY5MDNkNmY2
11
- Y2M2ZmNhOWVkNGVjNzI3MDczZmVjN2IxZTI0NjcwYmUzYzI2MmE=
9
+ MzBjOTlmZTVlNWRhZmM4NzMwODliNTFkODNiNDk1OGYzNzlhOWU2YjVhYTBj
10
+ OWM1M2IwOTljMWE5YTQzOWFjNWQ3M2Y1YWFiMWNjZDk0ZDA3YWRiZWRiYWNm
11
+ MGFkZTBlOTgxMzcwMWIzNjQyMGIwNzA2NjYxODJlYzJjZTQ3YWQ=
12
12
  data.tar.gz: !binary |-
13
- NmY4MDdkOTM1NzkxODU1N2NiN2U0N2Q2MTNiYTk0YjU4NGFmZTY2NDA4NjEz
14
- MWU5ODZhYTFkYWUwZGE4MmE4ZjZhNWU5ZGY5NDZkYzkxZjA3MGVmODgxOTEz
15
- MDM3ZDYwNTk5YTg1NjNkY2M1MWI5MDYxYzkwM2E0MzI2ZjllMzA=
13
+ MDIwM2Q2YTFlNmI5NjQyMWMwZjRhZjlmZWZiOTU5YzQwN2VjMjZjZjEwMDlm
14
+ N2FjMzcxY2U1ODgwMWFkZWM3ZDBlMmEwYTgwM2MwOTcyZjUzZjExZjExNWM4
15
+ ZGYxNDMyMjBhZjQyYTgwZDYyNmM3ZGIxMzkzMjY4ZjM5NGIxMTc=
data/.travis.yml CHANGED
@@ -2,22 +2,21 @@ language: ruby
2
2
 
3
3
  rvm:
4
4
  - 2.0.0
5
- - 1.8.7
5
+ # - 1.8.7
6
6
  - 1.9.3
7
7
 
8
8
  gemfile:
9
- # TODO: reenable once tests pass with 4.0
10
9
  - ci/Gemfile.rails-4.0.x
11
10
  - ci/Gemfile.rails-3.2.x
12
- - ci/Gemfile.rails-3.1.x
13
- - ci/Gemfile.rails-3.0.x
11
+ # - ci/Gemfile.rails-3.1.x
12
+ # - ci/Gemfile.rails-3.0.x
14
13
 
15
14
  env:
16
15
  - DB=sqlite
17
16
  - DB=mysql
18
17
  - DB=postgresql
19
18
 
20
- script: bundle exec rake
19
+ script: WITH_ADVISORY_LOCK_PREFIX=$TRAVIS_JOB_ID bundle exec rake --trace
21
20
 
22
21
  before_script:
23
22
  - mysql -e 'create database with_advisory_lock_test'
data/README.md CHANGED
@@ -6,6 +6,8 @@ or [PostgreSQL](http://www.postgresql.org/docs/9.1/static/functions-admin.html#F
6
6
  SQLite resorts to file locking.
7
7
 
8
8
  [![Build Status](https://api.travis-ci.org/mceachen/with_advisory_lock.png?branch=master)](https://travis-ci.org/mceachen/with_advisory_lock)
9
+ [![Gem Version](https://badge.fury.io/rb/with_advisory_lock.png)](http://rubygems.org/gems/with_advisory_lock)
10
+ [![Code Climate](https://codeclimate.com/github/mceachen/with_advisory_lock.png)](https://codeclimate.com/github/mceachen/with_advisory_lock)
9
11
 
10
12
  ## What's an "Advisory Lock"?
11
13
 
@@ -115,6 +117,16 @@ end
115
117
 
116
118
  ## Changelog
117
119
 
120
+ ### 0.0.9
121
+
122
+ * Merged in Postgis Adapter Support to address [issue 7](https://github.com/mceachen/with_advisory_lock/issues/7)
123
+ Thanks for the pull request, [Abdelkader Boudih](https://github.com/seuros)!
124
+ * The database switching code had to be duplicated by [Closure Tree](https://github.com/mceachen/closure_tree),
125
+ so I extracted a new ```WithAdvisoryLock::DatabaseAdapterSupport``` one-trick pony.
126
+ * Builds were failing on Travis, so I introduced a global lock prefix that can be set with the
127
+ ```WITH_ADVISORY_LOCK_PREFIX``` environment variable. I'm not going to advertise this feature yet.
128
+ It's a secret. Only you and I know, now. *shhh*
129
+
118
130
  ### 0.0.8
119
131
 
120
132
  * Addressed [issue 5](https://github.com/mceachen/with_advisory_lock/issues/5) by
@@ -2,4 +2,4 @@ source 'https://rubygems.org'
2
2
  gemspec :path => '..'
3
3
 
4
4
  # rspec-rails reverts to 2.3.1 (old and broken) unless you fetch the whole rails enchilada:
5
- gem 'rails', '4.0.0.rc2'
5
+ gem 'rails', '~> 4.0.0'
@@ -1,3 +1,5 @@
1
+ require 'zlib'
2
+
1
3
  module WithAdvisoryLock
2
4
  class Base
3
5
  attr_reader :connection, :lock_name, :timeout_seconds
@@ -5,6 +7,14 @@ module WithAdvisoryLock
5
7
  def initialize(connection, lock_name, timeout_seconds)
6
8
  @connection = connection
7
9
  @lock_name = lock_name
10
+ lock_name_prefix = ENV['WITH_ADVISORY_LOCK_PREFIX']
11
+ if lock_name_prefix
12
+ @lock_name = if lock_name.is_a? Numeric
13
+ "#{lock_name_prefix.to_i}#{lock_name}".to_i
14
+ else
15
+ "#{lock_name_prefix}#{lock_name}"
16
+ end
17
+ end
8
18
  @timeout_seconds = timeout_seconds
9
19
  end
10
20
 
@@ -28,6 +38,16 @@ module WithAdvisoryLock
28
38
  end
29
39
  end
30
40
 
41
+ def stable_hashcode(input)
42
+ if input.is_a? Numeric
43
+ input.to_i
44
+ else
45
+ # Ruby MRI's String#hash is randomly seeded as of Ruby 1.9 so
46
+ # make sure we use a deterministic hash.
47
+ Zlib.crc32(input.to_s)
48
+ end
49
+ end
50
+
31
51
  def yield_with_lock
32
52
  give_up_at = Time.now + @timeout_seconds if @timeout_seconds
33
53
  while @timeout_seconds.nil? || Time.now < give_up_at do
@@ -1,13 +1,12 @@
1
1
  # Tried desperately to monkeypatch the polymorphic connection object,
2
2
  # but rails autoloading is too clever by half. Pull requests are welcome.
3
3
 
4
- # Think of this module as a hipster, using "case" ironically.
5
-
4
+ require 'active_support/concern'
6
5
  require 'with_advisory_lock/base'
6
+ require 'with_advisory_lock/database_adapter_support'
7
+ require 'with_advisory_lock/flock'
7
8
  require 'with_advisory_lock/mysql'
8
9
  require 'with_advisory_lock/postgresql'
9
- require 'with_advisory_lock/flock'
10
- require 'active_support/concern'
11
10
 
12
11
  module WithAdvisoryLock
13
12
  module Concern
@@ -18,19 +17,18 @@ module WithAdvisoryLock
18
17
  end
19
18
 
20
19
  module ClassMethods
21
-
22
20
  def with_advisory_lock(lock_name, timeout_seconds=nil, &block)
23
- impl_class = case (connection.adapter_name.downcase)
24
- when "postgresql", "empostgresql"
25
- WithAdvisoryLock::PostgreSQL
26
- when "mysql", "mysql2"
27
- WithAdvisoryLock::MySQL
28
- else
29
- WithAdvisoryLock::Flock
21
+ das = WithAdvisoryLock::DatabaseAdapterSupport.new(connection)
22
+ impl_class = if das.postgresql?
23
+ WithAdvisoryLock::PostgreSQL
24
+ elsif das.mysql?
25
+ WithAdvisoryLock::MySQL
26
+ else
27
+ WithAdvisoryLock::Flock
30
28
  end
31
29
  impl = impl_class.new(connection, lock_name, timeout_seconds)
32
30
  impl.with_advisory_lock_if_needed(&block)
33
31
  end
34
32
  end
35
33
  end
36
- end
34
+ end
@@ -0,0 +1,19 @@
1
+ module WithAdvisoryLock
2
+ class DatabaseAdapterSupport
3
+ def initialize(connection)
4
+ @sym_name = connection.adapter_name.downcase.to_sym
5
+ end
6
+
7
+ def mysql?
8
+ [:mysql, :mysql2].include? @sym_name
9
+ end
10
+
11
+ def postgresql?
12
+ [:postgresql, :empostgresql, :postgis].include? @sym_name
13
+ end
14
+
15
+ def sqlite?
16
+ :sqlite3 == @sym_name
17
+ end
18
+ end
19
+ end
@@ -5,8 +5,8 @@ module WithAdvisoryLock
5
5
 
6
6
  def filename
7
7
  @filename ||= begin
8
- safe = @lock_name.gsub(/[^a-z0-9]/i, '')
9
- fn = ".lock-#{safe}-#{@lock_name.to_s.hash}"
8
+ safe = @lock_name.to_s.gsub(/[^a-z0-9]/i, '')
9
+ fn = ".lock-#{safe}-#{stable_hashcode(@lock_name)}"
10
10
  # Let the user specify a directory besides CWD.
11
11
  ENV['FLOCK_DIR'] ? File.expand_path(fn, ENV['FLOCK_DIR']) : fn
12
12
  end
@@ -1,4 +1,3 @@
1
- require 'zlib'
2
1
 
3
2
  module WithAdvisoryLock
4
3
  class PostgreSQL < Base
@@ -18,15 +17,7 @@ module WithAdvisoryLock
18
17
  end
19
18
 
20
19
  def numeric_lock
21
- @numeric_lock ||= begin
22
- if lock_name.is_a? Numeric
23
- lock_name.to_i
24
- else
25
- # Ruby MRI's String#hash is randomly seeded as of Ruby 1.9 so
26
- # make sure we use a deterministic hash.
27
- Zlib.crc32(lock_name.to_s)
28
- end
29
- end
20
+ @numeric_lock ||= stable_hashcode(lock_name)
30
21
  end
31
22
  end
32
23
  end
@@ -1,3 +1,3 @@
1
1
  module WithAdvisoryLock
2
- VERSION = "0.0.8"
2
+ VERSION = Gem::Version.new('0.0.9')
3
3
  end
data/test/nesting_test.rb CHANGED
@@ -1,6 +1,15 @@
1
1
  require 'minitest_helper'
2
2
 
3
3
  describe "lock nesting" do
4
+ before :each do
5
+ @prior_prefix = ENV['WITH_ADVISORY_LOCK_PREFIX']
6
+ ENV['WITH_ADVISORY_LOCK_PREFIX'] = nil
7
+ end
8
+
9
+ after :each do
10
+ ENV['WITH_ADVISORY_LOCK_PREFIX'] = @prior_prefix
11
+ end
12
+
4
13
  it "doesn't request the same lock twice" do
5
14
  impl = WithAdvisoryLock::Base.new(nil, nil, nil)
6
15
  impl.lock_stack.must_be_empty
@@ -16,7 +25,7 @@ describe "lock nesting" do
16
25
  end
17
26
 
18
27
  it "raises errors with MySQL when acquiring nested lock" do
19
- skip if env_db != 'mysql'
28
+ skip unless env_db == 'mysql'
20
29
  exc = proc {
21
30
  Tag.with_advisory_lock("first") do
22
31
  Tag.with_advisory_lock("second") do
@@ -1,12 +1,12 @@
1
1
  require 'minitest_helper'
2
2
 
3
- describe "simplest" do
4
- it "should prevent threads from accessing a resource concurrently" do
3
+ describe "prevents threads from accessing a resource concurrently" do
4
+ def assert_correct_parallel_behavior(lock_name)
5
5
  times = ActiveSupport::OrderedHash.new
6
6
  ActiveRecord::Base.connection_pool.disconnect!
7
7
  t1 = Thread.new do
8
8
  ActiveRecord::Base.connection.reconnect!
9
- ActiveRecord::Base.with_advisory_lock("simplest test") do
9
+ ActiveRecord::Base.with_advisory_lock(lock_name) do
10
10
  times[:t1_acquire] = Time.now
11
11
  sleep 0.5
12
12
  end
@@ -15,7 +15,7 @@ describe "simplest" do
15
15
  sleep 0.1
16
16
  t2 = Thread.new do
17
17
  ActiveRecord::Base.connection.reconnect!
18
- ActiveRecord::Base.with_advisory_lock("simplest test") do
18
+ ActiveRecord::Base.with_advisory_lock(lock_name) do
19
19
  times[:t2_acquire] = Time.now
20
20
  sleep 1
21
21
  end
@@ -26,4 +26,12 @@ describe "simplest" do
26
26
  times.keys.must_equal [:t1_acquire, :t1_release, :t2_acquire, :t2_release]
27
27
  times[:t2_acquire].must_be :>, times[:t1_release]
28
28
  end
29
+
30
+ it "with a string lock name" do
31
+ assert_correct_parallel_behavior("example lock name")
32
+ end
33
+
34
+ it "with a numeric lock name" do
35
+ assert_correct_parallel_behavior(1234)
36
+ end
29
37
  end
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.8
4
+ version: 0.0.9
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-06-22 00:00:00.000000000 Z
11
+ date: 2013-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -156,6 +156,7 @@ files:
156
156
  - lib/with_advisory_lock.rb
157
157
  - lib/with_advisory_lock/base.rb
158
158
  - lib/with_advisory_lock/concern.rb
159
+ - lib/with_advisory_lock/database_adapter_support.rb
159
160
  - lib/with_advisory_lock/flock.rb
160
161
  - lib/with_advisory_lock/mysql.rb
161
162
  - lib/with_advisory_lock/nested_advisory_lock_error.rb
@@ -166,7 +167,7 @@ files:
166
167
  - test/minitest_helper.rb
167
168
  - test/nesting_test.rb
168
169
  - test/parallelism_test.rb
169
- - test/simplest_test.rb
170
+ - test/simple_parallel_test.rb
170
171
  - test/test_models.rb
171
172
  - tests.sh
172
173
  - with_advisory_lock.gemspec
@@ -199,6 +200,6 @@ test_files:
199
200
  - test/minitest_helper.rb
200
201
  - test/nesting_test.rb
201
202
  - test/parallelism_test.rb
202
- - test/simplest_test.rb
203
+ - test/simple_parallel_test.rb
203
204
  - test/test_models.rb
204
205
  has_rdoc: