canvas_sync 0.21.1 → 0.22.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/lib/canvas_sync/concerns/auto_relations.rb +11 -0
  3. data/lib/canvas_sync/config.rb +3 -5
  4. data/lib/canvas_sync/generators/templates/models/rubric.rb +2 -1
  5. data/lib/canvas_sync/job_batches/batch.rb +432 -402
  6. data/lib/canvas_sync/job_batches/callback.rb +100 -114
  7. data/lib/canvas_sync/job_batches/chain_builder.rb +194 -196
  8. data/lib/canvas_sync/job_batches/{active_job.rb → compat/active_job.rb} +2 -2
  9. data/lib/canvas_sync/job_batches/{sidekiq → compat/sidekiq}/web/helpers.rb +1 -1
  10. data/lib/canvas_sync/job_batches/{sidekiq → compat/sidekiq}/web.rb +3 -3
  11. data/lib/canvas_sync/job_batches/{sidekiq.rb → compat/sidekiq.rb} +35 -22
  12. data/lib/canvas_sync/job_batches/compat.rb +20 -0
  13. data/lib/canvas_sync/job_batches/context_hash.rb +124 -126
  14. data/lib/canvas_sync/job_batches/jobs/base_job.rb +2 -4
  15. data/lib/canvas_sync/job_batches/jobs/concurrent_batch_job.rb +14 -16
  16. data/lib/canvas_sync/job_batches/jobs/managed_batch_job.rb +125 -127
  17. data/lib/canvas_sync/job_batches/jobs/serial_batch_job.rb +14 -16
  18. data/lib/canvas_sync/job_batches/pool.rb +193 -195
  19. data/lib/canvas_sync/job_batches/redis_model.rb +50 -52
  20. data/lib/canvas_sync/job_batches/redis_script.rb +129 -131
  21. data/lib/canvas_sync/job_batches/status.rb +85 -87
  22. data/lib/canvas_sync/job_uniqueness/compat/active_job.rb +75 -0
  23. data/lib/canvas_sync/job_uniqueness/compat/sidekiq.rb +135 -0
  24. data/lib/canvas_sync/job_uniqueness/compat.rb +20 -0
  25. data/lib/canvas_sync/job_uniqueness/configuration.rb +25 -0
  26. data/lib/canvas_sync/job_uniqueness/job_uniqueness.rb +47 -0
  27. data/lib/canvas_sync/job_uniqueness/lock_context.rb +171 -0
  28. data/lib/canvas_sync/job_uniqueness/locksmith.rb +92 -0
  29. data/lib/canvas_sync/job_uniqueness/on_conflict/base.rb +32 -0
  30. data/lib/canvas_sync/job_uniqueness/on_conflict/log.rb +13 -0
  31. data/lib/canvas_sync/job_uniqueness/on_conflict/null_strategy.rb +9 -0
  32. data/lib/canvas_sync/job_uniqueness/on_conflict/raise.rb +11 -0
  33. data/lib/canvas_sync/job_uniqueness/on_conflict/reject.rb +21 -0
  34. data/lib/canvas_sync/job_uniqueness/on_conflict/reschedule.rb +20 -0
  35. data/lib/canvas_sync/job_uniqueness/on_conflict.rb +41 -0
  36. data/lib/canvas_sync/job_uniqueness/strategy/base.rb +104 -0
  37. data/lib/canvas_sync/job_uniqueness/strategy/until_and_while_executing.rb +35 -0
  38. data/lib/canvas_sync/job_uniqueness/strategy/until_executed.rb +20 -0
  39. data/lib/canvas_sync/job_uniqueness/strategy/until_executing.rb +20 -0
  40. data/lib/canvas_sync/job_uniqueness/strategy/until_expired.rb +16 -0
  41. data/lib/canvas_sync/job_uniqueness/strategy/while_executing.rb +26 -0
  42. data/lib/canvas_sync/job_uniqueness/strategy.rb +27 -0
  43. data/lib/canvas_sync/job_uniqueness/unique_job_common.rb +79 -0
  44. data/lib/canvas_sync/misc_helper.rb +1 -1
  45. data/lib/canvas_sync/version.rb +1 -1
  46. data/lib/canvas_sync.rb +4 -3
  47. data/spec/dummy/app/models/rubric.rb +2 -1
  48. data/spec/dummy/config/environments/test.rb +1 -1
  49. data/spec/job_batching/batch_spec.rb +49 -7
  50. data/spec/job_batching/{active_job_spec.rb → compat/active_job_spec.rb} +2 -2
  51. data/spec/job_batching/{sidekiq_spec.rb → compat/sidekiq_spec.rb} +14 -12
  52. data/spec/job_batching/flow_spec.rb +1 -1
  53. data/spec/job_batching/integration_helper.rb +1 -1
  54. data/spec/job_batching/status_spec.rb +2 -2
  55. data/spec/job_uniqueness/compat/active_job_spec.rb +49 -0
  56. data/spec/job_uniqueness/compat/sidekiq_spec.rb +68 -0
  57. data/spec/job_uniqueness/lock_context_spec.rb +95 -0
  58. data/spec/job_uniqueness/on_conflict/log_spec.rb +11 -0
  59. data/spec/job_uniqueness/on_conflict/raise_spec.rb +10 -0
  60. data/spec/job_uniqueness/on_conflict/reschedule_spec.rb +24 -0
  61. data/spec/job_uniqueness/on_conflict_spec.rb +16 -0
  62. data/spec/job_uniqueness/spec_helper.rb +14 -0
  63. data/spec/job_uniqueness/strategy/base_spec.rb +100 -0
  64. data/spec/job_uniqueness/strategy/until_and_while_executing_spec.rb +48 -0
  65. data/spec/job_uniqueness/strategy/until_executed_spec.rb +23 -0
  66. data/spec/job_uniqueness/strategy/until_executing_spec.rb +23 -0
  67. data/spec/job_uniqueness/strategy/until_expired_spec.rb +23 -0
  68. data/spec/job_uniqueness/strategy/while_executing_spec.rb +33 -0
  69. data/spec/job_uniqueness/support/lock_strategy.rb +28 -0
  70. data/spec/job_uniqueness/support/on_conflict.rb +24 -0
  71. data/spec/job_uniqueness/support/test_worker.rb +19 -0
  72. data/spec/job_uniqueness/unique_job_common_spec.rb +45 -0
  73. data/spec/spec_helper.rb +1 -1
  74. metadata +278 -204
  75. /data/lib/canvas_sync/job_batches/{sidekiq → compat/sidekiq}/web/batches_assets/css/styles.less +0 -0
  76. /data/lib/canvas_sync/job_batches/{sidekiq → compat/sidekiq}/web/batches_assets/js/batch_tree.js +0 -0
  77. /data/lib/canvas_sync/job_batches/{sidekiq → compat/sidekiq}/web/batches_assets/js/util.js +0 -0
  78. /data/lib/canvas_sync/job_batches/{sidekiq → compat/sidekiq}/web/views/_batch_tree.erb +0 -0
  79. /data/lib/canvas_sync/job_batches/{sidekiq → compat/sidekiq}/web/views/_batches_table.erb +0 -0
  80. /data/lib/canvas_sync/job_batches/{sidekiq → compat/sidekiq}/web/views/_common.erb +0 -0
  81. /data/lib/canvas_sync/job_batches/{sidekiq → compat/sidekiq}/web/views/_jobs_table.erb +0 -0
  82. /data/lib/canvas_sync/job_batches/{sidekiq → compat/sidekiq}/web/views/_pagination.erb +0 -0
  83. /data/lib/canvas_sync/job_batches/{sidekiq → compat/sidekiq}/web/views/batch.erb +0 -0
  84. /data/lib/canvas_sync/job_batches/{sidekiq → compat/sidekiq}/web/views/batches.erb +0 -0
  85. /data/lib/canvas_sync/job_batches/{sidekiq → compat/sidekiq}/web/views/pool.erb +0 -0
  86. /data/lib/canvas_sync/job_batches/{sidekiq → compat/sidekiq}/web/views/pools.erb +0 -0
@@ -1,159 +1,157 @@
1
- module CanvasSync
2
- module JobBatches
3
- class ContextHash
4
- delegate_missing_to :flatten
5
-
6
- def initialize(bid, hash = nil)
7
- @bid_stack = [bid]
8
- @hash_map = {}
9
- @dirty = false
10
- @flattened = nil
11
- @hash_map[bid] = hash.with_indifferent_access if hash
12
- end
13
-
14
- # Local is "the nearest batch with a context value"
15
- # This allows for, for example, SerialBatchJob to have a modifiable context stored on it's main Batch
16
- # that can be accessed transparently from one of it's internal, context-less Batches
17
- def local_bid
18
- bid = @bid_stack[-1]
19
- while bid.present?
20
- bhash = resolve_hash(bid)
21
- return bid if bhash
22
- bid = get_parent_bid(bid)
23
- end
24
- nil
25
- end
1
+ module CanvasSync::JobBatches
2
+ class ContextHash
3
+ delegate_missing_to :flatten
4
+
5
+ def initialize(bid, hash = nil)
6
+ @bid_stack = [bid]
7
+ @hash_map = {}
8
+ @dirty = false
9
+ @flattened = nil
10
+ @hash_map[bid] = hash.with_indifferent_access if hash
11
+ end
26
12
 
27
- def local
28
- @hash_map[local_bid]
29
- end
13
+ # Local is "the nearest batch with a context value"
14
+ # This allows for, for example, SerialBatchJob to have a modifiable context stored on it's main Batch
15
+ # that can be accessed transparently from one of it's internal, context-less Batches
16
+ def local_bid
17
+ bid = @bid_stack[-1]
18
+ while bid.present?
19
+ bhash = resolve_hash(bid)
20
+ return bid if bhash
21
+ bid = get_parent_bid(bid)
22
+ end
23
+ nil
24
+ end
30
25
 
31
- def own
32
- resolve_hash(@bid_stack[-1]) || {}
33
- end
26
+ def local
27
+ @hash_map[local_bid]
28
+ end
34
29
 
35
- def set_local(new_hash)
36
- @dirty = true
37
- local.clear.merge!(new_hash)
38
- end
30
+ def own
31
+ resolve_hash(@bid_stack[-1]) || {}
32
+ end
39
33
 
40
- def clear
41
- local.clear
42
- @flattened = nil
43
- @dirty = true
44
- self
45
- end
34
+ def set_local(new_hash)
35
+ @dirty = true
36
+ local.clear.merge!(new_hash)
37
+ end
46
38
 
47
- def []=(key, value)
48
- @flattened = nil
49
- @dirty = true
50
- local[key] = value
51
- end
39
+ def clear
40
+ local.clear
41
+ @flattened = nil
42
+ @dirty = true
43
+ self
44
+ end
52
45
 
53
- def [](key)
54
- bid = @bid_stack[-1]
55
- while bid.present?
56
- bhash = resolve_hash(bid)
57
- return bhash[key] if bhash&.key?(key)
58
- bid = get_parent_bid(bid)
59
- end
60
- nil
61
- end
46
+ def []=(key, value)
47
+ @flattened = nil
48
+ @dirty = true
49
+ local[key] = value
50
+ end
62
51
 
63
- def reload!
64
- @dirty = false
65
- @hash_map = {}
66
- self
52
+ def [](key)
53
+ bid = @bid_stack[-1]
54
+ while bid.present?
55
+ bhash = resolve_hash(bid)
56
+ return bhash[key] if bhash&.key?(key)
57
+ bid = get_parent_bid(bid)
67
58
  end
59
+ nil
60
+ end
68
61
 
69
- def save!(force: false)
70
- return unless dirty? || force
71
- Batch.redis do |r|
72
- r.hset("BID-#{local_bid}", 'context', JSON.unparse(local))
73
- end
74
- end
62
+ def reload!
63
+ @dirty = false
64
+ @hash_map = {}
65
+ self
66
+ end
75
67
 
76
- def dirty?
77
- @dirty
68
+ def save!(force: false)
69
+ return unless dirty? || force
70
+ Batch.redis do |r|
71
+ r.hset("BID-#{local_bid}", 'context', JSON.unparse(local))
78
72
  end
73
+ end
79
74
 
80
- def is_a?(arg)
81
- return true if Hash <= arg
82
- super
83
- end
75
+ def dirty?
76
+ @dirty
77
+ end
84
78
 
85
- def flatten
86
- return @flattened if @flattened
79
+ def is_a?(arg)
80
+ return true if Hash <= arg
81
+ super
82
+ end
87
83
 
88
- load_all
89
- flattened = {}
90
- @bid_stack.compact.each do |bid|
91
- flattened.merge!(@hash_map[bid]) if @hash_map[bid]
92
- end
93
- flattened.freeze
84
+ def flatten
85
+ return @flattened if @flattened
94
86
 
95
- @flattened = flattened.with_indifferent_access
87
+ load_all
88
+ flattened = {}
89
+ @bid_stack.compact.each do |bid|
90
+ flattened.merge!(@hash_map[bid]) if @hash_map[bid]
96
91
  end
92
+ flattened.freeze
97
93
 
98
- def to_h
99
- flatten
100
- end
94
+ @flattened = flattened.with_indifferent_access
95
+ end
101
96
 
102
- private
97
+ def to_h
98
+ flatten
99
+ end
103
100
 
104
- def get_parent_hash(bid)
105
- resolve_hash(get_parent_bid(bid)).freeze
106
- end
101
+ private
107
102
 
108
- def get_parent_bid(bid)
109
- index = @bid_stack.index(bid)
110
- raise "Invalid BID #{bid}" if index.nil? # Sanity Check - this shouldn't happen
111
-
112
- index -= 1
113
- if index >= 0
114
- @bid_stack[index]
115
- else
116
- pbid = Batch.redis do |r|
117
- callback_params = JSON.parse(r.hget("BID-#{bid}", "callback_params") || "{}")
118
- callback_params['for_bid'] || r.hget("BID-#{bid}", "parent_bid")
119
- end
120
- @bid_stack.unshift(pbid)
121
- pbid
103
+ def get_parent_hash(bid)
104
+ resolve_hash(get_parent_bid(bid)).freeze
105
+ end
106
+
107
+ def get_parent_bid(bid)
108
+ index = @bid_stack.index(bid)
109
+ raise "Invalid BID #{bid}" if index.nil? # Sanity Check - this shouldn't happen
110
+
111
+ index -= 1
112
+ if index >= 0
113
+ @bid_stack[index]
114
+ else
115
+ pbid = Batch.redis do |r|
116
+ callback_params = JSON.parse(r.hget("BID-#{bid}", "callback_params") || "{}")
117
+ callback_params['for_bid'] || r.hget("BID-#{bid}", "parent_bid")
122
118
  end
119
+ @bid_stack.unshift(pbid)
120
+ pbid
123
121
  end
122
+ end
124
123
 
125
- def resolve_hash(bid)
126
- return nil unless bid.present?
127
- return @hash_map[bid] if @hash_map.key?(bid)
124
+ def resolve_hash(bid)
125
+ return nil unless bid.present?
126
+ return @hash_map[bid] if @hash_map.key?(bid)
128
127
 
129
- context_json, editable = Batch.redis do |r|
130
- r.multi do |r|
131
- r.hget("BID-#{bid}", "context")
132
- r.hget("BID-#{bid}", "allow_context_changes")
133
- end
128
+ context_json, editable = Batch.redis do |r|
129
+ r.multi do |r|
130
+ r.hget("BID-#{bid}", "context")
131
+ r.hget("BID-#{bid}", "allow_context_changes")
134
132
  end
133
+ end
135
134
 
136
- if context_json.present?
137
- context_hash = JSON.parse(context_json)
138
- context_hash = context_hash.with_indifferent_access
139
- context_hash.each do |k, v|
140
- v.freeze
141
- end
142
- context_hash.freeze unless editable
143
-
144
- @hash_map[bid] = context_hash
145
- else
146
- @hash_map[bid] = nil
135
+ if context_json.present?
136
+ context_hash = JSON.parse(context_json)
137
+ context_hash = context_hash.with_indifferent_access
138
+ context_hash.each do |k, v|
139
+ v.freeze
147
140
  end
141
+ context_hash.freeze unless editable
142
+
143
+ @hash_map[bid] = context_hash
144
+ else
145
+ @hash_map[bid] = nil
148
146
  end
147
+ end
149
148
 
150
- def load_all
151
- resolve_hash(@bid_stack[0]).freeze
152
- while @bid_stack[0].present?
153
- get_parent_hash(@bid_stack[0])
154
- end
155
- @hash_map
149
+ def load_all
150
+ resolve_hash(@bid_stack[0]).freeze
151
+ while @bid_stack[0].present?
152
+ get_parent_hash(@bid_stack[0])
156
153
  end
154
+ @hash_map
157
155
  end
158
156
  end
159
157
  end
@@ -1,7 +1,5 @@
1
- module CanvasSync
2
- module JobBatches
3
- class BaseJob < ::ActiveJob::Base
1
+ module CanvasSync::JobBatches
2
+ class BaseJob < ::ActiveJob::Base
4
3
 
5
- end
6
4
  end
7
5
  end
@@ -1,22 +1,20 @@
1
1
  require_relative './base_job'
2
2
 
3
- module CanvasSync
4
- module JobBatches
5
- class ConcurrentBatchJob < BaseJob
6
- def self.make_batch(sub_jobs, **kwargs, &blk)
7
- ManagedBatchJob.make_batch(
8
- sub_jobs,
9
- **kwargs,
10
- ordered: false,
11
- concurrency: true,
12
- desc_prefix: 'ConcurrentBatchJob: ',
13
- &blk
14
- )
15
- end
3
+ module CanvasSync::JobBatches
4
+ class ConcurrentBatchJob < BaseJob
5
+ def self.make_batch(sub_jobs, **kwargs, &blk)
6
+ ManagedBatchJob.make_batch(
7
+ sub_jobs,
8
+ **kwargs,
9
+ ordered: false,
10
+ concurrency: true,
11
+ desc_prefix: 'ConcurrentBatchJob: ',
12
+ &blk
13
+ )
14
+ end
16
15
 
17
- def perform(sub_jobs, **kwargs)
18
- self.class.make_batch(sub_jobs, **kwargs)
19
- end
16
+ def perform(sub_jobs, **kwargs)
17
+ self.class.make_batch(sub_jobs, **kwargs)
20
18
  end
21
19
  end
22
20
  end
@@ -1,170 +1,168 @@
1
1
  require_relative './base_job'
2
2
 
3
- module CanvasSync
4
- module JobBatches
5
- class ManagedBatchJob < BaseJob
6
- def self.make_batch(sub_jobs, ordered: true, concurrency: nil, context: nil, preflight_check: nil, desc_prefix: nil, &blk)
7
- desc_prefix ||= ''
8
-
9
- if concurrency == 0 || concurrency == nil || concurrency == true
10
- concurrency = sub_jobs.count
11
- elsif concurrency == false
12
- concurrency = 1
13
- end
3
+ module CanvasSync::JobBatches
4
+ class ManagedBatchJob < BaseJob
5
+ def self.make_batch(sub_jobs, ordered: true, concurrency: nil, context: nil, preflight_check: nil, desc_prefix: nil, &blk)
6
+ desc_prefix ||= ''
7
+
8
+ if concurrency == 0 || concurrency == nil || concurrency == true
9
+ concurrency = sub_jobs.count
10
+ elsif concurrency == false
11
+ concurrency = 1
12
+ end
13
+
14
+ root_batch = Batch.new
15
+ man_batch_id = nil
16
+
17
+ if concurrency < sub_jobs.count
18
+ man_batch_id = SecureRandom.urlsafe_base64(10)
14
19
 
15
- root_batch = Batch.new
16
- man_batch_id = nil
17
-
18
- if concurrency < sub_jobs.count
19
- man_batch_id = SecureRandom.urlsafe_base64(10)
20
-
21
- Batch.redis do |r|
22
- r.multi do |r|
23
- r.hset("MNGBID-#{man_batch_id}", "root_bid", root_batch.bid)
24
- r.hset("MNGBID-#{man_batch_id}", "ordered", ordered ? 1 : 0)
25
- r.hset("MNGBID-#{man_batch_id}", "concurrency", concurrency)
26
- r.hset("MNGBID-#{man_batch_id}", "preflight_check", preflight_check) if preflight_check.present?
27
- r.expire("MNGBID-#{man_batch_id}", Batch::BID_EXPIRE_TTL)
28
-
29
- mapped_sub_jobs = sub_jobs.each_with_index.map do |j, i|
30
- j['_mngbid_index_'] = i # This allows duplicate jobs when a Redis Set is used
31
- j = ::ActiveJob::Arguments.serialize([j])
32
- JSON.unparse(j)
33
- end
34
- if ordered
35
- r.rpush("MNGBID-#{man_batch_id}-jobs", mapped_sub_jobs)
36
- else
37
- r.sadd("MNGBID-#{man_batch_id}-jobs", mapped_sub_jobs)
38
- end
39
- r.expire("MNGBID-#{man_batch_id}-jobs", Batch::BID_EXPIRE_TTL)
20
+ Batch.redis do |r|
21
+ r.multi do |r|
22
+ r.hset("MNGBID-#{man_batch_id}", "root_bid", root_batch.bid)
23
+ r.hset("MNGBID-#{man_batch_id}", "ordered", ordered ? 1 : 0)
24
+ r.hset("MNGBID-#{man_batch_id}", "concurrency", concurrency)
25
+ r.hset("MNGBID-#{man_batch_id}", "preflight_check", preflight_check) if preflight_check.present?
26
+ r.expire("MNGBID-#{man_batch_id}", Batch::BID_EXPIRE_TTL)
27
+
28
+ mapped_sub_jobs = sub_jobs.each_with_index.map do |j, i|
29
+ j['_mngbid_index_'] = i # This allows duplicate jobs when a Redis Set is used
30
+ j = ::ActiveJob::Arguments.serialize([j])
31
+ JSON.unparse(j)
40
32
  end
33
+ if ordered
34
+ r.rpush("MNGBID-#{man_batch_id}-jobs", mapped_sub_jobs)
35
+ else
36
+ r.sadd("MNGBID-#{man_batch_id}-jobs", mapped_sub_jobs)
37
+ end
38
+ r.expire("MNGBID-#{man_batch_id}-jobs", Batch::BID_EXPIRE_TTL)
41
39
  end
40
+ end
42
41
 
43
- root_batch.allow_context_changes = (concurrency == 1)
44
- root_batch.on(:success, "#{to_s}.cleanup_redis", managed_batch_id: man_batch_id)
42
+ root_batch.allow_context_changes = (concurrency == 1)
43
+ root_batch.on(:success, "#{to_s}.cleanup_redis", managed_batch_id: man_batch_id)
45
44
 
46
- desc_prefix = "MGD(#{man_batch_id}): #{desc_prefix}"
47
- end
45
+ desc_prefix = "MGD(#{man_batch_id}): #{desc_prefix}"
46
+ end
48
47
 
49
- root_batch.context = context
48
+ root_batch.context = context
50
49
 
51
- blk.call(ManagedBatchProxy.new(root_batch)) if blk.present?
50
+ blk.call(ManagedBatchProxy.new(root_batch)) if blk.present?
52
51
 
53
- root_batch.description = "#{desc_prefix}#{root_batch.description || 'Root'}"
52
+ root_batch.description = "#{desc_prefix}#{root_batch.description || 'Root'}"
54
53
 
55
- root_batch.context["managed_batch_bid"] = man_batch_id if man_batch_id
54
+ root_batch.context["managed_batch_bid"] = man_batch_id if man_batch_id
56
55
 
57
- if concurrency < sub_jobs.count
58
- root_batch.jobs {}
59
- concurrency.times do
60
- perform_next_sequence_job(man_batch_id, skip_preflight: true)
61
- end
62
- else
63
- root_batch.jobs do
64
- sub_jobs.each do |j|
65
- ChainBuilder.enqueue_job(j)
66
- end
56
+ if concurrency < sub_jobs.count
57
+ root_batch.jobs {}
58
+ concurrency.times do
59
+ perform_next_sequence_job(man_batch_id, skip_preflight: true)
60
+ end
61
+ else
62
+ root_batch.jobs do
63
+ sub_jobs.each do |j|
64
+ ChainBuilder.enqueue_job(j)
67
65
  end
68
66
  end
69
-
70
- root_batch
71
67
  end
72
68
 
73
- def perform(sub_jobs, **kwargs)
74
- self.class.make_batch(sub_jobs, **kwargs)
75
- end
69
+ root_batch
70
+ end
76
71
 
77
- def self.cleanup_redis(status, options)
78
- man_batch_id = options['managed_batch_id']
79
- Batch.redis do |r|
80
- r.del(
81
- "MNGBID-#{man_batch_id}",
82
- "MNGBID-#{man_batch_id}-jobs",
83
- )
84
- end
85
- end
72
+ def perform(sub_jobs, **kwargs)
73
+ self.class.make_batch(sub_jobs, **kwargs)
74
+ end
86
75
 
87
- def self.job_succeeded_callback(status, options)
88
- man_batch_id = options['managed_batch_id']
89
- perform_next_sequence_job(man_batch_id)
76
+ def self.cleanup_redis(status, options)
77
+ man_batch_id = options['managed_batch_id']
78
+ Batch.redis do |r|
79
+ r.del(
80
+ "MNGBID-#{man_batch_id}",
81
+ "MNGBID-#{man_batch_id}-jobs",
82
+ )
90
83
  end
84
+ end
91
85
 
92
- protected
86
+ def self.job_succeeded_callback(status, options)
87
+ man_batch_id = options['managed_batch_id']
88
+ perform_next_sequence_job(man_batch_id)
89
+ end
93
90
 
94
- def self.perform_next_sequence_job(man_batch_id, skip_preflight: false)
95
- root_bid, ordered, preflight_check = Batch.redis do |r|
96
- r.multi do |r|
97
- r.hget("MNGBID-#{man_batch_id}", "root_bid")
98
- r.hget("MNGBID-#{man_batch_id}", "ordered")
99
- r.hget("MNGBID-#{man_batch_id}", "preflight_check")
100
- end
91
+ protected
92
+
93
+ def self.perform_next_sequence_job(man_batch_id, skip_preflight: false)
94
+ root_bid, ordered, preflight_check = Batch.redis do |r|
95
+ r.multi do |r|
96
+ r.hget("MNGBID-#{man_batch_id}", "root_bid")
97
+ r.hget("MNGBID-#{man_batch_id}", "ordered")
98
+ r.hget("MNGBID-#{man_batch_id}", "preflight_check")
101
99
  end
100
+ end
102
101
 
103
- if !skip_preflight && preflight_check.present?
104
- if preflight_check.include?(".")
105
- clazz, method_name = preflight_check.split('.')
106
- clazz = clazz.constantize
107
- else
108
- clazz = Object
109
- method_name = preflight_check
110
- end
111
- preflight_check = ->(*args) { clazz.send(method_name, *args) }
102
+ if !skip_preflight && preflight_check.present?
103
+ if preflight_check.include?(".")
104
+ clazz, method_name = preflight_check.split('.')
105
+ clazz = clazz.constantize
112
106
  else
113
- preflight_check = ->(*args) { true }
107
+ clazz = Object
108
+ method_name = preflight_check
114
109
  end
110
+ preflight_check = ->(*args) { clazz.send(method_name, *args) }
111
+ else
112
+ preflight_check = ->(*args) { true }
113
+ end
115
114
 
116
- ordered = CanvasSync::MiscHelper.to_boolean(ordered)
115
+ ordered = CanvasSync::MiscHelper.to_boolean(ordered)
117
116
 
118
- loop do
119
- next_job_json = Batch.redis do |r|
120
- if ordered
121
- r.lpop("MNGBID-#{man_batch_id}-jobs")
122
- else
123
- r.spop("MNGBID-#{man_batch_id}-jobs")
124
- end
117
+ loop do
118
+ next_job_json = Batch.redis do |r|
119
+ if ordered
120
+ r.lpop("MNGBID-#{man_batch_id}-jobs")
121
+ else
122
+ r.spop("MNGBID-#{man_batch_id}-jobs")
125
123
  end
124
+ end
126
125
 
127
- break unless next_job_json.present?
126
+ break unless next_job_json.present?
128
127
 
129
- next_job = JSON.parse(next_job_json)
130
- next_job = ::ActiveJob::Arguments.deserialize(next_job)[0]
128
+ next_job = JSON.parse(next_job_json)
129
+ next_job = ::ActiveJob::Arguments.deserialize(next_job)[0]
131
130
 
132
- preflight_result = preflight_check.call(next_job)
133
- if preflight_result == :abort
134
- cleanup_redis(nil, { "managed_batch_id" => man_batch_id })
135
- break
136
- elsif !preflight_check
137
- next
138
- end
131
+ preflight_result = preflight_check.call(next_job)
132
+ if preflight_result == :abort
133
+ cleanup_redis(nil, { "managed_batch_id" => man_batch_id })
134
+ break
135
+ elsif !preflight_check
136
+ next
137
+ end
139
138
 
140
- Batch.new(root_bid).jobs do
141
- Batch.new.tap do |batch|
142
- batch.description = "Managed Batch Fiber (#{man_batch_id})"
143
- batch.on(:success, "#{self.to_s}.job_succeeded_callback", managed_batch_id: man_batch_id)
144
- batch.jobs do
145
- ChainBuilder.enqueue_job(next_job)
146
- end
139
+ Batch.new(root_bid).jobs do
140
+ Batch.new.tap do |batch|
141
+ batch.description = "Managed Batch Fiber (#{man_batch_id})"
142
+ batch.on(:success, "#{self.to_s}.job_succeeded_callback", managed_batch_id: man_batch_id)
143
+ batch.jobs do
144
+ ChainBuilder.enqueue_job(next_job)
147
145
  end
148
146
  end
149
-
150
- break
151
147
  end
152
- end
153
148
 
154
- class ManagedBatchProxy
155
- def initialize(real_batch)
156
- @real_batch = real_batch
157
- end
149
+ break
150
+ end
151
+ end
158
152
 
159
- delegate_missing_to :real_batch
153
+ class ManagedBatchProxy
154
+ def initialize(real_batch)
155
+ @real_batch = real_batch
156
+ end
160
157
 
161
- def jobs
162
- raise "Managed Batches do not support calling .jobs directly!"
163
- end
158
+ delegate_missing_to :real_batch
164
159
 
165
- private
166
- attr_reader :real_batch
160
+ def jobs
161
+ raise "Managed Batches do not support calling .jobs directly!"
167
162
  end
163
+
164
+ private
165
+ attr_reader :real_batch
168
166
  end
169
167
  end
170
168
  end
@@ -1,22 +1,20 @@
1
1
  require_relative './base_job'
2
2
 
3
- module CanvasSync
4
- module JobBatches
5
- class SerialBatchJob < BaseJob
6
- def self.make_batch(sub_jobs, **kwargs, &blk)
7
- ManagedBatchJob.make_batch(
8
- sub_jobs,
9
- **kwargs,
10
- ordered: true,
11
- concurrency: false,
12
- desc_prefix: 'SerialBatchJob: ',
13
- &blk
14
- )
15
- end
3
+ module CanvasSync::JobBatches
4
+ class SerialBatchJob < BaseJob
5
+ def self.make_batch(sub_jobs, **kwargs, &blk)
6
+ ManagedBatchJob.make_batch(
7
+ sub_jobs,
8
+ **kwargs,
9
+ ordered: true,
10
+ concurrency: false,
11
+ desc_prefix: 'SerialBatchJob: ',
12
+ &blk
13
+ )
14
+ end
16
15
 
17
- def perform(sub_jobs, **kwargs)
18
- self.class.make_batch(sub_jobs, **kwargs)
19
- end
16
+ def perform(sub_jobs, **kwargs)
17
+ self.class.make_batch(sub_jobs, **kwargs)
20
18
  end
21
19
  end
22
20
  end