canvas_sync 0.22.0 → 0.22.2

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/lib/canvas_sync/job_batches/batch.rb +80 -62
  3. data/lib/canvas_sync/job_batches/compat/active_job.rb +1 -1
  4. data/lib/canvas_sync/job_batches/compat/sidekiq.rb +1 -1
  5. data/lib/canvas_sync/job_batches/jobs/managed_batch_job.rb +8 -1
  6. data/lib/canvas_sync/job_batches/pool.rb +20 -9
  7. data/lib/canvas_sync/jobs/canvas_process_waiter.rb +1 -1
  8. data/lib/canvas_sync/version.rb +1 -1
  9. data/spec/canvas_sync/jobs/sync_admins_job_spec.rb +1 -1
  10. data/spec/canvas_sync/jobs/sync_provisioning_report_job_spec.rb +1 -1
  11. data/spec/canvas_sync/jobs/sync_roles_job_spec.rb +1 -1
  12. data/spec/canvas_sync/jobs/sync_simple_table_job_spec.rb +1 -1
  13. data/spec/canvas_sync/models/accounts_spec.rb +1 -1
  14. data/spec/canvas_sync/models/admins_spec.rb +2 -2
  15. data/spec/canvas_sync/models/assignment_group_spec.rb +1 -1
  16. data/spec/canvas_sync/models/assignment_spec.rb +3 -3
  17. data/spec/canvas_sync/models/context_module_item_spec.rb +1 -1
  18. data/spec/canvas_sync/models/context_module_spec.rb +1 -1
  19. data/spec/canvas_sync/models/course_spec.rb +1 -1
  20. data/spec/canvas_sync/models/enrollment_spec.rb +1 -1
  21. data/spec/canvas_sync/models/group_membership_spec.rb +1 -1
  22. data/spec/canvas_sync/models/group_spec.rb +1 -1
  23. data/spec/canvas_sync/models/roles_spec.rb +2 -2
  24. data/spec/canvas_sync/models/section_spec.rb +1 -1
  25. data/spec/canvas_sync/models/submission_spec.rb +1 -1
  26. data/spec/canvas_sync/models/term_spec.rb +6 -6
  27. data/spec/canvas_sync/models/user_spec.rb +1 -1
  28. data/spec/canvas_sync/services/module_event_spec.rb +1 -1
  29. data/spec/canvas_sync/services/module_item_event_spec.rb +1 -1
  30. data/spec/factories/account_factory.rb +4 -4
  31. data/spec/factories/admin_factory.rb +4 -4
  32. data/spec/factories/assignment_factory.rb +1 -1
  33. data/spec/factories/assignment_group_factory.rb +3 -3
  34. data/spec/factories/context_module_factory.rb +4 -4
  35. data/spec/factories/context_module_item_factory.rb +2 -2
  36. data/spec/factories/course_factory.rb +3 -3
  37. data/spec/factories/enrollment_factory.rb +1 -1
  38. data/spec/factories/group_factory.rb +3 -3
  39. data/spec/factories/group_membership_factory.rb +2 -2
  40. data/spec/factories/role_factory.rb +4 -4
  41. data/spec/factories/section_factory.rb +1 -1
  42. data/spec/factories/submission_factory.rb +1 -1
  43. data/spec/factories/term_factory.rb +5 -5
  44. data/spec/factories/user_factory.rb +4 -4
  45. data/spec/job_batching/batch_spec.rb +2 -2
  46. data/spec/job_batching/compat/active_job_spec.rb +1 -1
  47. data/spec/job_batching/compat/sidekiq_spec.rb +2 -2
  48. data/spec/job_batching/status_spec.rb +1 -1
  49. data/spec/spec_helper.rb +5 -2
  50. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b659edf35a8c6f427f847142d4627920cc19effabfe7fb5ad2ccb960884cf47c
4
- data.tar.gz: 3264f9b298a5fcbf251a6ccd927ce20133598ed1b9fdd8adf3a728ef90a4e080
3
+ metadata.gz: 9c79e88e0f642fadba95afa7f6b6960a511144ad41d6c6333febc010e7fe2e3e
4
+ data.tar.gz: 26ab8638f656d00f93cbd0393d46b5e0a711ab7dfa94d60bf98bcb5fb42a1a7b
5
5
  SHA512:
6
- metadata.gz: a9c7add460f50301b9f404880e9f6ac2fc57996f1e4c8928f2c52b9bfa5f4973f6cc3c531729763a40de6cce127b86aed70b88ea11fc2119e9fe1856f81a4996
7
- data.tar.gz: 7d5951ebd7f02917344ea94c23d4f7e5d467d7d803be2944ab1d073aa207acca55a065aa8e2b9145f129154c1ed10b9fb2d14b0692c1e1d8ec21a99f042dab8a
6
+ metadata.gz: d06042a0cb184a7f1efdfaf3b3e755967d97d13c8ed4a9d436eaedb5f7ebe0de0007ab58e8b6f1ad1fc520d4be1e6c139d81b292c7edb79dd8c6d3b6b491c879
7
+ data.tar.gz: cf3240e17d1df90858e1216c7e1ad8db3d92835d9ad10a17a3fc0f85a309058462e13a121ef156dee75b08adc05731f68a486de7c22c3b3b78cfab65395dca0f
@@ -98,30 +98,14 @@ module CanvasSync::JobBatches
98
98
  def jobs
99
99
  raise NoBlockGivenError unless block_given?
100
100
 
101
- if !@existing && !@initialized
102
- parent_bid = Thread.current[CURRENT_BATCH_THREAD_KEY]&.bid
103
-
104
- redis.multi do |r|
105
- r.hset(@bidkey, "parent_bid", parent_bid.to_s) if parent_bid
106
- r.expire(@bidkey, BID_EXPIRE_TTL)
107
-
108
- if parent_bid
109
- r.hincrby("BID-#{parent_bid}", "children", 1)
110
- r.expire("BID-#{parent_bid}", BID_EXPIRE_TTL)
111
- r.zadd("BID-#{parent_bid}-bids", created_at, bid)
112
- else
113
- r.zadd("BID-ROOT-bids", created_at, bid)
114
- end
115
- end
101
+ persist!
116
102
 
117
- flush_pending_attrs
118
- @context&.save!
119
-
120
- @initialized = true
121
- else
122
- assert_batch_is_open
123
- end
103
+ # TODO This keep_open! block is probably desired, but it has some caveats:
104
+ # - Old logic didn't auto-clean empty batches
105
+ # - Could be an issue if the Thread crashes at a bad moment (do we even need to plan for this?)
106
+ # - Technically there could be a race condition without it, but such hasn't been observed
124
107
 
108
+ # keep_open! do
125
109
  begin
126
110
  parent = Thread.current[CURRENT_BATCH_THREAD_KEY]
127
111
  Thread.current[CURRENT_BATCH_THREAD_KEY] = self
@@ -129,13 +113,16 @@ module CanvasSync::JobBatches
129
113
  ensure
130
114
  Thread.current[CURRENT_BATCH_THREAD_KEY] = parent
131
115
  end
116
+ # end
132
117
 
133
118
  nil
134
119
  end
135
120
 
136
- def increment_job_queue(jid)
137
- assert_batch_is_open
138
- append_jobs([jid])
121
+ # Mark this Batch as a placeholder. It will be persisted to Redis, but no jobs will be added.
122
+ # From here, you can either use `.jobs` on the batch to add jobs as usual, or call `.let_close!` to allow cleanup to occur.
123
+ def placeholder!
124
+ # TODO Provide a stable `let_close!` token?
125
+ persist!
139
126
  end
140
127
 
141
128
  def invalidate_all
@@ -157,35 +144,36 @@ module CanvasSync::JobBatches
157
144
  batch.parent ? valid && valid?(batch.parent) : valid
158
145
  end
159
146
 
160
- def keep_open!
147
+ def keep_open!(token = SecureRandom.urlsafe_base64(10))
161
148
  if block_given?
162
149
  begin
163
- keep_open!
150
+ token = keep_open!(token)
164
151
  yield
165
152
  ensure
166
- let_close!
153
+ let_close!(token)
167
154
  end
168
155
  else
169
- redis.hset(@bidkey, 'keep_open', "true")
170
- end
171
- end
156
+ persist!
157
+
158
+ redis.multi do |r|
159
+ r.sadd("#{@bidkey}-holds", token)
160
+ r.expire("#{@bidkey}-holds", BID_EXPIRE_TTL)
161
+ end
172
162
 
173
- def let_close!
174
- _, failed, pending, children, complete, success = redis.multi do |r|
175
- r.hset(@bidkey, 'keep_open', "false")
163
+ assert_batch_is_open
176
164
 
177
- r.scard("BID-#{bid}-failed")
178
- r.hincrby("BID-#{bid}", "pending", 0)
179
- r.hincrby("BID-#{bid}", "children", 0)
180
- r.scard("BID-#{bid}-batches-complete")
181
- r.scard("BID-#{bid}-batches-success")
165
+ token
182
166
  end
167
+ end
183
168
 
184
- all_success = pending.to_i.zero? && children == success
185
- # if complete or successfull call complete callback (the complete callback may then call successful)
186
- if (pending.to_i == failed.to_i && children == complete) || all_success
187
- self.class.enqueue_callbacks(:complete, bid)
188
- self.class.enqueue_callbacks(:success, bid) if all_success
169
+ def let_close!(token = :unset)
170
+ self.class.with_callback_check(bid, only: %i[complete success]) do |r|
171
+ if token == :unset # Legacy
172
+ r.del("#{@bidkey}-holds")
173
+ r.hset(@bidkey, 'keep_open', "false")
174
+ else
175
+ r.srem("#{@bidkey}-holds", token)
176
+ end
189
177
  end
190
178
  end
191
179
 
@@ -203,6 +191,23 @@ module CanvasSync::JobBatches
203
191
  with_batch(nil, &blk)
204
192
  end
205
193
 
194
+ def append_jobs(jids)
195
+ jids = Array(jids)
196
+ jids = jids.uniq
197
+ return unless jids.size > 0
198
+
199
+ redis do |r|
200
+ tme = Time.now.utc.to_f
201
+ added = r.zadd(@bidkey + "-jids", jids.map{|jid| [tme, jid] }, nx: true)
202
+ r.multi do |r|
203
+ r.hincrby(@bidkey, "pending", added)
204
+ r.hincrby(@bidkey, "job_count", added)
205
+ r.expire(@bidkey, BID_EXPIRE_TTL)
206
+ r.expire(@bidkey + "-jids", BID_EXPIRE_TTL)
207
+ end
208
+ end
209
+ end
210
+
206
211
  protected
207
212
 
208
213
  def redis_key
@@ -214,28 +219,34 @@ module CanvasSync::JobBatches
214
219
  redis.zadd("batches", created_at, bid) if INDEX_ALL_BATCHES
215
220
  end
216
221
 
217
- private
218
-
219
222
  def assert_batch_is_open
220
223
  unless defined?(@closed)
221
- @closed = redis.hget(@bidkey, 'success') == 'true'
224
+ @closed = redis.hget(@bidkey, 'complete') == 'true'
222
225
  end
223
226
  raise "Cannot add jobs to Batch #{} bid - it has already entered the callback-stage" if @closed
224
227
  end
225
228
 
226
- def append_jobs(jids)
227
- jids = jids.uniq
228
- return unless jids.size > 0
229
+ def persist!
230
+ if !@existing && !@initialized
231
+ parent_bid = Thread.current[CURRENT_BATCH_THREAD_KEY]&.bid
229
232
 
230
- redis do |r|
231
- tme = Time.now.utc.to_f
232
- added = r.zadd(@bidkey + "-jids", jids.map{|jid| [tme, jid] }, nx: true)
233
- r.multi do |r|
234
- r.hincrby(@bidkey, "pending", added)
235
- r.hincrby(@bidkey, "job_count", added)
233
+ redis.multi do |r|
234
+ r.hset(@bidkey, "parent_bid", parent_bid.to_s) if parent_bid
236
235
  r.expire(@bidkey, BID_EXPIRE_TTL)
237
- r.expire(@bidkey + "-jids", BID_EXPIRE_TTL)
236
+
237
+ if parent_bid
238
+ r.hincrby("BID-#{parent_bid}", "children", 1)
239
+ r.expire("BID-#{parent_bid}", BID_EXPIRE_TTL)
240
+ r.zadd("BID-#{parent_bid}-bids", created_at, bid)
241
+ else
242
+ r.zadd("BID-ROOT-bids", created_at, bid)
243
+ end
238
244
  end
245
+
246
+ flush_pending_attrs
247
+ @context&.save!
248
+
249
+ @initialized = true
239
250
  end
240
251
  end
241
252
 
@@ -269,6 +280,7 @@ module CanvasSync::JobBatches
269
280
  # Misc
270
281
  r.hget("BID-#{bid}", "parent_bid")
271
282
  r.hget("BID-#{bid}", "keep_open")
283
+ r.scard("BID-#{bid}-holds")
272
284
 
273
285
  # Jobs
274
286
  r.hincrby("BID-#{bid}", "pending", 0)
@@ -295,13 +307,18 @@ module CanvasSync::JobBatches
295
307
  # "failed" = dead or retrying
296
308
  # "complete" = successful or failed
297
309
 
298
- parent_bid, keep_open, \
310
+ parent_bid, keep_open, holds, \
299
311
  pending_jobs, failed_jobs, dead_jobs, \
300
312
  child_batches, complete_batches, success_batches, failed_batches, stagnated_batches \
301
313
  = actual_results
302
314
 
303
315
  pending_batches = child_batches - success_batches
304
316
 
317
+ if keep_open == 'true' || (holds && holds > 0)
318
+ except << :complete
319
+ except << :success
320
+ end
321
+
305
322
  trigger_callback = ->(callback) {
306
323
  next if except.include?(callback.to_sym)
307
324
  next unless only.include?(callback.to_sym)
@@ -360,11 +377,10 @@ module CanvasSync::JobBatches
360
377
  batch_key = "BID-#{bid}"
361
378
  callback_key = "#{batch_key}-callbacks-#{event}"
362
379
 
363
- callbacks, queue, parent_bid, callback_params = redis do |r|
364
- return unless r.exists?(batch_key)
365
- return if r.hget(batch_key, 'keep_open') == 'true'
366
-
380
+ exists, callbacks, queue, parent_bid, callback_params = redis do |r|
367
381
  r.multi do |r|
382
+ r.exists?(batch_key)
383
+
368
384
  r.smembers(callback_key)
369
385
  r.hget(batch_key, "callback_queue")
370
386
  r.hget(batch_key, "parent_bid")
@@ -372,6 +388,8 @@ module CanvasSync::JobBatches
372
388
  end
373
389
  end
374
390
 
391
+ return unless exists
392
+
375
393
  queue ||= "default"
376
394
  parent_bid = !parent_bid || parent_bid.empty? ? nil : parent_bid # Basically parent_bid.blank?
377
395
 
@@ -28,7 +28,7 @@ module CanvasSync::JobBatches
28
28
  around_enqueue do |job, block|
29
29
  if (batch = Thread.current[CURRENT_BATCH_THREAD_KEY])
30
30
  @bid = batch.bid
31
- batch.increment_job_queue(job_id) if @bid
31
+ batch.append_jobs(job_id) if @bid
32
32
  end
33
33
  block.call
34
34
  end
@@ -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['bid'] = batch.bid)
48
+ batch.append_jobs(msg['jid']) if (msg['bid'] = batch.bid)
49
49
  end
50
50
  yield
51
51
  end
@@ -54,7 +54,7 @@ module CanvasSync::JobBatches
54
54
  root_batch.context["managed_batch_bid"] = man_batch_id if man_batch_id
55
55
 
56
56
  if concurrency < sub_jobs.count
57
- root_batch.jobs {}
57
+ root_batch.placeholder!
58
58
  concurrency.times do
59
59
  perform_next_sequence_job(man_batch_id, skip_preflight: true)
60
60
  end
@@ -140,6 +140,13 @@ module CanvasSync::JobBatches
140
140
  Batch.new.tap do |batch|
141
141
  batch.description = "Managed Batch Fiber (#{man_batch_id})"
142
142
  batch.on(:success, "#{self.to_s}.job_succeeded_callback", managed_batch_id: man_batch_id)
143
+
144
+ if next_job[:chain_link].present?
145
+ # Annotate Batch with chain-step info
146
+ batch.context["csb:chain_link"] = next_job[:chain_link]
147
+ batch.on(:complete, "#{ChainBuilder.to_s}.chain_step_complete", chain_link: next_job[:chain_link])
148
+ end
149
+
143
150
  batch.jobs do
144
151
  ChainBuilder.enqueue_job(next_job)
145
152
  end
@@ -42,7 +42,7 @@ module CanvasSync::JobBatches
42
42
  wrapper.description = "Pool Job Wrapper (PID: #{pid})"
43
43
  checkin_event = (on_failed_job == :wait) ? :success : :complete
44
44
  wrapper.on(checkin_event, "#{self.class.to_s}.job_checked_in", pool_id: pid)
45
- wrapper.jobs {}
45
+ wrapper.placeholder!
46
46
 
47
47
  job_desc = job_desc.symbolize_keys
48
48
  job_desc = job_desc.merge!(
@@ -55,21 +55,31 @@ module CanvasSync::JobBatches
55
55
  refill_allotment unless skip_refill
56
56
  end
57
57
 
58
- def keep_open!
58
+ def keep_open!(token = SecureRandom.urlsafe_base64(10))
59
59
  if block_given?
60
60
  begin
61
- keep_open!
61
+ token = keep_open!(token)
62
62
  yield
63
63
  ensure
64
- let_close!
64
+ let_close!(token)
65
65
  end
66
66
  else
67
- redis.hset(redis_key, 'keep_open', 'true')
67
+ redis.multi do |r|
68
+ r.sadd("#{redis_key}-holds", token)
69
+ r.expire("#{redis_key}-holds", Batch::BID_EXPIRE_TTL)
70
+ end
71
+ token
68
72
  end
69
73
  end
70
74
 
71
- def let_close!
72
- redis.hset(redis_key, 'keep_open', 'false')
75
+ def let_close!(token = :unset)
76
+ if token == :unset # Legacy
77
+ redis.del("#{redis_key}-holds")
78
+ redis.hset(redis_key, 'keep_open', 'false')
79
+ else
80
+ redis.srem("#{redis_key}-holds", token)
81
+ end
82
+
73
83
  cleanup_if_empty
74
84
  end
75
85
 
@@ -87,15 +97,16 @@ module CanvasSync::JobBatches
87
97
  def cleanup_if_empty
88
98
  self.order
89
99
 
90
- activec, pactivec, pendingc, clean_when_empty, keep_open = redis.multi do |r|
100
+ activec, pactivec, pendingc, clean_when_empty, keep_open, holds = redis.multi do |r|
91
101
  r.hlen("#{redis_key}-active")
92
102
  r.hget(redis_key, "_active_count")
93
103
  pending_count(r)
94
104
  r.hget(redis_key, 'clean_when_empty')
95
105
  r.hget(redis_key, 'keep_open')
106
+ r.scard("#{redis_key}-holds")
96
107
  end
97
108
 
98
- return if keep_open == 'true' || clean_when_empty == 'false'
109
+ return if keep_open == 'true' || clean_when_empty == 'false' || (holds && holds > 0)
99
110
 
100
111
  if activec <= 0 && (pactivec.try(:to_i) || 0) <= 0 && pendingc <= 0
101
112
  cleanup_redis
@@ -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
@@ -1,3 +1,3 @@
1
1
  module CanvasSync
2
- VERSION = "0.22.0".freeze
2
+ VERSION = "0.22.2".freeze
3
3
  end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe CanvasSync::Jobs::SyncAdminsJob do
4
4
  describe '#perform' do
5
- let!(:account) { FactoryGirl.create(:account, canvas_id: 1) }
5
+ let!(:account) { FactoryBot.create(:account, canvas_id: 1) }
6
6
  let(:admin_params) { open_canvas_fixture('admins') }
7
7
 
8
8
  it 'retrieves all admins from the Canvas API and then invokes the next job' do
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  RSpec.describe CanvasSync::Jobs::SyncProvisioningReportJob do
4
4
  describe '#perform' do
5
5
  context 'a term scope is specified' do
6
- let!(:term) { FactoryGirl.create(:term) }
6
+ let!(:term) { FactoryBot.create(:term) }
7
7
 
8
8
  it 'enqueues a ReportStarter for a provisioning report for the specified models for each term' do
9
9
  expect_any_instance_of(CanvasSync::Jobs::ReportStarter).to receive(:start_report)
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe CanvasSync::Jobs::SyncRolesJob do
4
4
  describe '#perform' do
5
- let!(:account) { FactoryGirl.create(:account, canvas_id: 1) }
5
+ let!(:account) { FactoryBot.create(:account, canvas_id: 1) }
6
6
  let(:role_params) { open_canvas_fixture('roles') }
7
7
 
8
8
  it 'retrieves all roles from the Canvas API and then invokes the next job' do
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  RSpec.describe CanvasSync::Jobs::SyncSimpleTableJob do
4
4
  describe '#perform' do
5
5
  context 'Simple report' do
6
- let!(:term) { FactoryGirl.create(:term) }
6
+ let!(:term) { FactoryBot.create(:term) }
7
7
 
8
8
  it 'enqueues a ReportStarter for a provisioning report for the specified model for a term' do
9
9
  expect(CanvasSync::Jobs::ReportStarter).to receive(:perform_later)
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe Account, type: :model do
4
- let(:subject) { FactoryGirl.create(:account) }
4
+ let(:subject) { FactoryBot.create(:account) }
5
5
 
6
6
  describe 'validations' do
7
7
  it { should validate_presence_of(:canvas_id) }
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe Admin, type: :model do
4
- let(:subject) { FactoryGirl.create(:admin) }
4
+ let(:subject) { FactoryBot.create(:admin) }
5
5
 
6
6
  describe 'validations' do
7
7
  it { should validate_presence_of(:canvas_id) }
@@ -26,7 +26,7 @@ RSpec.describe Admin, type: :model do
26
26
  end
27
27
 
28
28
  context 'the admin already exists' do
29
- let!(:existing_admin) { FactoryGirl.create(:admin, canvas_id: admin_params['id']) }
29
+ let!(:existing_admin) { FactoryBot.create(:admin, canvas_id: admin_params['id']) }
30
30
 
31
31
  it 'updates it' do
32
32
  expect {
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe AssignmentGroup, type: :model do
4
- let(:subject) { FactoryGirl.create(:assignment_group) }
4
+ let(:subject) { FactoryBot.create(:assignment_group) }
5
5
 
6
6
  describe 'validations' do
7
7
  it { should validate_presence_of(:canvas_id) }
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
3
  RSpec.describe Assignment, type: :model do
4
- let(:subject) { FactoryGirl.create(:assignment) }
4
+ let(:subject) { FactoryBot.create(:assignment) }
5
5
 
6
6
  describe "validations" do
7
7
  it { should validate_presence_of(:canvas_id) }
@@ -31,8 +31,8 @@ RSpec.describe Assignment, type: :model do
31
31
  it { should have_many(:context_modules).through(:context_module_items) }
32
32
 
33
33
  describe "context" do
34
- let!(:other_course) { FactoryGirl.create(:course) }
35
- let!(:matching_course) { FactoryGirl.create(:course) }
34
+ let!(:other_course) { FactoryBot.create(:course) }
35
+ let!(:matching_course) { FactoryBot.create(:course) }
36
36
 
37
37
  before do
38
38
  subject.update(canvas_context_type: "Course", canvas_context_id: matching_course.canvas_id)
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
3
  RSpec.describe ContextModuleItem, type: :model do
4
- let(:subject) { FactoryGirl.create(:context_module_item) }
4
+ let(:subject) { FactoryBot.create(:context_module_item) }
5
5
 
6
6
  describe "associations" do
7
7
  it { should belong_to(:context_module) }
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
3
  RSpec.describe ContextModule, type: :model do
4
- let(:subject) { FactoryGirl.create(:context_module) }
4
+ let(:subject) { FactoryBot.create(:context_module) }
5
5
 
6
6
  describe "associations" do
7
7
  it do
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe Course, type: :model do
4
- let(:subject) { FactoryGirl.create(:course) }
4
+ let(:subject) { FactoryBot.create(:course) }
5
5
 
6
6
  describe 'validations' do
7
7
  it { should validate_presence_of(:canvas_id) }
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe Enrollment, type: :model do
4
- let(:subject) { FactoryGirl.create(:enrollment) }
4
+ let(:subject) { FactoryBot.create(:enrollment) }
5
5
 
6
6
  describe 'validations' do
7
7
  it { should validate_presence_of(:canvas_id) }
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe GroupMembership, type: :model do
4
4
  let(:subject) {
5
- FactoryGirl.create(:group_membership, group: FactoryGirl.create(:group), user: FactoryGirl.create(:user))
5
+ FactoryBot.create(:group_membership, group: FactoryBot.create(:group), user: FactoryBot.create(:user))
6
6
  }
7
7
 
8
8
  describe 'validations' do
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe Group, type: :model do
4
- let(:subject) { FactoryGirl.create(:group) }
4
+ let(:subject) { FactoryBot.create(:group) }
5
5
 
6
6
  describe 'validations' do
7
7
  it { should validate_presence_of(:canvas_id) }
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe Role, type: :model do
4
- let(:subject) { FactoryGirl.create(:role) }
4
+ let(:subject) { FactoryBot.create(:role) }
5
5
 
6
6
  describe 'validations' do
7
7
  it { should validate_presence_of(:canvas_id) }
@@ -27,7 +27,7 @@ RSpec.describe Role, type: :model do
27
27
  end
28
28
 
29
29
  context 'the role already exists' do
30
- let!(:existing_role) { FactoryGirl.create(:role, canvas_id: role_params['id']) }
30
+ let!(:existing_role) { FactoryBot.create(:role, canvas_id: role_params['id']) }
31
31
 
32
32
  it 'updates it' do
33
33
  expect {
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe Section, type: :model do
4
- let(:subject) { FactoryGirl.create(:section) }
4
+ let(:subject) { FactoryBot.create(:section) }
5
5
 
6
6
  describe 'validations' do
7
7
  it { should validate_presence_of(:canvas_id) }
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
3
  RSpec.describe Submission, type: :model do
4
- let(:subject) { FactoryGirl.create(:submission) }
4
+ let(:subject) { FactoryBot.create(:submission) }
5
5
 
6
6
  describe "validations" do
7
7
  it { should validate_presence_of(:canvas_id) }
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe Term, type: :model do
4
- let(:subject) { FactoryGirl.create(:term) }
4
+ let(:subject) { FactoryBot.create(:term) }
5
5
 
6
6
  describe 'validations' do
7
7
  it { should validate_presence_of(:canvas_id) }
@@ -18,10 +18,10 @@ RSpec.describe Term, type: :model do
18
18
 
19
19
  describe 'scopes' do
20
20
  describe '.active' do
21
- let!(:active_term) { FactoryGirl.create(:term, workflow_state: 'active', start_at: 2.days.ago, end_at: 3.days.from_now) }
22
- let!(:inactive_term) { FactoryGirl.create(:term, workflow_state: 'inactive') }
23
- let!(:completed_term) { FactoryGirl.create(:term, start_at: 2.months.ago, end_at: 1.month.ago) }
24
- let!(:unstarted_term) { FactoryGirl.create(:term, start_at: 6.months.from_now, end_at: 1.year.from_now) }
21
+ let!(:active_term) { FactoryBot.create(:term, workflow_state: 'active', start_at: 2.days.ago, end_at: 3.days.from_now) }
22
+ let!(:inactive_term) { FactoryBot.create(:term, workflow_state: 'inactive') }
23
+ let!(:completed_term) { FactoryBot.create(:term, start_at: 2.months.ago, end_at: 1.month.ago) }
24
+ let!(:unstarted_term) { FactoryBot.create(:term, start_at: 6.months.from_now, end_at: 1.year.from_now) }
25
25
 
26
26
  it 'returns terms with an active workflow_state that have a start_at 15 days in the future or earlier and an end_at 15 days in the past or later' do
27
27
  expect(Term.active).to match_array([active_term])
@@ -50,7 +50,7 @@ RSpec.describe Term, type: :model do
50
50
  end
51
51
 
52
52
  context 'the term already exists' do
53
- let!(:existing_term) { FactoryGirl.create(:term, canvas_id: term_params['id']) }
53
+ let!(:existing_term) { FactoryBot.create(:term, canvas_id: term_params['id']) }
54
54
 
55
55
  it 'updates it' do
56
56
  expect {
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe User, type: :model do
4
- let(:subject) { FactoryGirl.create(:user) }
4
+ let(:subject) { FactoryBot.create(:user) }
5
5
 
6
6
  describe 'validations' do
7
7
  it { should validate_presence_of(:canvas_id) }
@@ -16,7 +16,7 @@ RSpec.describe LiveEvents::ModuleEvent do
16
16
 
17
17
  describe "#perform" do
18
18
  context "the module already exists" do
19
- let!(:context_module) { FactoryGirl.create(:context_module, canvas_id: payload["body"][:module_id]) }
19
+ let!(:context_module) { FactoryBot.create(:context_module, canvas_id: payload["body"][:module_id]) }
20
20
 
21
21
  xit "updates it" do
22
22
  expect {
@@ -16,7 +16,7 @@ RSpec.describe LiveEvents::ModuleItemEvent do
16
16
 
17
17
  describe "#perform" do
18
18
  context "the module item already exists" do
19
- let!(:cmi) { FactoryGirl.create(:context_module_item, canvas_id: payload["body"][:module_item_id]) }
19
+ let!(:cmi) { FactoryBot.create(:context_module_item, canvas_id: payload["body"][:module_item_id]) }
20
20
 
21
21
  xit "updates it" do
22
22
  expect {
@@ -1,10 +1,10 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :account do
3
3
  canvas_id { SecureRandom.random_number(100_000_000) }
4
4
  sis_id { SecureRandom.hex }
5
- canvas_parent_account_id 1
5
+ canvas_parent_account_id { 1 }
6
6
  sis_parent_account_id { SecureRandom.hex }
7
- name "Account name"
8
- workflow_state "active"
7
+ name { "Account name" }
8
+ workflow_state { "active" }
9
9
  end
10
10
  end
@@ -1,9 +1,9 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :admin do
3
3
  canvas_id { SecureRandom.random_number(100_000_000) }
4
- role_name 'Cool Role'
4
+ role_name { 'Cool Role' }
5
5
  canvas_role_id { SecureRandom.random_number(100_000_000) }
6
- canvas_user_id 1
7
- workflow_state 'active'
6
+ canvas_user_id { 1 }
7
+ workflow_state { 'active' }
8
8
  end
9
9
  end
@@ -1,4 +1,4 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :assignment do
3
3
  sequence(:canvas_id) { |n| n }
4
4
  sequence(:title) { |n| "Assignment #{n}" }
@@ -1,8 +1,8 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :assignment_group do
3
3
  sequence(:canvas_id) { |n| n }
4
- name 'Dummy Assignment Group'
5
- workflow_state 'available'
4
+ name { 'Dummy Assignment Group' }
5
+ workflow_state { 'available' }
6
6
  canvas_created_at {1.week.ago}
7
7
  canvas_updated_at {1.day.ago}
8
8
  end
@@ -1,8 +1,8 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :context_module do
3
3
  sequence(:canvas_id) { |n| n }
4
- name "Context Module"
5
- workflow_state "available"
6
- context { FactoryGirl.create(:course) }
4
+ name { "Context Module" }
5
+ workflow_state { "available" }
6
+ context { FactoryBot.create(:course) }
7
7
  end
8
8
  end
@@ -1,7 +1,7 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :context_module_item do
3
3
  sequence(:canvas_id) { |n| n }
4
4
  assignment
5
- workflow_state "active"
5
+ workflow_state { "active" }
6
6
  end
7
7
  end
@@ -1,9 +1,9 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :course do
3
3
  canvas_id { SecureRandom.random_number(100_000_000) }
4
4
  sis_id { SecureRandom.hex }
5
- course_code 'Cool Course'
6
- name 'Really Really Cool Course'
5
+ course_code { 'Cool Course' }
6
+ name { 'Really Really Cool Course' }
7
7
  start_at { 3.days.ago }
8
8
  end_at { 3.weeks.from_now }
9
9
  end
@@ -1,4 +1,4 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :enrollment do
3
3
  canvas_id { SecureRandom.random_number(100_000_000) }
4
4
  end
@@ -1,8 +1,8 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :group do
3
3
  canvas_id { SecureRandom.random_number(100_000_000) }
4
4
  sis_id { SecureRandom.hex }
5
- name 'Some User Group'
6
- workflow_state 'available'
5
+ name { 'Some User Group' }
6
+ workflow_state { 'available' }
7
7
  end
8
8
  end
@@ -1,6 +1,6 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :group_membership do
3
3
  canvas_id { SecureRandom.random_number(100_000_000) }
4
- workflow_state 'accepted'
4
+ workflow_state { 'accepted' }
5
5
  end
6
6
  end
@@ -1,8 +1,8 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :role do
3
- label 'Cool Role'
4
- base_role_type 'AccountMembership'
3
+ label { 'Cool Role' }
4
+ base_role_type { 'AccountMembership' }
5
5
  canvas_id { SecureRandom.random_number(100_000_000) }
6
- workflow_state 'active'
6
+ workflow_state { 'active' }
7
7
  end
8
8
  end
@@ -1,4 +1,4 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :section do
3
3
  canvas_id { SecureRandom.random_number(100_000_000) }
4
4
  end
@@ -1,4 +1,4 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :submission do
3
3
  sequence(:canvas_id) { |n| n }
4
4
  submitted_at { 1.week.ago }
@@ -1,10 +1,10 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :term do
3
- name 'Cool Term'
4
- start_at 3.days.ago
5
- end_at 3.days.from_now
3
+ name { 'Cool Term' }
4
+ start_at { 3.days.ago }
5
+ end_at { 3.days.from_now }
6
6
  canvas_id { SecureRandom.random_number(100_000_000) }
7
- workflow_state 'active'
7
+ workflow_state { 'active' }
8
8
  sis_id { SecureRandom.hex }
9
9
  end
10
10
  end
@@ -1,8 +1,8 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :user do
3
3
  canvas_id { SecureRandom.random_number(100_000_000) }
4
- email "cooldude@coolsite.com"
5
- first_name "Cool"
6
- last_name "Dude"
4
+ email { "cooldude@coolsite.com" }
5
+ first_name { "Cool" }
6
+ last_name { "Dude" }
7
7
  end
8
8
  end
@@ -223,7 +223,7 @@ RSpec.describe CanvasSync::JobBatches::Batch do
223
223
 
224
224
  context 'complete' do
225
225
  before { batch.on(:complete, Object) }
226
- # before { batch.increment_job_queue(bid) }
226
+ # before { batch.append_jobs(bid) }
227
227
  # before { batch.jobs do BatchTestWorker.perform_async end }
228
228
  # before { CanvasSync::JobBatches::Batch.process_failed_job(bid, 'failed-job-id') }
229
229
 
@@ -341,7 +341,7 @@ RSpec.describe CanvasSync::JobBatches::Batch do
341
341
  end
342
342
  end
343
343
 
344
- describe '#increment_job_queue' do
344
+ describe '#append_jobs' do
345
345
  let(:batch) { CanvasSync::JobBatches::Batch.new }
346
346
 
347
347
  it 'increments pending' do
@@ -57,7 +57,7 @@ RSpec.describe CanvasSync::JobBatches::Compat::ActiveJob do
57
57
  context "When Enqueueing" do
58
58
  context 'when without batch' do
59
59
  it 'just yields' do
60
- expect(CanvasSync::JobBatches::Batch).not_to receive(:increment_job_queue)
60
+ expect(CanvasSync::JobBatches::Batch).not_to receive(:append_jobs)
61
61
  BatchTestJobBase.perform_later
62
62
  expect(BatchTestJobBase).to have_been_enqueued
63
63
  end
@@ -48,7 +48,7 @@ RSpec.describe CanvasSync::JobBatches::Compat::Sidekiq do
48
48
  context 'when without batch' do
49
49
  it 'just yields' do
50
50
  yielded = false
51
- expect(CanvasSync::JobBatches::Batch).not_to receive(:increment_job_queue)
51
+ expect(CanvasSync::JobBatches::Batch).not_to receive(:append_jobs)
52
52
  subject.call(nil, {}, nil) { yielded = true }
53
53
  expect(yielded).to be_truthy
54
54
  end
@@ -67,7 +67,7 @@ RSpec.describe CanvasSync::JobBatches::Compat::Sidekiq do
67
67
  end
68
68
 
69
69
  it 'increments job queue' do
70
- # expect(CanvasSync::JobBatches::Batch).to receive(:increment_job_queue).with(bid)
70
+ # expect(CanvasSync::JobBatches::Batch).to receive(:append_jobs).with(bid)
71
71
  # subject.call(nil, { 'jid' => jid }, nil) {}
72
72
  end
73
73
 
@@ -34,7 +34,7 @@ RSpec.describe CanvasSync::JobBatches::Batch::Status do
34
34
  end
35
35
 
36
36
  context 'when more than 0' do
37
- before { batch.increment_job_queue(bid) }
37
+ before { batch.append_jobs(bid) }
38
38
  before { CanvasSync::JobBatches::Batch.process_failed_job(bid, 'FAILEDID') }
39
39
 
40
40
  it 'returns failed jobs' do
data/spec/spec_helper.rb CHANGED
@@ -7,7 +7,7 @@ require File.expand_path("../dummy/config/environment.rb", __FILE__)
7
7
  require "bundler/setup"
8
8
  require 'rspec/rails'
9
9
  require 'spec_helper'
10
- require 'factory_girl_rails'
10
+ require 'factory_bot_rails'
11
11
  require 'timecop'
12
12
  require 'webmock/rspec'
13
13
  require 'support/fake_canvas'
@@ -16,6 +16,9 @@ require 'pry'
16
16
  require 'pry-nav'
17
17
  require 'with_model'
18
18
 
19
+ require 'redis'
20
+ Redis.silence_deprecations = true
21
+
19
22
  require 'sidekiq/testing'
20
23
  Sidekiq::Testing.fake!
21
24
  Sidekiq::Testing.server_middleware do |chain|
@@ -29,7 +32,7 @@ ActiveRecord::Migration.maintain_test_schema!
29
32
  RSpec.configure do |config|
30
33
  config.extend WithModel
31
34
 
32
- config.include FactoryGirl::Syntax::Methods
35
+ config.include FactoryBot::Syntax::Methods
33
36
  config.use_transactional_fixtures = true
34
37
  config.infer_spec_type_from_file_location!
35
38
  config.filter_rails_from_backtrace!
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.0
4
+ version: 0.22.2
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-07-29 00:00:00.000000000 Z
11
+ date: 2024-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -95,7 +95,7 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: factory_girl_rails
98
+ name: factory_bot_rails
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="