canvas_sync 0.21.1 → 0.22.0.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.
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