with_advisory_lock 4.0.0 → 5.0.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.
Files changed (40) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +80 -0
  3. data/.gitignore +3 -0
  4. data/.tool-versions +1 -0
  5. data/Appraisals +37 -11
  6. data/CHANGELOG.md +131 -0
  7. data/Gemfile +0 -12
  8. data/README.md +85 -171
  9. data/gemfiles/{activerecord_5.1.gemfile → activerecord_6.1.gemfile} +4 -2
  10. data/gemfiles/{activerecord_5.2.gemfile → activerecord_7.0.gemfile} +4 -2
  11. data/gemfiles/activerecord_7.1.gemfile +14 -0
  12. data/lib/with_advisory_lock/base.rb +16 -2
  13. data/lib/with_advisory_lock/concern.rb +13 -2
  14. data/lib/with_advisory_lock/database_adapter_support.rb +10 -3
  15. data/lib/with_advisory_lock/failed_to_acquire_lock.rb +7 -0
  16. data/lib/with_advisory_lock/flock.rb +4 -3
  17. data/lib/with_advisory_lock/mysql.rb +6 -16
  18. data/lib/with_advisory_lock/postgresql.rb +9 -7
  19. data/lib/with_advisory_lock/version.rb +3 -1
  20. data/lib/with_advisory_lock.rb +1 -1
  21. data/test/concern_test.rb +23 -10
  22. data/test/lock_test.rb +61 -28
  23. data/test/nesting_test.rb +14 -46
  24. data/test/options_test.rb +35 -33
  25. data/test/parallelism_test.rb +35 -37
  26. data/test/shared_test.rb +93 -90
  27. data/test/test_helper.rb +52 -0
  28. data/test/test_models.rb +9 -7
  29. data/test/thread_test.rb +23 -22
  30. data/test/transaction_test.rb +34 -36
  31. data/with_advisory_lock.gemspec +24 -23
  32. metadata +27 -41
  33. data/.travis.install-mysql-5.7.sh +0 -11
  34. data/.travis.yml +0 -32
  35. data/gemfiles/activerecord_4.2.gemfile +0 -19
  36. data/gemfiles/activerecord_5.0.gemfile +0 -19
  37. data/lib/with_advisory_lock/nested_advisory_lock_error.rb +0 -14
  38. data/test/database.yml +0 -17
  39. data/test/minitest_helper.rb +0 -40
  40. data/tests.sh +0 -11
@@ -1,35 +1,37 @@
1
- require 'minitest_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
2
4
  require 'forwardable'
3
5
 
4
- describe 'parallelism' do
5
- class FindOrCreateWorker
6
- extend Forwardable
7
- def_delegators :@thread, :join, :wakeup, :status, :to_s
6
+ class FindOrCreateWorker
7
+ extend Forwardable
8
+ def_delegators :@thread, :join, :wakeup, :status, :to_s
8
9
 
9
- def initialize(name, use_advisory_lock)
10
- @name = name
11
- @use_advisory_lock = use_advisory_lock
12
- @thread = Thread.new { work_later }
13
- end
10
+ def initialize(name, use_advisory_lock)
11
+ @name = name
12
+ @use_advisory_lock = use_advisory_lock
13
+ @thread = Thread.new { work_later }
14
+ end
14
15
 
15
- def work_later
16
- sleep
17
- ActiveRecord::Base.connection_pool.with_connection do
18
- if @use_advisory_lock
19
- Tag.with_advisory_lock(@name) { work }
20
- else
21
- work
22
- end
16
+ def work_later
17
+ sleep
18
+ ActiveRecord::Base.connection_pool.with_connection do
19
+ if @use_advisory_lock
20
+ Tag.with_advisory_lock(@name) { work }
21
+ else
22
+ work
23
23
  end
24
24
  end
25
+ end
25
26
 
26
- def work
27
- Tag.transaction do
28
- Tag.where(name: @name).first_or_create
29
- end
27
+ def work
28
+ Tag.transaction do
29
+ Tag.where(name: @name).first_or_create
30
30
  end
31
31
  end
32
+ end
32
33
 
34
+ class ParallelismTest < GemTestCase
33
35
  def run_workers
34
36
  @names = @iterations.times.map { |iter| "iteration ##{iter}" }
35
37
  @names.each do |name|
@@ -37,9 +39,7 @@ describe 'parallelism' do
37
39
  FindOrCreateWorker.new(name, @use_advisory_lock)
38
40
  end
39
41
  # Wait for all the threads to get ready:
40
- until workers.all? { |ea| ea.status == 'sleep' }
41
- sleep(0.1)
42
- end
42
+ sleep(0.1) until workers.all? { |ea| ea.status == 'sleep' }
43
43
  # OK, GO!
44
44
  workers.each(&:wakeup)
45
45
  # Then wait for them to finish:
@@ -49,29 +49,27 @@ describe 'parallelism' do
49
49
  ActiveRecord::Base.connection_pool.connection
50
50
  end
51
51
 
52
- before :each do
52
+ setup do
53
53
  ActiveRecord::Base.connection.reconnect!
54
54
  @workers = 10
55
55
  end
56
56
 
57
- # < SQLite, understandably, throws "The database file is locked (database is locked)"
58
-
59
- it 'creates multiple duplicate rows without advisory locks' do
60
- skip if env_db == :sqlite
57
+ test 'creates multiple duplicate rows without advisory locks' do
58
+ skip if %i[sqlite3 jdbcsqlite3].include?(env_db)
61
59
  @use_advisory_lock = false
62
60
  @iterations = 1
63
61
  run_workers
64
- Tag.all.size.must_be :>, @iterations # <- any duplicated rows will make me happy.
65
- TagAudit.all.size.must_be :>, @iterations # <- any duplicated rows will make me happy.
66
- Label.all.size.must_be :>, @iterations # <- any duplicated rows will make me happy.
62
+ assert_operator(Tag.all.size, :>, @iterations) # <- any duplicated rows will make me happy.
63
+ assert_operator(TagAudit.all.size, :>, @iterations) # <- any duplicated rows will make me happy.
64
+ assert_operator(Label.all.size, :>, @iterations) # <- any duplicated rows will make me happy.
67
65
  end
68
66
 
69
- it "doesn't create multiple duplicate rows with advisory locks" do
67
+ test "doesn't create multiple duplicate rows with advisory locks" do
70
68
  @use_advisory_lock = true
71
69
  @iterations = 10
72
70
  run_workers
73
- Tag.all.size.must_equal @iterations # <- any duplicated rows will NOT make me happy.
74
- TagAudit.all.size.must_equal @iterations # <- any duplicated rows will NOT make me happy.
75
- Label.all.size.must_equal @iterations # <- any duplicated rows will NOT make me happy.
71
+ assert_equal(@iterations, Tag.all.size) # <- any duplicated rows will NOT make me happy.
72
+ assert_equal(@iterations, TagAudit.all.size) # <- any duplicated rows will NOT make me happy.
73
+ assert_equal(@iterations, Label.all.size) # <- any duplicated rows will NOT make me happy.
76
74
  end
77
75
  end
data/test/shared_test.rb CHANGED
@@ -1,131 +1,134 @@
1
- require 'minitest_helper'
1
+ # frozen_string_literal: true
2
2
 
3
- describe 'shared locks' do
4
- def supported?
5
- env_db != :mysql
6
- end
7
-
8
- class SharedTestWorker
9
- def initialize(shared)
10
- @shared = shared
3
+ require 'test_helper'
4
+ class SharedTestWorker
5
+ def initialize(shared)
6
+ @shared = shared
11
7
 
12
- @locked = nil
13
- @cleanup = false
14
- @thread = Thread.new { work }
15
- end
8
+ @locked = nil
9
+ @cleanup = false
10
+ @thread = Thread.new { work }
11
+ end
16
12
 
17
- def locked?
18
- sleep 0.01 while @locked.nil? && @thread.alive?
19
- @locked
20
- end
13
+ def locked?
14
+ sleep 0.01 while @locked.nil? && @thread.alive?
15
+ @locked
16
+ end
21
17
 
22
- def cleanup!
23
- @cleanup = true
24
- @thread.join
25
- raise if @thread.status.nil?
26
- end
18
+ def cleanup!
19
+ @cleanup = true
20
+ @thread.join
21
+ raise if @thread.status.nil?
22
+ end
27
23
 
28
- private
24
+ private
29
25
 
30
- def work
31
- ActiveRecord::Base.connection_pool.with_connection do
32
- Tag.with_advisory_lock('test', timeout_seconds: 0, shared: @shared) do
33
- @locked = true
34
- sleep 0.01 until @cleanup
35
- end
36
- @locked = false
26
+ def work
27
+ ActiveRecord::Base.connection_pool.with_connection do
28
+ Tag.with_advisory_lock('test', timeout_seconds: 0, shared: @shared) do
29
+ @locked = true
37
30
  sleep 0.01 until @cleanup
38
31
  end
32
+ @locked = false
33
+ sleep 0.01 until @cleanup
39
34
  end
40
35
  end
36
+ end
37
+
38
+ class SharedLocksTest < GemTestCase
39
+ def supported?
40
+ %i[trilogy mysql2 jdbcmysql].exclude?(env_db)
41
+ end
41
42
 
42
- it 'does not allow two exclusive locks' do
43
+ test 'does not allow two exclusive locks' do
43
44
  one = SharedTestWorker.new(false)
44
- one.locked?.must_equal true
45
+ assert_predicate(one, :locked?)
45
46
 
46
47
  two = SharedTestWorker.new(false)
47
- two.locked?.must_equal false
48
+ refute(two.locked?)
48
49
 
49
50
  one.cleanup!
50
51
  two.cleanup!
51
52
  end
53
+ end
52
54
 
53
- describe 'not supported' do
54
- before do
55
- skip if supported?
56
- end
55
+ class NotSupportedEnvironmentTest < SharedLocksTest
56
+ setup do
57
+ skip if supported?
58
+ end
57
59
 
58
- it 'raises an error when attempting to use a shared lock' do
59
- one = SharedTestWorker.new(true)
60
- one.locked?.must_be_nil
61
- exception = proc {
62
- one.cleanup!
63
- }.must_raise ArgumentError
64
- exception.message.must_include 'not supported'
60
+ test 'raises an error when attempting to use a shared lock' do
61
+ one = SharedTestWorker.new(true)
62
+ assert_nil(one.locked?)
63
+
64
+ exception = assert_raises(ArgumentError) do
65
+ one.cleanup!
65
66
  end
67
+
68
+ assert_match(/#{Regexp.escape('not supported')}/, exception.message)
66
69
  end
70
+ end
67
71
 
68
- describe 'supported' do
69
- before do
70
- skip unless supported?
71
- end
72
+ class SupportedEnvironmentTest < SharedLocksTest
73
+ setup do
74
+ skip unless supported?
75
+ end
72
76
 
73
- it 'does allow two shared locks' do
74
- one = SharedTestWorker.new(true)
75
- one.locked?.must_equal true
77
+ test 'does allow two shared locks' do
78
+ one = SharedTestWorker.new(true)
79
+ assert_predicate(one, :locked?)
76
80
 
77
- two = SharedTestWorker.new(true)
78
- two.locked?.must_equal true
81
+ two = SharedTestWorker.new(true)
82
+ assert_predicate(two, :locked?)
79
83
 
80
- one.cleanup!
81
- two.cleanup!
82
- end
84
+ one.cleanup!
85
+ two.cleanup!
86
+ end
83
87
 
84
- it 'does not allow exclusive lock with shared lock' do
85
- one = SharedTestWorker.new(true)
86
- one.locked?.must_equal true
88
+ test 'does not allow exclusive lock with shared lock' do
89
+ one = SharedTestWorker.new(true)
90
+ assert_predicate(one, :locked?)
87
91
 
88
- two = SharedTestWorker.new(false)
89
- two.locked?.must_equal false
92
+ two = SharedTestWorker.new(false)
93
+ refute(two.locked?)
90
94
 
91
- three = SharedTestWorker.new(true)
92
- three.locked?.must_equal true
95
+ three = SharedTestWorker.new(true)
96
+ assert_predicate(three, :locked?)
93
97
 
94
- one.cleanup!
95
- two.cleanup!
96
- three.cleanup!
97
- end
98
+ one.cleanup!
99
+ two.cleanup!
100
+ three.cleanup!
101
+ end
98
102
 
99
- it 'does not allow shared lock with exclusive lock' do
100
- one = SharedTestWorker.new(false)
101
- one.locked?.must_equal true
103
+ test 'does not allow shared lock with exclusive lock' do
104
+ one = SharedTestWorker.new(false)
105
+ assert_predicate(one, :locked?)
102
106
 
103
- two = SharedTestWorker.new(true)
104
- two.locked?.must_equal false
107
+ two = SharedTestWorker.new(true)
108
+ refute(two.locked?)
105
109
 
106
- one.cleanup!
107
- two.cleanup!
108
- end
110
+ one.cleanup!
111
+ two.cleanup!
112
+ end
109
113
 
110
- describe 'PostgreSQL' do
111
- before do
112
- skip unless env_db == :postgresql
113
- end
114
+ class PostgreSQLTest < SupportedEnvironmentTest
115
+ setup do
116
+ skip unless env_db == :postgresql
117
+ end
114
118
 
115
- def pg_lock_modes
116
- ActiveRecord::Base.connection.select_values("SELECT mode FROM pg_locks WHERE locktype = 'advisory';")
117
- end
119
+ def pg_lock_modes
120
+ ActiveRecord::Base.connection.select_values("SELECT mode FROM pg_locks WHERE locktype = 'advisory';")
121
+ end
118
122
 
119
- it 'allows shared lock to be upgraded to an exclusive lock' do
120
- pg_lock_modes.must_equal %w[]
121
- Tag.with_advisory_lock 'test', shared: true do
122
- pg_lock_modes.must_equal %w[ShareLock]
123
- Tag.with_advisory_lock 'test', shared: false do
124
- pg_lock_modes.must_equal %w[ShareLock ExclusiveLock]
125
- end
123
+ test 'allows shared lock to be upgraded to an exclusive lock' do
124
+ assert_empty(pg_lock_modes)
125
+ Tag.with_advisory_lock 'test', shared: true do
126
+ assert_equal(%w[ShareLock], pg_lock_modes)
127
+ Tag.with_advisory_lock 'test', shared: false do
128
+ assert_equal(%w[ShareLock ExclusiveLock], pg_lock_modes)
126
129
  end
127
- pg_lock_modes.must_equal %w[]
128
130
  end
131
+ assert_empty(pg_lock_modes)
129
132
  end
130
133
  end
131
134
  end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+ require 'active_record'
5
+ require 'with_advisory_lock'
6
+ require 'tmpdir'
7
+ require 'securerandom'
8
+ begin
9
+ require 'activerecord-trilogy-adapter'
10
+ ActiveSupport.on_load(:active_record) do
11
+ require "trilogy_adapter/connection"
12
+ ActiveRecord::Base.public_send :extend, TrilogyAdapter::Connection
13
+ end
14
+ rescue LoadError
15
+ # do nothing
16
+ end
17
+
18
+ ActiveRecord::Base.configurations = {
19
+ default_env: {
20
+ url: ENV.fetch('DATABASE_URL', "sqlite3://#{Dir.tmpdir}/#{SecureRandom.hex}.sqlite3"),
21
+ properties: { allowPublicKeyRetrieval: true } # for JRuby madness
22
+ }
23
+ }
24
+
25
+ ENV['WITH_ADVISORY_LOCK_PREFIX'] ||= SecureRandom.hex
26
+
27
+ ActiveRecord::Base.establish_connection
28
+
29
+ def env_db
30
+ @env_db ||= ActiveRecord::Base.connection_db_config.adapter.to_sym
31
+ end
32
+
33
+ ActiveRecord::Migration.verbose = false
34
+
35
+ require 'test_models'
36
+ require 'minitest'
37
+ require 'maxitest/autorun'
38
+ require 'mocha/minitest'
39
+
40
+ class GemTestCase < ActiveSupport::TestCase
41
+ setup do
42
+ ENV['FLOCK_DIR'] = Dir.mktmpdir
43
+ Tag.delete_all
44
+ TagAudit.delete_all
45
+ Label.delete_all
46
+ end
47
+ teardown do
48
+ FileUtils.remove_entry_secure ENV['FLOCK_DIR']
49
+ end
50
+ end
51
+
52
+ puts "Testing with #{env_db} database, ActiveRecord #{ActiveRecord.gem_version} and #{RUBY_ENGINE} #{RUBY_ENGINE_VERSION} as #{RUBY_VERSION}"
data/test/test_models.rb CHANGED
@@ -1,12 +1,14 @@
1
- ActiveRecord::Schema.define(:version => 0) do
2
- create_table "tags", :force => true do |t|
3
- t.string "name"
1
+ # frozen_string_literal: true
2
+
3
+ ActiveRecord::Schema.define(version: 0) do
4
+ create_table 'tags', force: true do |t|
5
+ t.string 'name'
4
6
  end
5
- create_table "tag_audits", :id => false, :force => true do |t|
6
- t.string "tag_name"
7
+ create_table 'tag_audits', id: false, force: true do |t|
8
+ t.string 'tag_name'
7
9
  end
8
- create_table "labels", :id => false, :force => true do |t|
9
- t.string "name"
10
+ create_table 'labels', id: false, force: true do |t|
11
+ t.string 'name'
10
12
  end
11
13
  end
12
14
 
data/test/thread_test.rb CHANGED
@@ -1,16 +1,17 @@
1
- require 'minitest_helper'
1
+ # frozen_string_literal: true
2
2
 
3
- describe 'separate thread tests' do
4
- let(:lock_name) { 'testing 1,2,3' } # OMG COMMAS
3
+ require 'test_helper'
5
4
 
6
- before do
5
+ class SeparateThreadTest < GemTestCase
6
+ setup do
7
+ @lock_name = 'testing 1,2,3' # OMG COMMAS
7
8
  @mutex = Mutex.new
8
9
  @t1_acquired_lock = false
9
10
  @t1_return_value = nil
10
11
 
11
12
  @t1 = Thread.new do
12
13
  ActiveRecord::Base.connection_pool.with_connection do
13
- @t1_return_value = Label.with_advisory_lock(lock_name) do
14
+ @t1_return_value = Label.with_advisory_lock(@lock_name) do
14
15
  @mutex.synchronize { @t1_acquired_lock = true }
15
16
  sleep
16
17
  't1 finished'
@@ -19,42 +20,42 @@ describe 'separate thread tests' do
19
20
  end
20
21
 
21
22
  # Wait for the thread to acquire the lock:
22
- until @mutex.synchronize { @t1_acquired_lock } do
23
- sleep(0.1)
24
- end
23
+ sleep(0.1) until @mutex.synchronize { @t1_acquired_lock }
25
24
  ActiveRecord::Base.connection.reconnect!
26
25
  end
27
26
 
28
- after do
27
+ teardown do
29
28
  @t1.wakeup if @t1.status == 'sleep'
30
29
  @t1.join
31
30
  end
32
31
 
33
- it '#with_advisory_lock with a 0 timeout returns false immediately' do
34
- response = Label.with_advisory_lock(lock_name, 0) do
35
- fail 'should not be yielded to'
32
+ test '#with_advisory_lock with a 0 timeout returns false immediately' do
33
+ response = Label.with_advisory_lock(@lock_name, 0) do
34
+ raise 'should not be yielded to'
36
35
  end
37
- response.must_be_false
36
+ assert_not(response)
38
37
  end
39
38
 
40
- it '#with_advisory_lock yields to the provided block' do
41
- @t1_acquired_lock.must_be_true
39
+ test '#with_advisory_lock yields to the provided block' do
40
+ assert(@t1_acquired_lock)
42
41
  end
43
42
 
44
- it '#advisory_lock_exists? returns true when another thread has the lock' do
45
- Tag.advisory_lock_exists?(lock_name).must_be_true
43
+ test '#advisory_lock_exists? returns true when another thread has the lock' do
44
+ assert(Tag.advisory_lock_exists?(@lock_name))
46
45
  end
47
46
 
48
- it 'can re-establish the lock after the other thread releases it' do
47
+ test 'can re-establish the lock after the other thread releases it' do
49
48
  @t1.wakeup
50
49
  @t1.join
51
- @t1_return_value.must_equal 't1 finished'
50
+ assert_equal('t1 finished', @t1_return_value)
52
51
 
53
52
  # We should now be able to acquire the lock immediately:
54
53
  reacquired = false
55
- Label.with_advisory_lock(lock_name, 0) do
54
+ lock_result = Label.with_advisory_lock(@lock_name, 0) do
56
55
  reacquired = true
57
- end.must_be_true
58
- reacquired.must_be_true
56
+ end
57
+
58
+ assert(lock_result)
59
+ assert(reacquired)
59
60
  end
60
61
  end
@@ -1,70 +1,68 @@
1
- require 'minitest_helper'
1
+ # frozen_string_literal: true
2
2
 
3
- describe 'transaction scoping' do
3
+ require 'test_helper'
4
+
5
+ class TransactionScopingTest < GemTestCase
4
6
  def supported?
5
- env_db == :postgresql
7
+ %i[postgresql jdbcpostgresql].include?(env_db)
6
8
  end
7
9
 
8
- describe 'not supported' do
9
- before do
10
- skip if supported?
11
- end
10
+ test 'raises an error when attempting to use transaction level locks if not supported' do
11
+ skip if supported?
12
12
 
13
- it 'raises an error when attempting to use transaction level locks' do
14
- Tag.transaction do
15
- exception = proc {
16
- Tag.with_advisory_lock 'test', transaction: true do
17
- raise 'should not get here'
18
- end
19
- }.must_raise ArgumentError
20
- exception.message.must_include 'not supported'
13
+ Tag.transaction do
14
+ exception = assert_raises(ArgumentError) do
15
+ Tag.with_advisory_lock 'test', transaction: true do
16
+ raise 'should not get here'
17
+ end
21
18
  end
19
+
20
+ assert_match(/#{Regexp.escape('not supported')}/, exception.message)
22
21
  end
23
22
  end
24
23
 
25
- describe 'supported' do
26
- before do
24
+ class PostgresqlTest < TransactionScopingTest
25
+ setup do
27
26
  skip unless env_db == :postgresql
27
+ @pg_lock_count = lambda do
28
+ ActiveRecord::Base.connection.select_value("SELECT COUNT(*) FROM pg_locks WHERE locktype = 'advisory';").to_i
29
+ end
28
30
  end
29
31
 
30
- def pg_lock_count
31
- ActiveRecord::Base.connection.select_value("SELECT COUNT(*) FROM pg_locks WHERE locktype = 'advisory';").to_i
32
- end
33
-
34
- specify 'session locks release after the block executes' do
32
+ test 'session locks release after the block executes' do
35
33
  Tag.transaction do
36
- pg_lock_count.must_equal 0
34
+ assert_equal(0, @pg_lock_count.call)
37
35
  Tag.with_advisory_lock 'test' do
38
- pg_lock_count.must_equal 1
36
+ assert_equal(1, @pg_lock_count.call)
39
37
  end
40
- pg_lock_count.must_equal 0
38
+ assert_equal(0, @pg_lock_count.call)
41
39
  end
42
40
  end
43
41
 
44
- specify 'session locks release when transaction fails inside block' do
42
+ test 'session locks release when transaction fails inside block' do
45
43
  Tag.transaction do
46
- pg_lock_count.must_equal 0
44
+ assert_equal(0, @pg_lock_count.call)
47
45
 
48
- exception = proc {
46
+ exception = assert_raises(ActiveRecord::StatementInvalid) do
49
47
  Tag.with_advisory_lock 'test' do
50
48
  Tag.connection.execute 'SELECT 1/0;'
51
49
  end
52
- }.must_raise ActiveRecord::StatementInvalid
53
- exception.message.must_include 'division by zero'
50
+ end
54
51
 
55
- pg_lock_count.must_equal 0
52
+ assert_match(/#{Regexp.escape('division by zero')}/, exception.message)
53
+ assert_equal(0, @pg_lock_count.call)
56
54
  end
57
55
  end
58
56
 
59
- specify 'transaction level locks hold until the transaction completes' do
57
+ test 'transaction level locks hold until the transaction completes' do
60
58
  Tag.transaction do
61
- pg_lock_count.must_equal 0
59
+ assert_equal(0, @pg_lock_count.call)
62
60
  Tag.with_advisory_lock 'test', transaction: true do
63
- pg_lock_count.must_equal 1
61
+ assert_equal(1, @pg_lock_count.call)
64
62
  end
65
- pg_lock_count.must_equal 1
63
+ assert_equal(1, @pg_lock_count.call)
66
64
  end
67
- pg_lock_count.must_equal 0
65
+ assert_equal(0, @pg_lock_count.call)
68
66
  end
69
67
  end
70
68
  end
@@ -1,29 +1,30 @@
1
- lib = File.expand_path('../lib', __FILE__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require 'with_advisory_lock/version'
1
+ # frozen_string_literal: true
4
2
 
5
- Gem::Specification.new do |gem|
6
- gem.name = "with_advisory_lock"
7
- gem.version = WithAdvisoryLock::VERSION
8
- gem.authors = ['Matthew McEachen']
9
- gem.email = %w(matthew+github@mceachen.org)
10
- gem.homepage = 'https://github.com/mceachen/with_advisory_lock'
11
- gem.summary = %q{Advisory locking for ActiveRecord}
12
- gem.description = %q{Advisory locking for ActiveRecord}
13
- gem.license = 'MIT'
3
+ require 'English'
4
+ require_relative 'lib/with_advisory_lock/version'
14
5
 
15
- gem.files = `git ls-files`.split($/)
16
- gem.test_files = gem.files.grep(%r{^test/})
17
- gem.require_paths = %w(lib)
18
- gem.required_ruby_version = '>= 2.2.10'
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'with_advisory_lock'
8
+ spec.version = WithAdvisoryLock::VERSION
9
+ spec.authors = ['Matthew McEachen', 'Abdelkader Boudih']
10
+ spec.email = %w[matthew+github@mceachen.org terminale@gmail.com]
11
+ spec.homepage = 'https://github.com/ClosureTree/with_advisory_lock'
12
+ spec.summary = 'Advisory locking for ActiveRecord'
13
+ spec.description = 'Advisory locking for ActiveRecord'
14
+ spec.license = 'MIT'
19
15
 
20
- gem.add_runtime_dependency 'activerecord', '>= 4.2'
16
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
17
+ spec.test_files = spec.files.grep(%r{^test/})
18
+ spec.require_paths = %w[lib]
19
+ spec.metadata = { "rubyspecs_mfa_required" => "true" }
20
+ spec.required_ruby_version = '>= 2.7.0'
21
+ spec.metadata["yard.run"] = "yri"
21
22
 
23
+ spec.add_runtime_dependency 'activerecord', '>= 6.1'
22
24
 
23
- gem.add_development_dependency 'yard'
24
- gem.add_development_dependency 'minitest'
25
- gem.add_development_dependency 'minitest-great_expectations'
26
- gem.add_development_dependency 'minitest-reporters'
27
- gem.add_development_dependency 'mocha'
28
- gem.add_development_dependency 'appraisal'
25
+ spec.add_development_dependency 'appraisal'
26
+ spec.add_development_dependency 'maxitest'
27
+ spec.add_development_dependency 'minitest-reporters'
28
+ spec.add_development_dependency 'mocha'
29
+ spec.add_development_dependency 'yard'
29
30
  end