active_record_mutex 2.5.1 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,6 +6,10 @@ class DatabaseMutexTest < Test::Unit::TestCase
6
6
  class Foo < ActiveRecord::Base; end
7
7
 
8
8
  def setup
9
+ Foo.instance_eval do
10
+ @mutex_name = nil
11
+ @mutex = nil
12
+ end
9
13
  ActiveRecord::Schema.define(:version => 1) do
10
14
  create_table(:foos, :force => true) { |t| t.string :bar }
11
15
  end
@@ -19,9 +23,6 @@ class DatabaseMutexTest < Test::Unit::TestCase
19
23
 
20
24
  def test_class_method_mutex
21
25
  old, ENV['RAILS_ENV'] = ENV['RAILS_ENV'], nil
22
- Foo.instance_eval do
23
- @mutex = nil
24
- end
25
26
  mutex = Foo.mutex
26
27
  assert_kind_of ActiveRecord::DatabaseMutex::Implementation, mutex
27
28
  assert_equal Foo.name, mutex.name
@@ -31,9 +32,6 @@ class DatabaseMutexTest < Test::Unit::TestCase
31
32
 
32
33
  def test_class_method_mutex_within_env
33
34
  old, ENV['RAILS_ENV'] = ENV['RAILS_ENV'], 'test'
34
- Foo.instance_eval do
35
- @mutex = nil
36
- end
37
35
  mutex = Foo.mutex
38
36
  assert_kind_of ActiveRecord::DatabaseMutex::Implementation, mutex
39
37
  assert_equal "#{Foo.name}@test", mutex.name
@@ -65,29 +63,126 @@ class DatabaseMutexTest < Test::Unit::TestCase
65
63
  def test_lock
66
64
  mutex = Implementation.new(:name => 'Lock')
67
65
  assert mutex.unlocked?
66
+ assert mutex.not_owned?
68
67
  assert_equal 0, mutex.send(:counter_value)
69
68
  assert mutex.lock
70
69
  assert mutex.locked?
71
- assert mutex.aquired_lock?
70
+ assert mutex.owned?
72
71
  assert_equal 1, mutex.send(:counter_value)
73
72
  assert mutex.lock
74
73
  assert_equal 2, mutex.send(:counter_value)
75
74
  end
76
75
 
76
+ def test_lock_with_timeout_multiple_threads
77
+ done = false
78
+ thread = Thread.new do
79
+ ActiveRecord::Base.connection_pool.with_connection do
80
+ Implementation.new(:name => 'LockTimeout').synchronize {
81
+ done = true
82
+ sleep 2
83
+ }
84
+ end
85
+ ensure
86
+ done = true
87
+ end
88
+ mutex = Implementation.new(:name => 'LockTimeout')
89
+ until done
90
+ sleep 0.1
91
+ end
92
+ assert_false mutex.lock(timeout: 0.1, raise: false)
93
+ assert_raises(ActiveRecord::DatabaseMutex::MutexLocked) { mutex.lock(timeout: 0.1) }
94
+ thread.join
95
+ assert mutex.unlocked?
96
+ assert_false mutex.owned?
97
+ assert_equal 0, mutex.send(:counter_value)
98
+ assert mutex.lock(timeout: 1)
99
+ assert mutex.locked?
100
+ assert mutex.owned?
101
+ assert_equal 1, mutex.send(:counter_value)
102
+ end
103
+
104
+ def test_lock_without_timeout_multiple_threads
105
+ done = false
106
+ thread = Thread.new do
107
+ ActiveRecord::Base.connection_pool.with_connection do
108
+ Implementation.new(:name => 'SpinTimeout').synchronize {
109
+ done = true
110
+ sleep 2
111
+ }
112
+ end
113
+ ensure
114
+ done = true
115
+ end
116
+ mutex = Implementation.new(:name => 'SpinTimeout')
117
+ until done
118
+ sleep 0.1
119
+ end
120
+ thread.join
121
+ assert mutex.lock
122
+ assert mutex.locked?
123
+ assert mutex.owned?
124
+ assert_equal 1, mutex.send(:counter_value)
125
+ end
126
+
77
127
  def test_unlock
78
128
  mutex = Implementation.new(:name => 'Unlock')
79
129
  assert_raises(ActiveRecord::DatabaseMutex::MutexUnlockFailed) { mutex.unlock }
80
130
  assert_equal 0, mutex.send(:counter_value)
81
131
  assert mutex.lock
82
132
  assert mutex.locked?
83
- assert mutex.aquired_lock?
133
+ assert mutex.owned?
134
+ assert_equal 1, mutex.send(:counter_value)
135
+ assert mutex.lock
136
+ assert mutex.locked?
137
+ assert mutex.owned?
138
+ assert_equal 2, mutex.send(:counter_value)
139
+ assert_false mutex.unlock
140
+ assert_false mutex.unlocked?
141
+ assert_false mutex.not_owned?
84
142
  assert_equal 1, mutex.send(:counter_value)
85
143
  assert mutex.unlock
86
144
  assert mutex.unlocked?
145
+ assert mutex.not_owned?
87
146
  assert_equal 0, mutex.send(:counter_value)
88
147
  assert_raises(ActiveRecord::DatabaseMutex::MutexUnlockFailed) { mutex.unlock }
89
148
  end
90
149
 
150
+ def test_unlock_with_force
151
+ mutex = Implementation.new(:name => 'Unlock')
152
+ assert_false mutex.unlock raise: false
153
+ assert_raises(ActiveRecord::DatabaseMutex::MutexUnlockFailed) { mutex.unlock }
154
+ assert_equal 0, mutex.send(:counter_value)
155
+ assert mutex.lock
156
+ assert mutex.locked?
157
+ assert mutex.owned?
158
+ assert_equal 1, mutex.send(:counter_value)
159
+ assert mutex.lock
160
+ assert mutex.locked?
161
+ assert mutex.owned?
162
+ assert_equal 2, mutex.send(:counter_value)
163
+ assert mutex.unlock force: true
164
+ assert mutex.unlocked?
165
+ assert mutex.not_owned?
166
+ assert_equal 0, mutex.send(:counter_value)
167
+ assert_false mutex.unlock force: true, raise: false
168
+ assert_raises(ActiveRecord::DatabaseMutex::MutexUnlockFailed) { mutex.unlock force: true }
169
+ end
170
+
171
+ def test_unlock?
172
+ mutex = Implementation.new(:name => 'Unlock')
173
+ assert_nil mutex.unlock?
174
+ assert_equal 0, mutex.send(:counter_value)
175
+ assert mutex.lock
176
+ assert mutex.locked?
177
+ assert mutex.owned?
178
+ assert_equal 1, mutex.send(:counter_value)
179
+ assert mutex.unlock?
180
+ assert mutex.unlocked?
181
+ assert mutex.not_owned?
182
+ assert_equal 0, mutex.send(:counter_value)
183
+ assert_nil mutex.unlock?
184
+ end
185
+
91
186
  def test_synchronize
92
187
  mutex = Implementation.new(:name => 'Sync1')
93
188
  assert mutex.unlocked?
@@ -100,6 +195,30 @@ class DatabaseMutexTest < Test::Unit::TestCase
100
195
  assert_equal 0, mutex.send(:counter_value)
101
196
  end
102
197
 
198
+ def test_synchronize_two_threads
199
+ done = false
200
+ thread = Thread.new do
201
+ ActiveRecord::Base.connection_pool.with_connection do
202
+ Implementation.new(:name => 'Sync1').synchronize {
203
+ done = true
204
+ sleep 2
205
+ }
206
+ end
207
+ ensure
208
+ done = true
209
+ end
210
+ mutex = Implementation.new(:name => 'Sync1')
211
+ yielded = false
212
+ until done
213
+ sleep 0.1
214
+ end
215
+ mutex.synchronize(block: false) { yielded = true }
216
+ assert_false yielded
217
+ thread.join
218
+ mutex.synchronize(block: false) { yielded = true }
219
+ assert yielded
220
+ end
221
+
103
222
  def test_synchronize_exception
104
223
  mutex = Implementation.new(:name => 'Sync2')
105
224
  exception = Class.new StandardError
@@ -147,8 +266,13 @@ class DatabaseMutexTest < Test::Unit::TestCase
147
266
  assert_nil mutex.synchronize {}
148
267
  end
149
268
 
269
+ def test_internal_name
270
+ mutex = Implementation.new(:name => (250..255).map(&:chr) * '')
271
+ assert_equal '$3i3xQvUrNPGyH6kaIOkiPw', mutex.send(:internal_name)
272
+ end
273
+
150
274
  def test_counter_name
151
275
  mutex = Implementation.new(:name => (250..255).map(&:chr) * '')
152
- assert_equal '@$_vv8.f7.', mutex.send(:counter)
276
+ assert_equal '@$3i3xQvUrNPGyH6kaIOkiPw', mutex.send(:counter)
153
277
  end
154
278
  end
data/test/test_helper.rb CHANGED
@@ -6,15 +6,14 @@ if ENV['START_SIMPLECOV'].to_i == 1
6
6
  end
7
7
 
8
8
  require 'active_record'
9
- $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
10
9
  require 'active_record/database_mutex'
10
+ require 'debug'
11
+
12
+ database_url = URI.parse(ENV.fetch('DATABASE_URL'))
13
+ database = File.basename(database_url.path)
14
+ database_url_without_db = database_url.dup.tap { _1.path = '' }
15
+ ch = ActiveRecord::Base.establish_connection(database_url_without_db.to_s)
16
+ ch.with_connection { _1.execute %{ CREATE DATABASE IF NOT EXISTS #{database} } }
17
+ ActiveRecord::Base.establish_connection(database_url.to_s)
11
18
 
12
- ActiveRecord::Base.establish_connection(
13
- :adapter => "mysql2",
14
- :database => ENV['DATABASE'] || "test",
15
- :username => ENV['USER'],
16
- :password => ENV['PASSWORD'],
17
- :host => ENV['HOST'] || 'localhost'
18
- )
19
19
  require 'test/unit'
20
- require 'byebug'
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.5.1
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-07 00:00:00.000000000 Z
11
+ date: 2024-10-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gem_hadar
@@ -16,14 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.9.1
19
+ version: '1.19'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.9.1
26
+ version: '1.19'
27
+ - !ruby/object:Gem::Dependency
28
+ name: all_images
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.6'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.6'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: test-unit
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -39,7 +53,7 @@ dependencies:
39
53
  - !ruby/object:Gem::Version
40
54
  version: '3.0'
41
55
  - !ruby/object:Gem::Dependency
42
- name: byebug
56
+ name: debug
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - ">="
@@ -72,14 +86,14 @@ dependencies:
72
86
  requirements:
73
87
  - - "~>"
74
88
  - !ruby/object:Gem::Version
75
- version: 0.3.0
89
+ version: '0.3'
76
90
  type: :runtime
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: 0.3.0
96
+ version: '0.3'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: activerecord
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -87,9 +101,6 @@ dependencies:
87
101
  - - ">="
88
102
  - !ruby/object:Gem::Version
89
103
  version: '4.0'
90
- - - "<"
91
- - !ruby/object:Gem::Version
92
- version: '6'
93
104
  type: :runtime
94
105
  prerelease: false
95
106
  version_requirements: !ruby/object:Gem::Requirement
@@ -97,23 +108,20 @@ dependencies:
97
108
  - - ">="
98
109
  - !ruby/object:Gem::Version
99
110
  version: '4.0'
100
- - - "<"
101
- - !ruby/object:Gem::Version
102
- version: '6'
103
111
  - !ruby/object:Gem::Dependency
104
- name: tins
112
+ name: ostruct
105
113
  requirement: !ruby/object:Gem::Requirement
106
114
  requirements:
107
115
  - - "~>"
108
116
  - !ruby/object:Gem::Version
109
- version: '1.12'
117
+ version: '0.6'
110
118
  type: :runtime
111
119
  prerelease: false
112
120
  version_requirements: !ruby/object:Gem::Requirement
113
121
  requirements:
114
122
  - - "~>"
115
123
  - !ruby/object:Gem::Version
116
- version: '1.12'
124
+ version: '0.6'
117
125
  description: Mutex that can be used to synchronise ruby processes via an ActiveRecord
118
126
  datababase connection. (Only Mysql is supported at the moment.)
119
127
  email: flori@ping.de
@@ -127,14 +135,16 @@ extra_rdoc_files:
127
135
  - lib/active_record/mutex.rb
128
136
  - lib/active_record_mutex.rb
129
137
  files:
130
- - ".gitignore"
131
- - ".travis.yml"
138
+ - ".envrc"
139
+ - CHANGES.md
132
140
  - COPYING
133
141
  - Gemfile
134
142
  - README.md
135
143
  - Rakefile
136
- - VERSION
137
144
  - active_record_mutex.gemspec
145
+ - docker-compose.yml
146
+ - examples/process1.rb
147
+ - examples/process2.rb
138
148
  - lib/active_record/database_mutex.rb
139
149
  - lib/active_record/database_mutex/implementation.rb
140
150
  - lib/active_record/database_mutex/version.rb
@@ -146,7 +156,7 @@ homepage: http://github.com/flori/active_record_mutex
146
156
  licenses:
147
157
  - GPL-2
148
158
  metadata: {}
149
- post_install_message:
159
+ post_install_message:
150
160
  rdoc_options:
151
161
  - "--title"
152
162
  - ActiveRecordMutex - Implementation of a Mutex for Active Record
@@ -165,9 +175,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
165
175
  - !ruby/object:Gem::Version
166
176
  version: '0'
167
177
  requirements: []
168
- rubyforge_project:
169
- rubygems_version: 2.6.8
170
- signing_key:
178
+ rubygems_version: 3.5.18
179
+ signing_key:
171
180
  specification_version: 4
172
181
  summary: Implementation of a Mutex for Active Record
173
182
  test_files:
data/.gitignore DELETED
@@ -1,6 +0,0 @@
1
- .*.sw[pon]
2
- .DS_Store
3
- .byebug_history
4
- Gemfile.lock
5
- coverage
6
- pkg
data/.travis.yml DELETED
@@ -1,20 +0,0 @@
1
- rvm:
2
- - 2.0
3
- - 2.1
4
- - 2.2
5
- - 2.3.3
6
- - jruby-head
7
- matrix:
8
- allow_failures:
9
- - rvm: ruby-head
10
- - rvm: jruby-head
11
- before_script:
12
- - mysql -e 'create database test;'
13
- script:
14
- - rake && codeclimate-test-reporter --file coverage
15
- sudo: false
16
- addons:
17
- code_climate:
18
- repo_token: 316615e61480039c3444f59bf124cf810d31110326e51f133e9cc9852de14892
19
- env:
20
- - START_SIMPLECOV=1
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 2.5.1