active_record_mutex 2.2.1 → 2.3.0

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,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bae4a0303c87496334623532cdf84ebe36965400
4
- data.tar.gz: 3ff1f5b3142972f9e38b35dd6384efdc6141756f
3
+ metadata.gz: 82a2b14490ab51a0627c72260226d1742b1c0441
4
+ data.tar.gz: c487aa29472b77887e5dec81cd7f624676091d4a
5
5
  SHA512:
6
- metadata.gz: c6925871418c55c987de96784403d27b959af95bd07a5f27b9dbf97f9bcb5cf844875279aff404c9e39173af238dccec9b2a04f6c12513e712465430ac977d46
7
- data.tar.gz: ffa0d076563b3e3b86b66528c36b6c1eb95ddc597196036d34db6f5020c4f3d58aa58c430bd70a791a439f9a81d412cd42be81c0b8e0e3533b6b96f8e669a655
6
+ metadata.gz: 52337abd846212ae910f0d66ba99b39e35e02ad55a540e952dcbee8f195ec4c74d5dbc5f507d2f3dfa9e8b1189c6ba4e245805015893f561fdcd8c1eea4ca8fc
7
+ data.tar.gz: cbaceacb0cb2e06fef1b1d4a89b5940400e2a06213d7ab031f22f5151087357d0f5e8e092b9acdff49de08a8b133a8647ee064f8b9dea0fafbb82b8b85f9e4f8
data/README.md CHANGED
@@ -40,13 +40,6 @@ create Mutex instance like this:
40
40
 
41
41
  Now you can send all messages directly to the Mutex instance.
42
42
 
43
- ## Changes
44
-
45
- * 2016-08-19 Make locks rails environments independent
46
- * 2014-12-12 Release 2.0.0
47
- * 2014-12-12 Add license information
48
- * 2014-12-09 Adapt to newer Rails versions' API
49
-
50
43
  ## Download
51
44
 
52
45
  The homepage of this library is located at
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.2.1
1
+ 2.3.0
@@ -1,14 +1,14 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: active_record_mutex 2.2.1 ruby lib
2
+ # stub: active_record_mutex 2.3.0 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "active_record_mutex"
6
- s.version = "2.2.1"
6
+ s.version = "2.3.0"
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib"]
10
10
  s.authors = ["Florian Frank"]
11
- s.date = "2016-08-19"
11
+ s.date = "2016-08-23"
12
12
  s.description = "Mutex that can be used to synchronise ruby processes via an ActiveRecord datababase connection. (Only Mysql is supported at the moment.)"
13
13
  s.email = "flori@ping.de"
14
14
  s.extra_rdoc_files = ["README.md", "lib/active_record/database_mutex.rb", "lib/active_record/database_mutex/implementation.rb", "lib/active_record/database_mutex/version.rb", "lib/active_record/mutex.rb", "lib/active_record_mutex.rb"]
@@ -29,7 +29,7 @@ module ActiveRecord
29
29
  rescue ActiveRecord::DatabaseMutex::MutexLocked
30
30
  return nil
31
31
  ensure
32
- locked && unlock
32
+ locked and unlock
33
33
  end
34
34
 
35
35
  # Locks the mutex and returns true if successful. If the mutex is
@@ -58,9 +58,18 @@ module ActiveRecord
58
58
  # Unlocks the mutex and returns true if successful. Otherwise this method
59
59
  # raises a MutexLocked exception.
60
60
  def unlock(*)
61
- case query("SELECT RELEASE_LOCK(#{quote_value(name)})")
62
- when 1 then true
63
- when 0, nil then raise MutexUnlockFailed, "unlocking of mutex '#{name}' failed"
61
+ if aquired_lock?
62
+ decrease_counter
63
+ if counter_zero?
64
+ case query("SELECT RELEASE_LOCK(#{quote(name)})")
65
+ when 1
66
+ true
67
+ when 0, nil
68
+ raise MutexUnlockFailed, "unlocking of mutex '#{name}' failed"
69
+ end
70
+ end
71
+ else
72
+ raise MutexUnlockFailed, "unlocking of mutex '#{name}' failed"
64
73
  end
65
74
  end
66
75
 
@@ -75,7 +84,7 @@ module ActiveRecord
75
84
 
76
85
  # Returns true if this mutex is unlocked at the moment.
77
86
  def unlocked?
78
- query("SELECT IS_FREE_LOCK(#{quote_value(name)})") == 1
87
+ query("SELECT IS_FREE_LOCK(#{quote(name)})") == 1
79
88
  end
80
89
 
81
90
  # Returns true if this mutex is locked at the moment.
@@ -85,7 +94,7 @@ module ActiveRecord
85
94
 
86
95
  # Returns true if this mutex is locked by this database connection.
87
96
  def aquired_lock?
88
- query("SELECT CONNECTION_ID() = IS_USED_LOCK(#{quote_value(name)})") == 1
97
+ query("SELECT CONNECTION_ID() = IS_USED_LOCK(#{quote(name)})") == 1
89
98
  end
90
99
 
91
100
  # Returns true if this mutex is not locked by this database connection.
@@ -102,15 +111,45 @@ module ActiveRecord
102
111
 
103
112
  private
104
113
 
105
- def quote_value(value)
114
+ def quote(value)
106
115
  ActiveRecord::Base.connection.quote(value)
107
116
  end
108
117
 
118
+ def counter
119
+ "@#{name}_mutex_counter"
120
+ end
121
+
122
+ def increase_counter
123
+ query("SET #{counter} = IF(#{counter} IS NULL OR #{counter} = 0, 1, #{counter} + 1)")
124
+ end
125
+
126
+ def decrease_counter
127
+ query("SET #{counter} = #{counter} - 1")
128
+ end
129
+
130
+ def counter_value
131
+ query("SELECT #{counter}").to_i
132
+ end
133
+
134
+ def counter_zero?
135
+ counter_value.zero?
136
+ end
137
+
109
138
  def lock_with_timeout(opts = {})
110
- timeout = opts[:timeout] || 1
111
- case query("SELECT GET_LOCK(#{quote_value(name)}, #{timeout})")
112
- when 1 then true
113
- when 0 then raise MutexLocked, "mutex '#{name}' is already locked"
139
+ if aquired_lock?
140
+ increase_counter
141
+ true
142
+ else
143
+ timeout = opts[:timeout] || 1
144
+ case query("SELECT GET_LOCK(#{quote(name)}, #{timeout})")
145
+ when 1
146
+ increase_counter
147
+ true
148
+ when 0
149
+ raise MutexLocked, "mutex '#{name}' is already locked"
150
+ when nil
151
+ raise MutexSystemError, "mutex '#{name}' not locked due to system error"
152
+ end
114
153
  end
115
154
  end
116
155
 
@@ -1,6 +1,6 @@
1
1
  module ActiveRecord::DatabaseMutex
2
2
  # ActiveRecord::DatabaseMutex version
3
- VERSION = '2.2.1'
3
+ VERSION = '2.3.0'
4
4
  VERSION_ARRAY = VERSION.split('.').map(&:to_i) # :nodoc:
5
5
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
6
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
@@ -19,6 +19,8 @@ module ActiveRecord
19
19
 
20
20
  class MutexInvalidState < MutexError; end
21
21
 
22
+ class MutexSystemError < MutexError; end
23
+
22
24
  def self.included(modul)
23
25
  modul.instance_eval do
24
26
  extend ClassMethods
@@ -65,30 +65,39 @@ class DatabaseMutexTest < Test::Unit::TestCase
65
65
  def test_lock
66
66
  mutex = Implementation.new(:name => 'Lock')
67
67
  assert mutex.unlocked?
68
+ assert_equal 0, mutex.send(:counter_value)
68
69
  assert mutex.lock
69
70
  assert mutex.locked?
70
71
  assert mutex.aquired_lock?
72
+ assert_equal 1, mutex.send(:counter_value)
71
73
  assert mutex.lock
74
+ assert_equal 2, mutex.send(:counter_value)
72
75
  end
73
76
 
74
77
  def test_unlock
75
78
  mutex = Implementation.new(:name => 'Unlock')
76
79
  assert_raises(ActiveRecord::DatabaseMutex::MutexUnlockFailed) { mutex.unlock }
80
+ assert_equal 0, mutex.send(:counter_value)
77
81
  assert mutex.lock
78
82
  assert mutex.locked?
79
83
  assert mutex.aquired_lock?
84
+ assert_equal 1, mutex.send(:counter_value)
80
85
  assert mutex.unlock
81
86
  assert mutex.unlocked?
87
+ assert_equal 0, mutex.send(:counter_value)
82
88
  assert_raises(ActiveRecord::DatabaseMutex::MutexUnlockFailed) { mutex.unlock }
83
89
  end
84
90
 
85
91
  def test_synchronize
86
92
  mutex = Implementation.new(:name => 'Sync1')
87
93
  assert mutex.unlocked?
94
+ assert_equal 0, mutex.send(:counter_value)
88
95
  mutex.synchronize do
89
96
  assert mutex.locked?
97
+ assert_equal 1, mutex.send(:counter_value)
90
98
  end
91
99
  assert mutex.unlocked?
100
+ assert_equal 0, mutex.send(:counter_value)
92
101
  end
93
102
 
94
103
  def test_synchronize_exception
@@ -110,14 +119,24 @@ class DatabaseMutexTest < Test::Unit::TestCase
110
119
  def test_synchronize_nested
111
120
  mutex = Implementation.new(:name => 'Sync3')
112
121
  assert mutex.unlocked?
122
+ assert mutex.send(:counter_zero?)
123
+ assert_equal 0, mutex.send(:counter_value)
113
124
  mutex.synchronize do
114
125
  assert mutex.locked?
126
+ assert !mutex.send(:counter_zero?)
127
+ assert_equal 1, mutex.send(:counter_value)
115
128
  mutex.synchronize do
116
129
  assert mutex.locked?
130
+ assert !mutex.send(:counter_zero?)
131
+ assert_equal 2, mutex.send(:counter_value)
117
132
  end
118
133
  assert mutex.locked?
134
+ assert !mutex.send(:counter_zero?)
135
+ assert_equal 1, mutex.send(:counter_value)
119
136
  end
120
137
  assert mutex.unlocked?
138
+ assert mutex.send(:counter_zero?)
139
+ assert_equal 0, mutex.send(:counter_value)
121
140
  end
122
141
 
123
142
  def test_synchronize_already_locked
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record_mutex
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-19 00:00:00.000000000 Z
11
+ date: 2016-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gem_hadar