canvas_sync 0.17.35 → 0.17.37
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/engine.rb +6 -0
- data/lib/canvas_sync/job_batches/active_job.rb +108 -0
- data/lib/canvas_sync/job_batches/batch.rb +7 -4
- data/lib/canvas_sync/job_batches/callback.rb +1 -13
- data/lib/canvas_sync/job_batches/jobs/base_job.rb +1 -1
- data/lib/canvas_sync/job_batches/jobs/managed_batch_job.rb +2 -2
- data/lib/canvas_sync/job_batches/pool.rb +2 -2
- data/lib/canvas_sync/job_batches/sidekiq.rb +21 -7
- data/lib/canvas_sync/version.rb +1 -1
- data/spec/dummy/log/test.log +23910 -0
- data/spec/job_batching/active_job_spec.rb +107 -0
- data/spec/job_batching/batch_spec.rb +1 -1
- metadata +5 -5
- data/lib/canvas_sync/job_batches/batch_aware_job.rb +0 -63
- data/spec/job_batching/batch_aware_job_spec.rb +0 -101
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa91c7ca59af567024be0ac8cb9d13ffff059fe7c04fb075101609b3fc78fe4f
|
4
|
+
data.tar.gz: 8f4e9744ed47825c119e4725c506bf8a55a0dca44d045f49c239e272eed3ea7d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a6213cb2348019af23683bfa1847e6f0025dd81269fe0950f6a0217acd15565d74096cbcc536bdd42eea8d214f1a5e8a67f8fd6f5188a09aa5442d8f7a26ac7
|
7
|
+
data.tar.gz: 8a502df328aff5498bf191bc6b3ef73ed91c32b1bcdf2b0f9aa1ec14ce8f0aaf9c908284c8e51da61b2ce51c97df43af0461c297dcb1b0b48252aab8b0240cad
|
data/lib/canvas_sync/engine.rb
CHANGED
@@ -5,6 +5,12 @@ module CanvasSync
|
|
5
5
|
class Engine < ::Rails::Engine
|
6
6
|
isolate_namespace CanvasSync
|
7
7
|
|
8
|
+
initializer "canvas_sync.serialze_symbols" do |app|
|
9
|
+
app.config.active_record.yaml_column_permitted_classes ||= []
|
10
|
+
app.config.active_record.yaml_column_permitted_classes |= [Symbol]
|
11
|
+
rescue
|
12
|
+
end
|
13
|
+
|
8
14
|
initializer :append_migrations do |app|
|
9
15
|
config.paths["db/migrate"].expanded.each do |expanded_path|
|
10
16
|
app.config.paths["db/migrate"] << expanded_path
|
@@ -0,0 +1,108 @@
|
|
1
|
+
|
2
|
+
module CanvasSync
|
3
|
+
module JobBatches
|
4
|
+
module ActiveJob
|
5
|
+
module BatchAwareJob
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
around_perform do |job, block|
|
10
|
+
if (@bid) # This _must_ be @bid - not just bid
|
11
|
+
prev_batch = Thread.current[CURRENT_BATCH_THREAD_KEY]
|
12
|
+
begin
|
13
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY] = Batch.new(@bid)
|
14
|
+
block.call
|
15
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY].save_context_changes
|
16
|
+
Batch.process_successful_job(@bid, job_id)
|
17
|
+
rescue
|
18
|
+
Batch.process_failed_job(@bid, job_id)
|
19
|
+
raise
|
20
|
+
ensure
|
21
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY] = prev_batch
|
22
|
+
end
|
23
|
+
else
|
24
|
+
block.call
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
around_enqueue do |job, block|
|
29
|
+
if (batch = Thread.current[CURRENT_BATCH_THREAD_KEY])
|
30
|
+
@bid = batch.bid
|
31
|
+
batch.increment_job_queue(job_id) if @bid
|
32
|
+
end
|
33
|
+
block.call
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def bid
|
38
|
+
@bid || Thread.current[CURRENT_BATCH_THREAD_KEY]&.bid
|
39
|
+
end
|
40
|
+
|
41
|
+
def batch
|
42
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY]
|
43
|
+
end
|
44
|
+
|
45
|
+
def batch_context
|
46
|
+
batch&.context || {}
|
47
|
+
end
|
48
|
+
|
49
|
+
def valid_within_batch?
|
50
|
+
batch.valid?
|
51
|
+
end
|
52
|
+
|
53
|
+
def serialize
|
54
|
+
super.tap do |data|
|
55
|
+
data['batch_id'] = @bid # This _must_ be @bid - not just bid
|
56
|
+
data
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def deserialize(data)
|
61
|
+
super
|
62
|
+
@bid = data['batch_id']
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class ActiveJobCallbackWorker < ::ActiveJob::Base
|
67
|
+
include Batch::Callback::CallbackWorkerCommon
|
68
|
+
|
69
|
+
def self.enqueue_all(args, queue)
|
70
|
+
args.each do |arg_set|
|
71
|
+
set(queue: queue).perform_later(*arg_set)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.handle_job_death(job, error = nil)
|
77
|
+
if job.is_a?(Array)
|
78
|
+
event = ActiveSupport::Notifications::Event.new(*job)
|
79
|
+
payload = event.payload
|
80
|
+
job = payload[:job].serialize
|
81
|
+
error = payload[:error]
|
82
|
+
end
|
83
|
+
|
84
|
+
if job["job_id"].present? && job["batch_id"].present?
|
85
|
+
CanvasSync::JobBatches::Batch.process_dead_job(job['batch_id'], job['job_id'])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.configure
|
90
|
+
::ActiveJob::Base.include BatchAwareJob
|
91
|
+
|
92
|
+
begin
|
93
|
+
ActiveSupport::Notifications.subscribe "discard.active_job" do |*args|
|
94
|
+
handle_job_death(args)
|
95
|
+
end
|
96
|
+
|
97
|
+
ActiveSupport::Notifications.subscribe "retry_stopped.active_job" do |*args|
|
98
|
+
handle_job_death(args)
|
99
|
+
end
|
100
|
+
rescue => err
|
101
|
+
Rails.logger.warn(err)
|
102
|
+
end
|
103
|
+
|
104
|
+
Batch::Callback.worker_class ||= ActiveJobCallbackWorker
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -6,7 +6,6 @@ end
|
|
6
6
|
|
7
7
|
require_relative './redis_model'
|
8
8
|
require_relative './redis_script'
|
9
|
-
require_relative './batch_aware_job'
|
10
9
|
require_relative "./callback"
|
11
10
|
require_relative "./context_hash"
|
12
11
|
require_relative "./status"
|
@@ -465,7 +464,7 @@ module CanvasSync
|
|
465
464
|
when 'set'
|
466
465
|
r.smembers(key)
|
467
466
|
when 'zset'
|
468
|
-
r.
|
467
|
+
r.zrange(key, 0, -1)
|
469
468
|
end
|
470
469
|
end
|
471
470
|
end
|
@@ -481,8 +480,6 @@ module CanvasSync
|
|
481
480
|
end
|
482
481
|
end
|
483
482
|
end
|
484
|
-
|
485
|
-
ActiveJob::Base.include BatchAwareJob
|
486
483
|
end
|
487
484
|
end
|
488
485
|
|
@@ -491,3 +488,9 @@ if defined?(::Sidekiq)
|
|
491
488
|
require_relative './sidekiq'
|
492
489
|
CanvasSync::JobBatches::Sidekiq.configure
|
493
490
|
end
|
491
|
+
|
492
|
+
# Automatically integrate with ActiveJob if it is present.
|
493
|
+
if defined?(::ActiveJob)
|
494
|
+
require_relative './active_job'
|
495
|
+
CanvasSync::JobBatches::ActiveJob.configure
|
496
|
+
end
|
@@ -38,24 +38,12 @@ module CanvasSync
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
class ActiveJobCallbackWorker < ActiveJob::Base
|
42
|
-
include CallbackWorkerCommon
|
43
|
-
|
44
|
-
def self.enqueue_all(args, queue)
|
45
|
-
args.each do |arg_set|
|
46
|
-
set(queue: queue).perform_later(*arg_set)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
worker_class = ActiveJobCallbackWorker
|
52
|
-
|
53
41
|
class Finalize
|
54
42
|
def dispatch(status, opts)
|
55
43
|
bid = opts["bid"]
|
56
44
|
event = opts["event"].to_sym
|
57
45
|
|
58
|
-
Batch.logger.debug {"Finalize #{event} batch id: #{opts["bid"]}
|
46
|
+
Batch.logger.debug {"Finalize #{event} batch id: #{opts["bid"]}"}
|
59
47
|
|
60
48
|
batch_status = Status.new bid
|
61
49
|
send(event, bid, batch_status, batch_status.parent_bid)
|
@@ -26,7 +26,7 @@ module CanvasSync
|
|
26
26
|
|
27
27
|
mapped_sub_jobs = sub_jobs.each_with_index.map do |j, i|
|
28
28
|
j['_mngbid_index_'] = i # This allows duplicate jobs when a Redis Set is used
|
29
|
-
j = ActiveJob::Arguments.serialize([j])
|
29
|
+
j = ::ActiveJob::Arguments.serialize([j])
|
30
30
|
JSON.unparse(j)
|
31
31
|
end
|
32
32
|
if ordered
|
@@ -104,7 +104,7 @@ module CanvasSync
|
|
104
104
|
return unless next_job_json.present?
|
105
105
|
|
106
106
|
next_job = JSON.parse(next_job_json)
|
107
|
-
next_job = ActiveJob::Arguments.deserialize(next_job)[0]
|
107
|
+
next_job = ::ActiveJob::Arguments.deserialize(next_job)[0]
|
108
108
|
|
109
109
|
Batch.new(root_bid).jobs do
|
110
110
|
Batch.new.tap do |batch|
|
@@ -171,7 +171,7 @@ module CanvasSync
|
|
171
171
|
jobs_key = "#{redis_key}-jobs"
|
172
172
|
# This allows duplicate jobs when a Redis Set is used
|
173
173
|
job_desc[:_pool_random_key_] = SecureRandom.urlsafe_base64(10)
|
174
|
-
job_json = JSON.unparse(ActiveJob::Arguments.serialize([job_desc]))
|
174
|
+
job_json = JSON.unparse(::ActiveJob::Arguments.serialize([job_desc]))
|
175
175
|
order = self.order
|
176
176
|
|
177
177
|
redis.multi do |r|
|
@@ -204,7 +204,7 @@ module CanvasSync
|
|
204
204
|
|
205
205
|
return nil unless job_json.present?
|
206
206
|
|
207
|
-
ActiveJob::Arguments.deserialize(JSON.parse(job_json))[0]&.symbolize_keys
|
207
|
+
::ActiveJob::Arguments.deserialize(JSON.parse(job_json))[0]&.symbolize_keys
|
208
208
|
end
|
209
209
|
|
210
210
|
def self.redis(&blk)
|
@@ -49,7 +49,7 @@ module CanvasSync
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def should_handle_batch?(msg)
|
52
|
-
return false if
|
52
|
+
return false if JobBatches::Sidekiq.is_activejob_job?(msg)
|
53
53
|
true
|
54
54
|
end
|
55
55
|
end
|
@@ -75,6 +75,22 @@ module CanvasSync
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
def self.is_activejob_job?(msg)
|
79
|
+
return false unless defined?(::ActiveJob)
|
80
|
+
|
81
|
+
msg['class'] == 'ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper' && (msg['wrapped'].to_s).constantize < JobBatches::ActiveJob::BatchAwareJob
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.switch_tenant(job)
|
85
|
+
if defined?(::Apartment)
|
86
|
+
::Apartment::Tenant.switch(job['apartment'] || 'public') do
|
87
|
+
yield
|
88
|
+
end
|
89
|
+
else
|
90
|
+
yield
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
78
94
|
def self.configure
|
79
95
|
if defined?(::Sidekiq::Batch) && ::Sidekiq::Batch != JobBatches::Batch
|
80
96
|
print "WARNING: Detected Sidekiq Pro or sidekiq-batch. CanvasSync JobBatches may not be fully compatible!"
|
@@ -98,14 +114,12 @@ module CanvasSync
|
|
98
114
|
end
|
99
115
|
|
100
116
|
config.death_handlers << ->(job, ex) do
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
117
|
+
switch_tenant(job) do
|
118
|
+
if is_activejob_job?(job)
|
119
|
+
JobBatches::ActiveJob.handle_job_death(job["args"][0], ex)
|
120
|
+
elsif job['bid'].present?
|
105
121
|
::Sidekiq::Batch.process_dead_job(job['bid'], job['jid'])
|
106
122
|
end
|
107
|
-
else
|
108
|
-
::Sidekiq::Batch.process_dead_job(job['bid'], job['jid'])
|
109
123
|
end
|
110
124
|
end
|
111
125
|
end
|
data/lib/canvas_sync/version.rb
CHANGED