Skip to content
This repository was archived by the owner on Nov 3, 2023. It is now read-only.

Commit f5da3b0

Browse files
authored
fix(unlock): ensure callback and unlock (mhenrixon#771)
* chore(deps): update gems (solargraph is awesome) * fix(unlock): ensure unlock and callback runs * chore(lint): lint'em real good
1 parent 98a3e8e commit f5da3b0

File tree

13 files changed

+87
-76
lines changed

13 files changed

+87
-76
lines changed

Diff for: .github/workflows/lint.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
- uses: ruby/setup-ruby@v1
1515
with:
1616
ruby-version: 3.1
17-
bundler: 2.3.19
17+
bundler: 2.4.12
1818
bundler-cache: true
1919
- run: bin/bundle --jobs=$(nproc) --retry=$(nproc)
2020
- run: bin/rubocop -P
@@ -29,7 +29,7 @@ jobs:
2929
- uses: ruby/setup-ruby@v1
3030
with:
3131
ruby-version: 3.1
32-
bundler: 2.3.19
32+
bundler: 2.4.12
3333
bundler-cache: true
3434
- run: bin/bundle --jobs=$(nproc) --retry=$(nproc)
3535
- run: bin/reek .

Diff for: .github/workflows/rspec.yml

+4-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
- uses: ruby/setup-ruby@v1
2424
with:
2525
ruby-version: 3.2
26-
bundler: 2.4.2
26+
bundler: 2.4.12
2727
bundler-cache: true
2828

2929
- name: Install Code Climate reporter
@@ -59,14 +59,15 @@ jobs:
5959
strategy:
6060
fail-fast: true
6161
matrix:
62-
ruby: [2.7, '3.0', 3.1]
62+
ruby: [2.7, '3.0', 3.1, 3.2]
6363

6464
steps:
6565
- uses: actions/checkout@v3
6666
- uses: ruby/setup-ruby@v1
6767
with:
6868
ruby-version: ${{ matrix.ruby }}
69-
bundler: 2.4.2
69+
bundler: 2.4.12
7070
bundler-cache: true
71+
- run: bundle install --gemfile='./gemfiles/sidekiq_7.0.gemfile' --retry 1
7172
- run: bin/appraisal install --jobs=$(nproc) --retry=$(nproc)
7273
- run: bin/appraisal rspec --require spec_helper --tag ~perf

Diff for: Gemfile

-2
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,10 @@ end
3131

3232
if respond_to?(:install_if)
3333
install_if -> { RUBY_PLATFORM.include?("darwin") } do
34-
gem "fasterer"
3534
gem "fuubar"
3635
gem "github_changelog_generator"
3736
gem "pry"
3837
gem "redcarpet", "~> 3.4"
39-
gem "rspec-nc"
4038
gem "ruby-prof", ">= 0.17.0", require: false
4139
gem "stackprof", ">= 0.2.9", require: false
4240
gem "test-prof"

Diff for: bin/bundle

+2
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,11 @@ m = Module.new do
6363
end
6464

6565
def bundler_version
66+
# rubocop:disable ThreadSafety/InstanceVariableInClassMethod
6667
@bundler_version ||=
6768
env_var_version || cli_arg_version ||
6869
lockfile_version
70+
# rubocop:enable ThreadSafety/InstanceVariableInClassMethod
6971
end
7072

7173
def bundler_requirement

Diff for: gemfiles/sidekiq_7.0.gemfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
source "https://rubygems.org"
44

55
gem "appraisal"
6+
gem "faraday-retry"
67
gem "gem-release"
78
gem "github-markup"
89
gem "rack-test"
910
gem "rake", "13.0.3"
10-
gem "redis-namespace"
1111
gem "reek", ">= 5.3"
1212
gem "rspec"
1313
gem "rspec-benchmark"

Diff for: lib/sidekiq_unique_jobs/lock/until_executed.rb

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def lock(&block)
3535
def execute
3636
executed = locksmith.execute do
3737
yield
38+
ensure
3839
unlock_and_callback
3940
end
4041

Diff for: lib/sidekiq_unique_jobs/lock/while_executing.rb

+1-2
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,8 @@ def execute(&block)
4242
with_logging_context do
4343
executed = locksmith.execute do
4444
yield
45-
callback_safely if locksmith.unlock
4645
ensure
47-
locksmith.unlock
46+
unlock_and_callback
4847
end
4948

5049
unless executed

Diff for: lib/sidekiq_unique_jobs/orphans/manager.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def stop
7272
# @return [<type>] <description>
7373
#
7474
def task
75-
@task ||= default_task
75+
@task ||= default_task # rubocop:disable ThreadSafety/InstanceVariableInClassMethod
7676
end
7777

7878
#
@@ -100,7 +100,7 @@ def default_task
100100
# @return [void]
101101
#
102102
def task=(task)
103-
@task = task
103+
@task = task # rubocop:disable ThreadSafety/InstanceVariableInClassMethod
104104
end
105105

106106
#

Diff for: lib/sidekiq_unique_jobs/sidekiq_unique_jobs.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ module SidekiqUniqueJobs # rubocop:disable Metrics/ModuleLength
1717
# @return [SidekiqUniqueJobs::Config] the gem configuration
1818
#
1919
def config
20-
@config ||= reset!
20+
@config ||= reset! # rubocop:disable ThreadSafety/InstanceVariableInClassMethod
2121
end
2222

2323
#
@@ -108,7 +108,7 @@ def use_config(tmp_config = {})
108108
# @return [SidekiqUniqueJobs::Config] a default gem configuration
109109
#
110110
def reset!
111-
@config = SidekiqUniqueJobs::Config.default
111+
@config = SidekiqUniqueJobs::Config.default # rubocop:disable ThreadSafety/InstanceVariableInClassMethod
112112
end
113113

114114
#
@@ -288,7 +288,7 @@ def safe_constantize(str)
288288
# @return [Reflections]
289289
#
290290
def reflections
291-
@reflections ||= Reflections.new
291+
@reflections ||= Reflections.new # rubocop:disable ThreadSafety/InstanceVariableInClassMethod
292292
end
293293

294294
#

Diff for: myapp/.tool-versions

+4-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
ruby 3.2.0
1+
ruby 3.2.2
2+
nodejs 19.1.0
3+
yarn 1.22.19
4+
direnv 2.32.2

Diff for: spec/sidekiq_unique_jobs/lock/while_executing_spec.rb

+8-2
Original file line numberDiff line numberDiff line change
@@ -77,27 +77,33 @@
7777
context "when no callback is defined" do
7878
let(:job_class) { WhileExecutingRescheduleJob }
7979
let(:callback_one) { -> { true } }
80-
let(:callback_two) { nil }
80+
let(:callback_two) { -> { true } }
8181

8282
let(:strategy_one) { process_one.send(:server_strategy) }
8383
let(:strategy_two) { process_two.send(:server_strategy) }
8484

8585
before do
8686
allow(strategy_one).to receive(:call).and_call_original
8787
allow(strategy_two).to receive(:call).and_call_original
88+
allow(process_one).to receive(:reflect).and_call_original
8889
allow(process_two).to receive(:reflect).and_call_original
8990
end
9091

9192
it "reflects execution_failed" do
9293
process_one.execute do
9394
process_two.execute { puts "BOGUS!" }
95+
# NOTE: Below looks weird but tests that
96+
# the result from process_two (which is nil) isn't considered.
97+
jid_one
9498
end
9599

100+
expect(process_one).not_to have_received(:reflect).with(:execution_failed, item_one)
96101
expect(callback_one).to have_received(:call).once
97102
expect(strategy_one).not_to have_received(:call)
98-
expect(strategy_two).to have_received(:call).once
99103

100104
expect(process_two).to have_received(:reflect).with(:execution_failed, item_two)
105+
expect(callback_two).not_to have_received(:call)
106+
expect(strategy_two).to have_received(:call).once
101107
end
102108
end
103109

Diff for: spec/support/shared_examples/a_lockable_lock.rb

-58
Original file line numberDiff line numberDiff line change
@@ -35,61 +35,3 @@
3535
end
3636
end
3737
end
38-
39-
RSpec.shared_examples "an executing lock implementation" do
40-
context "when job can't be locked" do
41-
before do
42-
allow(process_one.locksmith).to receive(:execute).and_return(nil)
43-
end
44-
45-
it "does not execute" do
46-
unset = true
47-
process_one.execute { unset = false }
48-
expect(unset).to be(true)
49-
end
50-
end
51-
52-
context "when process_one executes the job" do
53-
before { process_one.lock }
54-
55-
it "keeps being locked while executing" do
56-
process_one.execute do
57-
expect(process_one).to be_locked
58-
end
59-
end
60-
61-
it "keeps being locked when an error is raised" do
62-
allow(process_one.locksmith).to receive(:execute).and_raise(RuntimeError, "Hell")
63-
64-
expect { process_one.execute { "hey ho" } }.to raise_error("Hell")
65-
66-
expect(process_one).to be_locked
67-
end
68-
69-
it "prevents process_two from locking" do
70-
process_one.execute do
71-
expect(process_two.lock).to be_nil
72-
expect(process_two).not_to be_locked
73-
end
74-
end
75-
76-
it "prevents process_two from executing" do
77-
expect { process_two.execute { raise "Hell" } }.not_to raise_error
78-
end
79-
80-
it "reflects execution_failed on failure" do
81-
allow(process_two).to receive(:reflect).and_call_original
82-
process_two.execute { puts "Failed to execute" }
83-
84-
expect(process_two).to have_received(:reflect).with(:execution_failed, item_two)
85-
end
86-
87-
it "yields without arguments" do
88-
process_one.lock
89-
process_one.execute {}
90-
blk = -> {}
91-
92-
expect { process_one.execute(&blk) }.not_to raise_error
93-
end
94-
end
95-
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.shared_examples "an executing lock implementation" do
4+
context "when job can't be locked" do
5+
before do
6+
allow(process_one.locksmith).to receive(:execute).and_return(nil)
7+
end
8+
9+
it "does not execute" do
10+
unset = true
11+
process_one.execute { unset = false }
12+
expect(unset).to be(true)
13+
end
14+
end
15+
16+
context "when process_one executes the job" do
17+
before { process_one.lock }
18+
19+
it "keeps being locked while executing" do
20+
process_one.execute do
21+
expect(process_one).to be_locked
22+
end
23+
end
24+
25+
it "keeps being locked when an error is raised" do
26+
allow(process_one.locksmith).to receive(:execute).and_raise(RuntimeError, "Hell")
27+
28+
expect { process_one.execute { "hey ho" } }.to raise_error("Hell")
29+
30+
expect(process_one).to be_locked
31+
end
32+
33+
it "prevents process_two from locking" do
34+
process_one.execute do
35+
expect(process_two.lock).to be_nil
36+
expect(process_two).not_to be_locked
37+
end
38+
end
39+
40+
it "prevents process_two from executing" do
41+
expect { process_two.execute { raise "Hell" } }.not_to raise_error
42+
end
43+
44+
it "reflects execution_failed on failure" do
45+
allow(process_two).to receive(:reflect).and_call_original
46+
process_two.execute { puts "Failed to execute" }
47+
48+
expect(process_two).to have_received(:reflect).with(:execution_failed, item_two)
49+
end
50+
51+
it "yields without arguments" do
52+
process_one.lock
53+
process_one.execute {}
54+
blk = -> {}
55+
56+
expect { process_one.execute(&blk) }.not_to raise_error
57+
end
58+
end
59+
end

0 commit comments

Comments
 (0)