canvas_sync 0.22.0.beta8 → 0.22.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/canvas_sync/job_batches/compat/sidekiq.rb +1 -1
- data/lib/canvas_sync/job_uniqueness/compat/active_job.rb +1 -1
- data/lib/canvas_sync/job_uniqueness/compat/sidekiq.rb +2 -2
- data/lib/canvas_sync/job_uniqueness/lock_context.rb +2 -2
- data/lib/canvas_sync/job_uniqueness/locksmith.rb +1 -3
- data/lib/canvas_sync/job_uniqueness/strategy/base.rb +1 -6
- data/lib/canvas_sync/jobs/canvas_process_waiter.rb +1 -1
- data/lib/canvas_sync/version.rb +1 -1
- data/spec/job_batching/compat/sidekiq_spec.rb +1 -1
- data/spec/job_uniqueness/on_conflict/reschedule_spec.rb +39 -0
- data/spec/job_uniqueness/spec_helper.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d55ef789158e71984651c554186f25c0206632712483cb1f196f0f772183641f
|
4
|
+
data.tar.gz: e88f323145871f95d6979bd4c089fd9c993a5118e2075feb0e96257b96dad8ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34e5d02b710c1252657dd7d675b85d085a69bc6c03b0e52285f7264f5c7f5119113c6164bb148979eabf8a1c24be6f1f781ff28b61f9faf0aed331321369e598
|
7
|
+
data.tar.gz: 74f7b996899e7e4d45f74f04aabf2d098f0531c0bbae5594cfbc604661d0762aa765a9ea4d94358ebc40cbbfaeef1dfb5219c4ab8eb2be50cd3044290b7139e9
|
@@ -45,7 +45,7 @@ module CanvasSync::JobBatches
|
|
45
45
|
|
46
46
|
def call(_worker, msg, _queue, _redis_pool = nil)
|
47
47
|
if (batch = Thread.current[CURRENT_BATCH_THREAD_KEY]) && should_handle_batch?(msg)
|
48
|
-
batch.increment_job_queue(msg['jid']) if (msg[
|
48
|
+
batch.increment_job_queue(msg['jid']) if (msg['bid'] = batch.bid)
|
49
49
|
end
|
50
50
|
yield
|
51
51
|
end
|
@@ -38,7 +38,7 @@ module CanvasSync::JobUniqueness
|
|
38
38
|
queue: msg['queue'],
|
39
39
|
args: msg['args'],
|
40
40
|
# kwargs: msg['kwargs'],
|
41
|
-
**(msg['uniqueness_cache_data'] || {}),
|
41
|
+
**(msg['uniqueness_cache_data']&.symbolize_keys || {}),
|
42
42
|
}, job_instance: msg)
|
43
43
|
end
|
44
44
|
|
@@ -58,7 +58,7 @@ module CanvasSync::JobUniqueness
|
|
58
58
|
def call(_worker, msg, _queue, _redis_pool = nil, &blk)
|
59
59
|
ctx = lock_context(msg)
|
60
60
|
return blk.call unless ctx
|
61
|
-
msg['uniqueness_cache_data'] = ctx.cache_data
|
61
|
+
msg['uniqueness_cache_data'] = ctx.cache_data.stringify_keys
|
62
62
|
ctx.handle_lifecycle!(:enqueue, &blk)
|
63
63
|
end
|
64
64
|
end
|
@@ -15,11 +15,11 @@ module CanvasSync::JobUniqueness
|
|
15
15
|
@job_instance = job_instance
|
16
16
|
@config = config || @context_data[:config]
|
17
17
|
|
18
|
+
# TODO Consider (somewhere) updating the lock_id to the BID of the wrapping Batch (when applicable)
|
18
19
|
@lock_id ||= data[:lid] || Thread.current[:unique_jobs_previous_context]&.lock_id || job_id
|
19
20
|
end
|
20
21
|
|
21
22
|
# This is primarily for rehydrating in a Batch Callback, so it is unlikely that args and kwargs are needed.
|
22
|
-
# Honestly, base_key and job_clazz are probably the only needed values
|
23
23
|
def serialize
|
24
24
|
{
|
25
25
|
lid: lock_id,
|
@@ -44,6 +44,7 @@ module CanvasSync::JobUniqueness
|
|
44
44
|
|
45
45
|
def debug_data
|
46
46
|
{
|
47
|
+
lid: lock_id,
|
47
48
|
context_class: self.class.to_s,
|
48
49
|
job_class: job_class.to_s,
|
49
50
|
queue: job_queue,
|
@@ -152,7 +153,6 @@ module CanvasSync::JobUniqueness
|
|
152
153
|
# @yieldreturn [void] the yield is irrelevant, it only provides a mechanism in
|
153
154
|
# one specific situation to yield back to the middleware.
|
154
155
|
def call_conflict_strategy(origin)
|
155
|
-
new_job_id = nil
|
156
156
|
strategy = conflict_strategy_for(origin)
|
157
157
|
|
158
158
|
strategy.call
|
@@ -14,9 +14,7 @@ module CanvasSync::JobUniqueness
|
|
14
14
|
|
15
15
|
def initialize(key, lock_context, redis_pool = nil)
|
16
16
|
@lock_context = lock_context
|
17
|
-
|
18
|
-
# TODO For locks that do use a wrapping Batch, it may be nice to use the BID here instead
|
19
|
-
@job_id = lock_context.lock_id
|
17
|
+
@job_id = lock_context.lock_id # Yes, .lock_id is intentional
|
20
18
|
@item = lock_context
|
21
19
|
@key = SidekiqUniqueJobs::Key.new(key)
|
22
20
|
|
@@ -62,7 +62,7 @@ module CanvasSync::JobUniqueness
|
|
62
62
|
})
|
63
63
|
end
|
64
64
|
|
65
|
-
CanvasSync::JobUniqueness.logger.debug("Wrapped job in Locking Batch #{batch.bid} for #{key}")
|
65
|
+
CanvasSync::JobUniqueness.logger.debug("Wrapped job (#{lock_context.lock_id}) in Locking Batch #{batch.bid} for #{key}")
|
66
66
|
|
67
67
|
batch.jobs do
|
68
68
|
return blk.call
|
@@ -83,12 +83,7 @@ module CanvasSync::JobUniqueness
|
|
83
83
|
def lock!(purpose, wait: nil)
|
84
84
|
locked = nil
|
85
85
|
if purpose == :enqueue
|
86
|
-
# We don't need to swap_locks anymore because we maintain a consistent lock_id across re-enqueues
|
87
|
-
# if Thread.current[:unique_jobs_previous_context].present?
|
88
|
-
# locked = locksmith.swap_locks(Thread.current[:unique_jobs_previous_context].job_id)
|
89
|
-
# else
|
90
86
|
locked = locksmith.lock()
|
91
|
-
# end
|
92
87
|
elsif purpose == :perform
|
93
88
|
locked = locksmith.execute { lock_context.lock_id }
|
94
89
|
end
|
@@ -9,7 +9,7 @@ module CanvasSync::Jobs
|
|
9
9
|
|
10
10
|
if %w[completed complete imported imported_with_messages].include? status
|
11
11
|
InvokeCallbackWorker.perform_later(build_next_job(next_job, kwargs, response)) if next_job
|
12
|
-
elsif %w[failed error failed_with_messages].include? status
|
12
|
+
elsif %w[failed error failed_with_messages imports_failed exports_failed].include? status
|
13
13
|
if kwargs[:on_failure].is_a?(Hash)
|
14
14
|
InvokeCallbackWorker.perform_later(build_next_job(kwargs[:on_failure], kwargs, response))
|
15
15
|
else
|
data/lib/canvas_sync/version.rb
CHANGED
@@ -21,4 +21,43 @@ RSpec.describe CanvasSync::JobUniqueness::OnConflict::Reschedule do
|
|
21
21
|
lock_context2.handle_lifecycle!(:enqueue) {}
|
22
22
|
lock_context2.handle_lifecycle!(:perform) {}
|
23
23
|
end
|
24
|
+
|
25
|
+
it "maintains a consistent lock_id" do
|
26
|
+
TestWorker.clear
|
27
|
+
TestWorker.unique_job_options.merge!({ strategy: :while_executing, on_conflict: :reschedule })
|
28
|
+
|
29
|
+
lock_context.handle_lifecycle!(:enqueue) {}
|
30
|
+
lock_context.handle_lifecycle!(:perform) {}
|
31
|
+
|
32
|
+
TestWorker.perform_async
|
33
|
+
j1 = TestWorker.jobs[0]
|
34
|
+
TestWorker.perform_one
|
35
|
+
j2 = TestWorker.jobs[0]
|
36
|
+
|
37
|
+
expect(j1).not_to eq(j2)
|
38
|
+
expect(j1['uniqueness_cache_data']['lid']).to be_present
|
39
|
+
expect(j1['uniqueness_cache_data']['lid']).to eq(j2['uniqueness_cache_data']['lid'])
|
40
|
+
end
|
41
|
+
|
42
|
+
it "unlocks after rescheduling" do
|
43
|
+
TestWorker.clear
|
44
|
+
TestWorker.unique_job_options.merge!({ strategy: :while_executing, on_conflict: :reschedule })
|
45
|
+
|
46
|
+
lock_context.handle_lifecycle!(:enqueue) {}
|
47
|
+
lock_context.handle_lifecycle!(:perform) {}
|
48
|
+
|
49
|
+
TestWorker.perform_async
|
50
|
+
expect(TestWorker.jobs.size).to eq(1)
|
51
|
+
TestWorker.perform_one
|
52
|
+
expect(TestWorker.jobs.size).to eq(1)
|
53
|
+
|
54
|
+
lock_context.lock_strategy.send(:unlock)
|
55
|
+
Sidekiq::Worker.drain_all
|
56
|
+
expect(TestWorker.jobs.size).to eq(0)
|
57
|
+
|
58
|
+
# Run another worker to validate that the lock was released
|
59
|
+
TestWorker.perform_async
|
60
|
+
TestWorker.perform_one
|
61
|
+
expect(TestWorker.jobs.size).to eq(0)
|
62
|
+
end
|
24
63
|
end
|
@@ -7,7 +7,7 @@ Redis.silence_deprecations = true
|
|
7
7
|
Dir[File.join(File.dirname(__FILE__), "./support/**/*.rb")].sort.each { |f| require f }
|
8
8
|
|
9
9
|
Sidekiq::Testing.server_middleware do |chain|
|
10
|
-
chain.
|
10
|
+
chain.insert_after CanvasSync::JobBatches::Compat::Sidekiq::ServerMiddleware, CanvasSync::JobUniqueness::Compat::Sidekiq::ServerMiddleware
|
11
11
|
end
|
12
12
|
|
13
13
|
RSpec.configure do |config|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: canvas_sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.22.
|
4
|
+
version: 0.22.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Instructure CustomDev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-08-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -870,9 +870,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
870
870
|
version: '0'
|
871
871
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
872
872
|
requirements:
|
873
|
-
- - "
|
873
|
+
- - ">="
|
874
874
|
- !ruby/object:Gem::Version
|
875
|
-
version:
|
875
|
+
version: '0'
|
876
876
|
requirements: []
|
877
877
|
rubygems_version: 3.1.6
|
878
878
|
signing_key:
|