active_record_mutex 2.5.1 → 3.1.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.
@@ -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