with_advisory_lock 0.0.8 → 0.0.9

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