canvas_sync 0.17.23.beta7 → 0.17.26.beta1
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.
- checksums.yaml +4 -4
- data/lib/canvas_sync/job_batches/batch.rb +99 -58
- data/lib/canvas_sync/job_batches/batch_aware_job.rb +7 -7
- data/lib/canvas_sync/job_batches/chain_builder.rb +39 -6
- data/lib/canvas_sync/job_batches/pool.rb +42 -52
- data/lib/canvas_sync/job_batches/sidekiq.rb +7 -7
- data/lib/canvas_sync/jobs/begin_sync_chain_job.rb +9 -1
- data/lib/canvas_sync/jobs/sync_terms_job.rb +1 -17
- data/lib/canvas_sync/jobs/term_batches_job.rb +23 -0
- data/lib/canvas_sync/version.rb +1 -1
- data/lib/canvas_sync.rb +21 -8
- data/spec/canvas_sync/processors/provisioning_report_processor_spec.rb +8 -1
- data/spec/dummy/log/development.log +540 -0
- data/spec/dummy/log/test.log +65350 -0
- data/spec/job_batching/batch_aware_job_spec.rb +3 -3
- data/spec/job_batching/batch_spec.rb +40 -1
- data/spec/job_batching/sidekiq_spec.rb +2 -2
- data/spec/support/fixtures/reports/xlist.csv +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ce544260a5cc94f9193cb99da3bc55e06ecd1078e0ef6a5afca282cc4d39169f
|
4
|
+
data.tar.gz: 30a5bccedebde1cb00aeb31219b1d9f605672fa8ea58cb50af483cf8f98d15fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e84bde52492c2276650bd662adff677c0aa6a1c511587886d45fc6d328389af242ade72fe872dda2093df9ebb151aa25a4a353559a31d74330849f0a0c93d159
|
7
|
+
data.tar.gz: 3c30eceedad806932b61abc66456973250c7247ba7431406f1c5440b09b05cc3b7174112e34e78392d8f3e9c89dfcd7eba43377a0f8ee30d6320a00a50303163
|
@@ -19,6 +19,8 @@ require_relative "./chain_builder"
|
|
19
19
|
|
20
20
|
module CanvasSync
|
21
21
|
module JobBatches
|
22
|
+
CURRENT_BATCH_THREAD_KEY = :job_batches_batch
|
23
|
+
|
22
24
|
class Batch
|
23
25
|
include RedisModel
|
24
26
|
|
@@ -76,14 +78,12 @@ module CanvasSync
|
|
76
78
|
def on(event, callback, options = {})
|
77
79
|
return unless Callback::VALID_CALLBACKS.include?(event.to_s)
|
78
80
|
callback_key = "#{@bidkey}-callbacks-#{event}"
|
79
|
-
redis do |r|
|
80
|
-
r.
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
r.expire(callback_key, BID_EXPIRE_TTL)
|
86
|
-
end
|
81
|
+
redis.multi do |r|
|
82
|
+
r.sadd(callback_key, JSON.unparse({
|
83
|
+
callback: callback,
|
84
|
+
opts: options
|
85
|
+
}))
|
86
|
+
r.expire(callback_key, BID_EXPIRE_TTL)
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
@@ -91,18 +91,16 @@ module CanvasSync
|
|
91
91
|
raise NoBlockGivenError unless block_given?
|
92
92
|
|
93
93
|
if !@existing && !@initialized
|
94
|
-
parent_bid = Thread.current[
|
94
|
+
parent_bid = Thread.current[CURRENT_BATCH_THREAD_KEY]&.bid
|
95
95
|
|
96
|
-
redis do |r|
|
97
|
-
r.
|
98
|
-
|
99
|
-
r.expire(@bidkey, BID_EXPIRE_TTL)
|
96
|
+
redis.multi do |r|
|
97
|
+
r.hset(@bidkey, "parent_bid", parent_bid.to_s) if parent_bid
|
98
|
+
r.expire(@bidkey, BID_EXPIRE_TTL)
|
100
99
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
end
|
100
|
+
if parent_bid
|
101
|
+
r.hincrby("BID-#{parent_bid}", "children", 1)
|
102
|
+
r.expire("BID-#{parent_bid}", BID_EXPIRE_TTL)
|
103
|
+
r.zadd("BID-#{parent_bid}-bids", created_at, bid)
|
106
104
|
end
|
107
105
|
end
|
108
106
|
|
@@ -115,11 +113,11 @@ module CanvasSync
|
|
115
113
|
end
|
116
114
|
|
117
115
|
begin
|
118
|
-
parent = Thread.current[
|
119
|
-
Thread.current[
|
116
|
+
parent = Thread.current[CURRENT_BATCH_THREAD_KEY]
|
117
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY] = self
|
120
118
|
yield
|
121
119
|
ensure
|
122
|
-
Thread.current[
|
120
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY] = parent
|
123
121
|
end
|
124
122
|
|
125
123
|
nil
|
@@ -131,15 +129,11 @@ module CanvasSync
|
|
131
129
|
end
|
132
130
|
|
133
131
|
def invalidate_all
|
134
|
-
redis
|
135
|
-
r.setex("invalidated-bid-#{bid}", BID_EXPIRE_TTL, 1)
|
136
|
-
end
|
132
|
+
redis.setex("invalidated-bid-#{bid}", BID_EXPIRE_TTL, 1)
|
137
133
|
end
|
138
134
|
|
139
135
|
def parent_bid
|
140
|
-
redis
|
141
|
-
r.hget(@bidkey, "parent_bid")
|
142
|
-
end
|
136
|
+
redis.hget(@bidkey, "parent_bid")
|
143
137
|
end
|
144
138
|
|
145
139
|
def parent
|
@@ -149,7 +143,7 @@ module CanvasSync
|
|
149
143
|
end
|
150
144
|
|
151
145
|
def valid?(batch = self)
|
152
|
-
valid = !redis
|
146
|
+
valid = !redis.exists?("invalidated-bid-#{batch.bid}")
|
153
147
|
batch.parent ? valid && valid?(batch.parent) : valid
|
154
148
|
end
|
155
149
|
|
@@ -162,23 +156,19 @@ module CanvasSync
|
|
162
156
|
let_close!
|
163
157
|
end
|
164
158
|
else
|
165
|
-
redis
|
166
|
-
r.hset(@bidkey, 'keep_open', true)
|
167
|
-
end
|
159
|
+
redis.hset(@bidkey, 'keep_open', true)
|
168
160
|
end
|
169
161
|
end
|
170
162
|
|
171
163
|
def let_close!
|
172
|
-
_, failed, pending, children, complete, success = redis do |r|
|
173
|
-
r.
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
r.scard("BID-#{bid}-batches-success")
|
181
|
-
end
|
164
|
+
_, failed, pending, children, complete, success = redis.multi do |r|
|
165
|
+
r.hset(@bidkey, 'keep_open', false)
|
166
|
+
|
167
|
+
r.scard("BID-#{bid}-failed")
|
168
|
+
r.hincrby("BID-#{bid}", "pending", 0)
|
169
|
+
r.hincrby("BID-#{bid}", "children", 0)
|
170
|
+
r.scard("BID-#{bid}-batches-complete")
|
171
|
+
r.scard("BID-#{bid}-batches-success")
|
182
172
|
end
|
183
173
|
|
184
174
|
all_success = pending.to_i.zero? && children == success
|
@@ -191,11 +181,11 @@ module CanvasSync
|
|
191
181
|
|
192
182
|
def self.with_batch(batch)
|
193
183
|
batch = self.new(batch) if batch.is_a?(String)
|
194
|
-
parent = Thread.current[
|
195
|
-
Thread.current[
|
184
|
+
parent = Thread.current[CURRENT_BATCH_THREAD_KEY]
|
185
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY] = batch
|
196
186
|
yield
|
197
187
|
ensure
|
198
|
-
Thread.current[
|
188
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY] = parent
|
199
189
|
end
|
200
190
|
|
201
191
|
# Any Batches or Jobs created in the given block won't be assocaiated to the current batch
|
@@ -211,18 +201,14 @@ module CanvasSync
|
|
211
201
|
|
212
202
|
def flush_pending_attrs
|
213
203
|
super
|
214
|
-
redis
|
215
|
-
r.zadd("batches", created_at, bid)
|
216
|
-
end
|
204
|
+
redis.zadd("batches", created_at, bid)
|
217
205
|
end
|
218
206
|
|
219
207
|
private
|
220
208
|
|
221
209
|
def assert_batch_is_open
|
222
210
|
unless defined?(@closed)
|
223
|
-
redis
|
224
|
-
@closed = r.hget(@bidkey, 'success') == 'true'
|
225
|
-
end
|
211
|
+
@closed = redis.hget(@bidkey, 'success') == 'true'
|
226
212
|
end
|
227
213
|
raise "Cannot add jobs to Batch #{} bid - it has already entered the callback-stage" if @closed
|
228
214
|
end
|
@@ -234,7 +220,7 @@ module CanvasSync
|
|
234
220
|
redis do |r|
|
235
221
|
tme = Time.now.utc.to_f
|
236
222
|
added = r.zadd(@bidkey + "-jids", jids.map{|jid| [tme, jid] }, nx: true)
|
237
|
-
r.multi do
|
223
|
+
r.multi do |r|
|
238
224
|
r.hincrby(@bidkey, "pending", added)
|
239
225
|
r.hincrby(@bidkey, "job_count", added)
|
240
226
|
r.expire(@bidkey, BID_EXPIRE_TTL)
|
@@ -244,6 +230,14 @@ module CanvasSync
|
|
244
230
|
end
|
245
231
|
|
246
232
|
class << self
|
233
|
+
def current
|
234
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY]
|
235
|
+
end
|
236
|
+
|
237
|
+
def current_context
|
238
|
+
current&.context || {}
|
239
|
+
end
|
240
|
+
|
247
241
|
def process_failed_job(bid, jid)
|
248
242
|
_, pending, failed, children, complete, parent_bid = redis do |r|
|
249
243
|
return unless r.exists?("BID-#{bid}")
|
@@ -283,11 +277,9 @@ module CanvasSync
|
|
283
277
|
end
|
284
278
|
|
285
279
|
if parent_bid
|
286
|
-
redis do
|
287
|
-
r.
|
288
|
-
|
289
|
-
r.expire("BID-#{parent_bid}-dead", BID_EXPIRE_TTL)
|
290
|
-
end
|
280
|
+
redis.multi do
|
281
|
+
r.sadd("BID-#{parent_bid}-dead", jid)
|
282
|
+
r.expire("BID-#{parent_bid}-dead", BID_EXPIRE_TTL)
|
291
283
|
end
|
292
284
|
end
|
293
285
|
|
@@ -413,8 +405,21 @@ module CanvasSync
|
|
413
405
|
cleanup_redis(bid)
|
414
406
|
end
|
415
407
|
|
416
|
-
def redis(
|
417
|
-
|
408
|
+
def redis(&blk)
|
409
|
+
return RedisProxy.new unless block_given?
|
410
|
+
|
411
|
+
if Thread.current[:job_batches_redis]
|
412
|
+
yield Thread.current[:job_batches_redis]
|
413
|
+
elsif defined?(::Sidekiq)
|
414
|
+
::Sidekiq.redis do |r|
|
415
|
+
Thread.current[:job_batches_redis] = r
|
416
|
+
yield r
|
417
|
+
ensure
|
418
|
+
Thread.current[:job_batches_redis] = nil
|
419
|
+
end
|
420
|
+
else
|
421
|
+
# TODO
|
422
|
+
end
|
418
423
|
end
|
419
424
|
|
420
425
|
def logger
|
@@ -433,6 +438,42 @@ module CanvasSync
|
|
433
438
|
end
|
434
439
|
end
|
435
440
|
end
|
441
|
+
|
442
|
+
class RedisProxy
|
443
|
+
def multi(*args, &block)
|
444
|
+
Batch.redis do |r|
|
445
|
+
if block.arity == 1
|
446
|
+
r.multi(*args) do
|
447
|
+
block.call(r)
|
448
|
+
end
|
449
|
+
else
|
450
|
+
r.multi(*args, &block)
|
451
|
+
end
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
def pipelined(*args, &block)
|
456
|
+
Batch.redis do |r|
|
457
|
+
if block.arity == 1
|
458
|
+
r.pipelined(*args) do
|
459
|
+
block.call(r)
|
460
|
+
end
|
461
|
+
else
|
462
|
+
r.pipelined(*args, &block)
|
463
|
+
end
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
def method_missing(method_name, *arguments, &block)
|
468
|
+
Batch.redis do |r|
|
469
|
+
r.send(method_name, *arguments, &block)
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
def respond_to_missing?(method_name, include_private = false)
|
474
|
+
super || Redis.method_defined?(method_name)
|
475
|
+
end
|
476
|
+
end
|
436
477
|
end
|
437
478
|
|
438
479
|
ActiveJob::Base.include BatchAwareJob
|
@@ -6,17 +6,17 @@ module CanvasSync
|
|
6
6
|
included do
|
7
7
|
around_perform do |job, block|
|
8
8
|
if (@bid) # This _must_ be @bid - not just bid
|
9
|
-
prev_batch = Thread.current[
|
9
|
+
prev_batch = Thread.current[CURRENT_BATCH_THREAD_KEY]
|
10
10
|
begin
|
11
|
-
Thread.current[
|
11
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY] = Batch.new(@bid)
|
12
12
|
block.call
|
13
|
-
Thread.current[
|
13
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY].save_context_changes
|
14
14
|
Batch.process_successful_job(@bid, job_id)
|
15
15
|
rescue
|
16
16
|
Batch.process_failed_job(@bid, job_id)
|
17
17
|
raise
|
18
18
|
ensure
|
19
|
-
Thread.current[
|
19
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY] = prev_batch
|
20
20
|
end
|
21
21
|
else
|
22
22
|
block.call
|
@@ -24,7 +24,7 @@ module CanvasSync
|
|
24
24
|
end
|
25
25
|
|
26
26
|
around_enqueue do |job, block|
|
27
|
-
if (batch = Thread.current[
|
27
|
+
if (batch = Thread.current[CURRENT_BATCH_THREAD_KEY])
|
28
28
|
@bid = batch.bid
|
29
29
|
batch.increment_job_queue(job_id) if @bid
|
30
30
|
end
|
@@ -33,11 +33,11 @@ module CanvasSync
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def bid
|
36
|
-
@bid || Thread.current[
|
36
|
+
@bid || Thread.current[CURRENT_BATCH_THREAD_KEY]&.bid
|
37
37
|
end
|
38
38
|
|
39
39
|
def batch
|
40
|
-
Thread.current[
|
40
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY]
|
41
41
|
end
|
42
42
|
|
43
43
|
def batch_context
|
@@ -37,16 +37,29 @@ module CanvasSync
|
|
37
37
|
insert_at(-1, new_job)
|
38
38
|
end
|
39
39
|
|
40
|
-
def insert_at(position, new_jobs)
|
40
|
+
def insert_at(position, new_jobs, *args, &blk)
|
41
41
|
chain = self.class.get_chain_parameter(base_job)
|
42
|
+
if new_jobs.is_a?(Class) || new_jobs.is_a?(String)
|
43
|
+
new_jobs = build_job_hash(new_jobs, *args, &blk)
|
44
|
+
elsif args.length > 0
|
45
|
+
raise "Unexpected number of arguments"
|
46
|
+
end
|
42
47
|
new_jobs = [new_jobs] unless new_jobs.is_a?(Array)
|
43
48
|
chain.insert(position, *new_jobs)
|
44
49
|
end
|
45
50
|
|
46
|
-
def insert(new_jobs, **kwargs)
|
47
|
-
|
48
|
-
|
49
|
-
|
51
|
+
def insert(new_jobs, *args, **kwargs, &blk)
|
52
|
+
if new_jobs.is_a?(Class) || new_jobs.is_a?(String)
|
53
|
+
job_kwargs = kwargs.except(*VALID_PLACEMENT_PARAMETERS)
|
54
|
+
args << job_kwargs if job_kwargs.present?
|
55
|
+
new_jobs = build_job_hash(new_jobs, *args, &blk)
|
56
|
+
kwargs = kwargs.slice(*VALID_PLACEMENT_PARAMETERS)
|
57
|
+
else
|
58
|
+
invalid_params = kwargs.keys - VALID_PLACEMENT_PARAMETERS
|
59
|
+
raise "Invalid placement parameters: #{invalid_params.map(&:to_s).join(', ')}" if invalid_params.present?
|
60
|
+
raise "At most one placement parameter may be provided" if kwargs.values.compact.length > 1
|
61
|
+
raise "Unexpected number of arguments" if args.length > 0
|
62
|
+
end
|
50
63
|
|
51
64
|
new_jobs = [new_jobs] unless new_jobs.is_a?(Array)
|
52
65
|
|
@@ -90,7 +103,6 @@ module CanvasSync
|
|
90
103
|
raise "Found multiple \"#{sub_type}\" jobs in the chain" if matching_jobs.count > 1
|
91
104
|
return nil if matching_jobs.count == 0
|
92
105
|
|
93
|
-
|
94
106
|
job = matching_jobs[0][0]
|
95
107
|
job = self.class.new(job) unless job.is_a?(ChainBuilder)
|
96
108
|
job
|
@@ -116,8 +128,22 @@ module CanvasSync
|
|
116
128
|
end
|
117
129
|
end
|
118
130
|
|
131
|
+
def apply_block(&blk)
|
132
|
+
return unless blk.present?
|
133
|
+
instance_exec(&blk)
|
134
|
+
end
|
135
|
+
|
119
136
|
private
|
120
137
|
|
138
|
+
def build_job_hash(job, *params, &blk)
|
139
|
+
hsh = {
|
140
|
+
job: job,
|
141
|
+
parameters: params,
|
142
|
+
}
|
143
|
+
self.class.new(hsh).apply_block(&blk) if blk.present?
|
144
|
+
hsh
|
145
|
+
end
|
146
|
+
|
121
147
|
def find_matching_jobs(search_job, parent_job = self.base_job)
|
122
148
|
return to_enum(:find_matching_jobs, search_job, parent_job) unless block_given?
|
123
149
|
|
@@ -150,6 +176,13 @@ module CanvasSync
|
|
150
176
|
end
|
151
177
|
|
152
178
|
class << self
|
179
|
+
def build(job, *args, &blk)
|
180
|
+
new(job).tap do |ch|
|
181
|
+
ch[:parameters] = args
|
182
|
+
ch.apply_block(&blk)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
153
186
|
def _job_type_definitions
|
154
187
|
@job_type_definitions ||= {}
|
155
188
|
end
|
@@ -64,18 +64,14 @@ module CanvasSync
|
|
64
64
|
let_close!
|
65
65
|
end
|
66
66
|
else
|
67
|
-
redis
|
68
|
-
r.hset(redis_key, 'keep_open', true)
|
69
|
-
end
|
67
|
+
redis.hset(redis_key, 'keep_open', true)
|
70
68
|
end
|
71
69
|
end
|
72
70
|
|
73
71
|
def let_close!
|
74
|
-
_, active_count = redis do |r|
|
75
|
-
r.
|
76
|
-
|
77
|
-
r.hincrby(redis_key, "active_count", 0)
|
78
|
-
end
|
72
|
+
_, active_count = redis.multi do |r|
|
73
|
+
r.hset(redis_key, 'keep_open', false)
|
74
|
+
r.hincrby(redis_key, "active_count", 0)
|
79
75
|
end
|
80
76
|
|
81
77
|
if active_count == 0 && pending_count == 0
|
@@ -95,35 +91,38 @@ module CanvasSync
|
|
95
91
|
end
|
96
92
|
|
97
93
|
def active_count
|
98
|
-
redis
|
99
|
-
r.hincrby(redis_key, "active_count", 0)
|
100
|
-
end
|
94
|
+
redis.hincrby(redis_key, "active_count", 0)
|
101
95
|
end
|
102
96
|
|
103
97
|
def pending_count
|
104
98
|
jobs_key = "#{redis_key}-jobs"
|
105
99
|
order = self.order || 'fifo'
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
r.zcard(jobs_key)
|
114
|
-
end
|
100
|
+
case order.to_sym
|
101
|
+
when :fifo, :lifo
|
102
|
+
redis.llen(jobs_key)
|
103
|
+
when :random
|
104
|
+
redis.scard(jobs_key)
|
105
|
+
when :priority
|
106
|
+
redis.zcard(jobs_key)
|
115
107
|
end
|
116
108
|
end
|
117
109
|
|
118
110
|
def job_checked_in(status, options)
|
119
|
-
active_count = redis do |r|
|
111
|
+
active_count, pending_count = redis do |r|
|
120
112
|
return unless r.exists?(redis_key)
|
121
|
-
|
113
|
+
|
114
|
+
# Make sure this is loaded outside of the pipeline
|
115
|
+
self.order
|
116
|
+
|
117
|
+
redis.multi do
|
118
|
+
r.hincrby(redis_key, "active_count", -1)
|
119
|
+
self.pending_count
|
120
|
+
end
|
122
121
|
end
|
123
122
|
|
124
123
|
added_count = refill_allotment
|
125
|
-
if active_count == 0 && added_count == 0
|
126
|
-
if clean_when_empty && redis
|
124
|
+
if active_count == 0 && added_count == 0 && pending_count == 0
|
125
|
+
if clean_when_empty && redis.hget(redis_key, 'keep_open') != 'true'
|
127
126
|
cleanup_redis
|
128
127
|
end
|
129
128
|
end
|
@@ -175,18 +174,16 @@ module CanvasSync
|
|
175
174
|
job_json = JSON.unparse(ActiveJob::Arguments.serialize([job_desc]))
|
176
175
|
order = self.order
|
177
176
|
|
178
|
-
redis do |r|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
r.zadd(jobs_key, job_desc[:priority] || 0, job_json)
|
187
|
-
end
|
188
|
-
r.expire(jobs_key, Batch::BID_EXPIRE_TTL)
|
177
|
+
redis.multi do |r|
|
178
|
+
case order.to_sym
|
179
|
+
when :fifo, :lifo
|
180
|
+
r.rpush(jobs_key, job_json)
|
181
|
+
when :random
|
182
|
+
r.sadd(jobs_key, job_json)
|
183
|
+
when :priority
|
184
|
+
r.zadd(jobs_key, job_desc[:priority] || 0, job_json)
|
189
185
|
end
|
186
|
+
r.expire(jobs_key, Batch::BID_EXPIRE_TTL)
|
190
187
|
end
|
191
188
|
end
|
192
189
|
|
@@ -194,18 +191,15 @@ module CanvasSync
|
|
194
191
|
jobs_key = "#{redis_key}-jobs"
|
195
192
|
order = self.order
|
196
193
|
|
197
|
-
job_json =
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
when :priority
|
207
|
-
r.zpopmax(jobs_key)
|
208
|
-
end
|
194
|
+
job_json = case order.to_sym
|
195
|
+
when :fifo
|
196
|
+
redis.lpop(jobs_key)
|
197
|
+
when :lifo
|
198
|
+
redis.rpop(jobs_key)
|
199
|
+
when :random
|
200
|
+
redis.spop(jobs_key)
|
201
|
+
when :priority
|
202
|
+
redis.zpopmax(jobs_key)
|
209
203
|
end
|
210
204
|
|
211
205
|
return nil unless job_json.present?
|
@@ -218,13 +212,9 @@ module CanvasSync
|
|
218
212
|
end
|
219
213
|
delegate :redis, to: :class
|
220
214
|
|
221
|
-
protected
|
222
|
-
|
223
215
|
def flush_pending_attrs
|
224
216
|
super
|
225
|
-
redis
|
226
|
-
r.zadd("pools", created_at, pid)
|
227
|
-
end
|
217
|
+
redis.zadd("pools", created_at, pid)
|
228
218
|
end
|
229
219
|
|
230
220
|
private
|
@@ -8,11 +8,11 @@ module CanvasSync
|
|
8
8
|
module Sidekiq
|
9
9
|
module WorkerExtension
|
10
10
|
def bid
|
11
|
-
Thread.current[
|
11
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY].bid
|
12
12
|
end
|
13
13
|
|
14
14
|
def batch
|
15
|
-
Thread.current[
|
15
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY]
|
16
16
|
end
|
17
17
|
|
18
18
|
def batch_context
|
@@ -42,7 +42,7 @@ module CanvasSync
|
|
42
42
|
|
43
43
|
class ClientMiddleware
|
44
44
|
def call(_worker, msg, _queue, _redis_pool = nil)
|
45
|
-
if (batch = Thread.current[
|
45
|
+
if (batch = Thread.current[CURRENT_BATCH_THREAD_KEY]) && should_handle_batch?(msg)
|
46
46
|
batch.increment_job_queue(msg['jid']) if (msg[:bid] = batch.bid)
|
47
47
|
end
|
48
48
|
yield
|
@@ -57,17 +57,17 @@ module CanvasSync
|
|
57
57
|
class ServerMiddleware
|
58
58
|
def call(_worker, msg, _queue)
|
59
59
|
if (bid = msg['bid'])
|
60
|
-
prev_batch = Thread.current[
|
60
|
+
prev_batch = Thread.current[CURRENT_BATCH_THREAD_KEY]
|
61
61
|
begin
|
62
|
-
Thread.current[
|
62
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY] = Batch.new(bid)
|
63
63
|
yield
|
64
|
-
Thread.current[
|
64
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY].save_context_changes
|
65
65
|
Batch.process_successful_job(bid, msg['jid'])
|
66
66
|
rescue
|
67
67
|
Batch.process_failed_job(bid, msg['jid'])
|
68
68
|
raise
|
69
69
|
ensure
|
70
|
-
Thread.current[
|
70
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY] = prev_batch
|
71
71
|
end
|
72
72
|
else
|
73
73
|
yield
|
@@ -14,6 +14,12 @@ module CanvasSync
|
|
14
14
|
globals[:updated_after] = last_batch&.started_at&.iso8601
|
15
15
|
end
|
16
16
|
|
17
|
+
# Refuse to run syncs of the same genre if there is a running full sync
|
18
|
+
if last_full_sync_record&.status == 'processing' && last_full_sync > 12.hours.ago
|
19
|
+
Rails.logger.warn("Attempted to start a '#{genre}' sync while a full-sync is still processing.")
|
20
|
+
return
|
21
|
+
end
|
22
|
+
|
17
23
|
if should_full_sync?(globals[:full_sync_every])
|
18
24
|
globals[:updated_after] = nil
|
19
25
|
end
|
@@ -25,6 +31,8 @@ module CanvasSync
|
|
25
31
|
status: 'processing',
|
26
32
|
)
|
27
33
|
|
34
|
+
globals[:sync_batch_id] = sync_batch.id
|
35
|
+
|
28
36
|
JobBatches::Batch.new.tap do |b|
|
29
37
|
b.description = "CanvasSync Root Batch (SyncBatch##{sync_batch.id})"
|
30
38
|
b.on(:complete, "#{self.class.to_s}.batch_completed", sync_batch_id: sync_batch.id)
|
@@ -62,7 +70,7 @@ module CanvasSync
|
|
62
70
|
end
|
63
71
|
|
64
72
|
def last_full_sync_record
|
65
|
-
@last_full_sync_record ||= SyncBatch.where(status: 'completed', full_sync: true, batch_genre: genre).last
|
73
|
+
@last_full_sync_record ||= SyncBatch.where(status: ['completed', 'processing'], full_sync: true, batch_genre: genre).last
|
66
74
|
end
|
67
75
|
|
68
76
|
def last_full_sync
|
@@ -23,23 +23,7 @@ module CanvasSync
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
|
27
|
-
context = options[:context] || {}
|
28
|
-
if options[:term_scope]
|
29
|
-
Term.send(options[:term_scope]).find_each.map do |term|
|
30
|
-
local_context = context.merge(canvas_term_id: get_term_id(term))
|
31
|
-
JobBatches::ConcurrentBatchJob.perform_now(jobs, context: local_context)
|
32
|
-
end
|
33
|
-
else
|
34
|
-
JobBatches::ConcurrentBatchJob.perform_now(jobs, context: context)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
protected
|
40
|
-
|
41
|
-
def get_term_id(term)
|
42
|
-
term.try(:canvas_id) || term.canvas_term_id
|
26
|
+
TermBatchesJob.perform_now(options)
|
43
27
|
end
|
44
28
|
end
|
45
29
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module CanvasSync
|
2
|
+
module Jobs
|
3
|
+
class TermBatchesJob < CanvasSync::Job
|
4
|
+
def perform(options)
|
5
|
+
if (jobs = options[:sub_jobs]).present?
|
6
|
+
context = options[:context] || {}
|
7
|
+
if options[:term_scope]
|
8
|
+
Term.send(options[:term_scope]).find_each.map do |term|
|
9
|
+
local_context = context.merge(canvas_term_id: get_term_id(term))
|
10
|
+
JobBatches::ConcurrentBatchJob.perform_now(jobs, context: local_context)
|
11
|
+
end
|
12
|
+
else
|
13
|
+
JobBatches::ConcurrentBatchJob.perform_now(jobs, context: context)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_term_id(term)
|
19
|
+
term.try(:canvas_id) || term.canvas_term_id
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|