canvas_sync 0.23.4 → 0.24.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 (206) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +2 -4
  3. data/lib/canvas_sync/processors/provisioning_report_processor.rb +1 -0
  4. data/lib/canvas_sync/version.rb +1 -1
  5. data/lib/canvas_sync.rb +6 -4
  6. data/spec/canvas_sync/canvas_sync_spec.rb +11 -11
  7. data/spec/canvas_sync/live_events/process_event_job_spec.rb +1 -0
  8. data/spec/{dummy → internal}/app/models/application_record.rb +1 -0
  9. data/spec/{dummy → internal}/app/models/content_migration.rb +0 -0
  10. data/spec/{dummy → internal}/app/models/course.rb +0 -1
  11. data/spec/{dummy → internal}/app/models/course_nickname.rb +0 -0
  12. data/spec/{dummy → internal}/app/models/learning_outcome.rb +0 -0
  13. data/spec/{dummy → internal}/app/services/live_events/assignment_event.rb +0 -0
  14. data/spec/{dummy → internal}/app/services/live_events/course_event.rb +0 -0
  15. data/spec/{dummy → internal}/app/services/live_events/course_section_event.rb +0 -0
  16. data/spec/{dummy → internal}/app/services/live_events/enrollment_event.rb +0 -0
  17. data/spec/{dummy → internal}/app/services/live_events/grade_event.rb +0 -0
  18. data/spec/{dummy → internal}/app/services/live_events/module_event.rb +0 -0
  19. data/spec/{dummy → internal}/app/services/live_events/module_item_event.rb +0 -0
  20. data/spec/{dummy → internal}/app/services/live_events/submission_event.rb +0 -0
  21. data/spec/{dummy → internal}/app/services/live_events/syllabus_event.rb +0 -0
  22. data/spec/{dummy → internal}/app/services/live_events/user_event.rb +0 -0
  23. data/spec/internal/bin/rails +9 -0
  24. data/spec/internal/config/database.yml +5 -0
  25. data/spec/internal/config/routes.rb +5 -0
  26. data/spec/internal/config/storage.yml +3 -0
  27. data/spec/{dummy/db/migrate/20220926221926_create_users.rb → internal/db/migrate/20250912205136_create_users.rb} +0 -0
  28. data/spec/{dummy/db/migrate/20201016181346_create_pseudonyms.rb → internal/db/migrate/20250912205137_create_pseudonyms.rb} +0 -0
  29. data/spec/{dummy/db/migrate/20200415171620_create_groups.rb → internal/db/migrate/20250912205139_create_groups.rb} +0 -0
  30. data/spec/{dummy/db/migrate/20200416214248_create_group_memberships.rb → internal/db/migrate/20250912205140_create_group_memberships.rb} +0 -0
  31. data/spec/{dummy/db/migrate/20190702203622_create_accounts.rb → internal/db/migrate/20250912205141_create_accounts.rb} +0 -0
  32. data/spec/{dummy/db/migrate/20190702203623_create_terms.rb → internal/db/migrate/20250912205142_create_terms.rb} +0 -0
  33. data/spec/{dummy/db/migrate/20190702203625_create_sections.rb → internal/db/migrate/20250912205144_create_sections.rb} +0 -0
  34. data/spec/{dummy/db/migrate/20190702203626_create_assignments.rb → internal/db/migrate/20250912205145_create_assignments.rb} +0 -0
  35. data/spec/{dummy/db/migrate/20190702203627_create_submissions.rb → internal/db/migrate/20250912205146_create_submissions.rb} +0 -0
  36. data/spec/{dummy/db/migrate/20190927204545_create_roles.rb → internal/db/migrate/20250912205147_create_roles.rb} +2 -2
  37. data/spec/{dummy/db/migrate/20190927204546_create_admins.rb → internal/db/migrate/20250912205148_create_admins.rb} +0 -0
  38. data/spec/{dummy/db/migrate/20190702203630_create_assignment_groups.rb → internal/db/migrate/20250912205149_create_assignment_groups.rb} +0 -0
  39. data/spec/{dummy/db/migrate/20190702203631_create_context_modules.rb → internal/db/migrate/20250912205150_create_context_modules.rb} +0 -0
  40. data/spec/{dummy/db/migrate/20190702203632_create_context_module_items.rb → internal/db/migrate/20250912205151_create_context_module_items.rb} +0 -0
  41. data/spec/{dummy/db/migrate/20210907233329_create_user_observers.rb → internal/db/migrate/20250912205152_create_user_observers.rb} +0 -0
  42. data/spec/{dummy/db/migrate/20210907233330_create_grading_periods.rb → internal/db/migrate/20250912205153_create_grading_periods.rb} +0 -0
  43. data/spec/{dummy/db/migrate/20211001184920_create_grading_period_groups.rb → internal/db/migrate/20250912205154_create_grading_period_groups.rb} +0 -0
  44. data/spec/{dummy/db/migrate/20220308072643_create_content_migrations.rb → internal/db/migrate/20250912205155_create_content_migrations.rb} +0 -0
  45. data/spec/{dummy/db/migrate/20220712210559_create_learning_outcomes.rb → internal/db/migrate/20250912205156_create_learning_outcomes.rb} +0 -0
  46. data/spec/{dummy/db/migrate/20240523101010_create_learning_outcome_results.rb → internal/db/migrate/20250912205157_create_learning_outcome_results.rb} +0 -0
  47. data/spec/{dummy/db/migrate/20240510094100_create_rubric_associations.rb → internal/db/migrate/20250912205160_create_rubric_associations.rb} +0 -0
  48. data/spec/{dummy/db/migrate/20240510101100_create_rubric_assessments.rb → internal/db/migrate/20250912205161_create_rubric_assessments.rb} +0 -0
  49. data/spec/{dummy/db/migrate/20240828161300_create_course_progresses.rb → internal/db/migrate/20250912205162_create_course_progresses.rb} +0 -0
  50. data/spec/internal/db/schema.rb +6 -0
  51. data/spec/spec_helper.rb +8 -4
  52. metadata +182 -372
  53. data/lib/canvas_sync/job_batches/batch.rb +0 -595
  54. data/lib/canvas_sync/job_batches/callback.rb +0 -135
  55. data/lib/canvas_sync/job_batches/chain_builder.rb +0 -247
  56. data/lib/canvas_sync/job_batches/compat/active_job.rb +0 -108
  57. data/lib/canvas_sync/job_batches/compat/sidekiq/web/batches_assets/css/styles.less +0 -182
  58. data/lib/canvas_sync/job_batches/compat/sidekiq/web/batches_assets/js/batch_tree.js +0 -108
  59. data/lib/canvas_sync/job_batches/compat/sidekiq/web/batches_assets/js/util.js +0 -2
  60. data/lib/canvas_sync/job_batches/compat/sidekiq/web/helpers.rb +0 -41
  61. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/_batch_tree.erb +0 -6
  62. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/_batches_table.erb +0 -44
  63. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/_common.erb +0 -13
  64. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/_jobs_table.erb +0 -21
  65. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/_pagination.erb +0 -26
  66. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/batch.erb +0 -81
  67. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/batches.erb +0 -23
  68. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/pool.erb +0 -137
  69. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/pools.erb +0 -47
  70. data/lib/canvas_sync/job_batches/compat/sidekiq/web.rb +0 -218
  71. data/lib/canvas_sync/job_batches/compat/sidekiq.rb +0 -149
  72. data/lib/canvas_sync/job_batches/compat.rb +0 -20
  73. data/lib/canvas_sync/job_batches/context_hash.rb +0 -157
  74. data/lib/canvas_sync/job_batches/hier_batch_ids.lua +0 -25
  75. data/lib/canvas_sync/job_batches/jobs/base_job.rb +0 -5
  76. data/lib/canvas_sync/job_batches/jobs/concurrent_batch_job.rb +0 -20
  77. data/lib/canvas_sync/job_batches/jobs/managed_batch_job.rb +0 -175
  78. data/lib/canvas_sync/job_batches/jobs/serial_batch_job.rb +0 -20
  79. data/lib/canvas_sync/job_batches/pool.rb +0 -254
  80. data/lib/canvas_sync/job_batches/pool_refill.lua +0 -47
  81. data/lib/canvas_sync/job_batches/redis_model.rb +0 -67
  82. data/lib/canvas_sync/job_batches/redis_script.rb +0 -161
  83. data/lib/canvas_sync/job_batches/schedule_callback.lua +0 -14
  84. data/lib/canvas_sync/job_batches/status.rb +0 -89
  85. data/lib/canvas_sync/job_uniqueness/compat/active_job.rb +0 -75
  86. data/lib/canvas_sync/job_uniqueness/compat/sidekiq.rb +0 -135
  87. data/lib/canvas_sync/job_uniqueness/compat.rb +0 -20
  88. data/lib/canvas_sync/job_uniqueness/configuration.rb +0 -25
  89. data/lib/canvas_sync/job_uniqueness/job_uniqueness.rb +0 -47
  90. data/lib/canvas_sync/job_uniqueness/lock_context.rb +0 -199
  91. data/lib/canvas_sync/job_uniqueness/locksmith.rb +0 -92
  92. data/lib/canvas_sync/job_uniqueness/on_conflict/base.rb +0 -32
  93. data/lib/canvas_sync/job_uniqueness/on_conflict/log.rb +0 -13
  94. data/lib/canvas_sync/job_uniqueness/on_conflict/null_strategy.rb +0 -9
  95. data/lib/canvas_sync/job_uniqueness/on_conflict/raise.rb +0 -11
  96. data/lib/canvas_sync/job_uniqueness/on_conflict/reject.rb +0 -21
  97. data/lib/canvas_sync/job_uniqueness/on_conflict/reschedule.rb +0 -20
  98. data/lib/canvas_sync/job_uniqueness/on_conflict.rb +0 -62
  99. data/lib/canvas_sync/job_uniqueness/strategy/base.rb +0 -107
  100. data/lib/canvas_sync/job_uniqueness/strategy/until_and_while_executing.rb +0 -35
  101. data/lib/canvas_sync/job_uniqueness/strategy/until_executed.rb +0 -20
  102. data/lib/canvas_sync/job_uniqueness/strategy/until_executing.rb +0 -20
  103. data/lib/canvas_sync/job_uniqueness/strategy/until_expired.rb +0 -16
  104. data/lib/canvas_sync/job_uniqueness/strategy/while_executing.rb +0 -26
  105. data/lib/canvas_sync/job_uniqueness/strategy.rb +0 -27
  106. data/lib/canvas_sync/job_uniqueness/unique_job_common.rb +0 -79
  107. data/spec/dummy/README.rdoc +0 -1
  108. data/spec/dummy/Rakefile +0 -6
  109. data/spec/dummy/app/services/live_events/assignment_created_event.rb +0 -12
  110. data/spec/dummy/app/services/live_events/assignment_updated_event.rb +0 -12
  111. data/spec/dummy/app/services/live_events/base_event.rb +0 -52
  112. data/spec/dummy/app/services/live_events/course_created_event.rb +0 -12
  113. data/spec/dummy/app/services/live_events/course_section_created_event.rb +0 -12
  114. data/spec/dummy/app/services/live_events/course_section_updated_event.rb +0 -12
  115. data/spec/dummy/app/services/live_events/course_updated_event.rb +0 -12
  116. data/spec/dummy/app/services/live_events/enrollment_created_event.rb +0 -12
  117. data/spec/dummy/app/services/live_events/enrollment_updated_event.rb +0 -12
  118. data/spec/dummy/app/services/live_events/grade_changed_event.rb +0 -12
  119. data/spec/dummy/app/services/live_events/module_created_event.rb +0 -12
  120. data/spec/dummy/app/services/live_events/module_item_created_event.rb +0 -12
  121. data/spec/dummy/app/services/live_events/module_item_updated_event.rb +0 -12
  122. data/spec/dummy/app/services/live_events/module_updated_event.rb +0 -12
  123. data/spec/dummy/app/services/live_events/submission_created_event.rb +0 -12
  124. data/spec/dummy/app/services/live_events/submission_updated_event.rb +0 -12
  125. data/spec/dummy/app/services/live_events/syllabus_updated_event.rb +0 -12
  126. data/spec/dummy/app/services/live_events/user_created_event.rb +0 -12
  127. data/spec/dummy/app/services/live_events/user_updated_event.rb +0 -12
  128. data/spec/dummy/bin/rails +0 -4
  129. data/spec/dummy/config/application.rb +0 -39
  130. data/spec/dummy/config/boot.rb +0 -5
  131. data/spec/dummy/config/database.yml +0 -25
  132. data/spec/dummy/config/environment.rb +0 -5
  133. data/spec/dummy/config/environments/development.rb +0 -41
  134. data/spec/dummy/config/environments/test.rb +0 -44
  135. data/spec/dummy/config/initializers/assets.rb +0 -11
  136. data/spec/dummy/config/initializers/session_store.rb +0 -3
  137. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
  138. data/spec/dummy/config/routes.rb +0 -3
  139. data/spec/dummy/config/secrets.yml +0 -22
  140. data/spec/dummy/config.ru +0 -4
  141. data/spec/dummy/db/schema.rb +0 -563
  142. data/spec/job_batching/batch_spec.rb +0 -531
  143. data/spec/job_batching/callback_spec.rb +0 -38
  144. data/spec/job_batching/compat/active_job_spec.rb +0 -107
  145. data/spec/job_batching/compat/sidekiq_spec.rb +0 -127
  146. data/spec/job_batching/context_hash_spec.rb +0 -54
  147. data/spec/job_batching/flow_spec.rb +0 -82
  148. data/spec/job_batching/integration/fail_then_succeed.rb +0 -42
  149. data/spec/job_batching/integration/integration.rb +0 -57
  150. data/spec/job_batching/integration/nested.rb +0 -88
  151. data/spec/job_batching/integration/simple.rb +0 -47
  152. data/spec/job_batching/integration/workflow.rb +0 -134
  153. data/spec/job_batching/integration_helper.rb +0 -50
  154. data/spec/job_batching/pool_spec.rb +0 -161
  155. data/spec/job_batching/status_spec.rb +0 -76
  156. data/spec/job_batching/support/base_job.rb +0 -14
  157. data/spec/job_batching/support/sample_callback.rb +0 -2
  158. data/spec/job_uniqueness/compat/active_job_spec.rb +0 -49
  159. data/spec/job_uniqueness/compat/sidekiq_spec.rb +0 -68
  160. data/spec/job_uniqueness/lock_context_spec.rb +0 -106
  161. data/spec/job_uniqueness/on_conflict/log_spec.rb +0 -11
  162. data/spec/job_uniqueness/on_conflict/raise_spec.rb +0 -10
  163. data/spec/job_uniqueness/on_conflict/reschedule_spec.rb +0 -63
  164. data/spec/job_uniqueness/on_conflict_spec.rb +0 -16
  165. data/spec/job_uniqueness/spec_helper.rb +0 -17
  166. data/spec/job_uniqueness/strategy/base_spec.rb +0 -100
  167. data/spec/job_uniqueness/strategy/until_and_while_executing_spec.rb +0 -48
  168. data/spec/job_uniqueness/strategy/until_executed_spec.rb +0 -23
  169. data/spec/job_uniqueness/strategy/until_executing_spec.rb +0 -23
  170. data/spec/job_uniqueness/strategy/until_expired_spec.rb +0 -23
  171. data/spec/job_uniqueness/strategy/while_executing_spec.rb +0 -33
  172. data/spec/job_uniqueness/support/lock_strategy.rb +0 -28
  173. data/spec/job_uniqueness/support/on_conflict.rb +0 -24
  174. data/spec/job_uniqueness/support/test_worker.rb +0 -19
  175. data/spec/job_uniqueness/unique_job_common_spec.rb +0 -45
  176. /data/spec/{dummy → internal}/app/models/account.rb +0 -0
  177. /data/spec/{dummy → internal}/app/models/admin.rb +0 -0
  178. /data/spec/{dummy → internal}/app/models/assignment.rb +0 -0
  179. /data/spec/{dummy → internal}/app/models/assignment_group.rb +0 -0
  180. /data/spec/{dummy → internal}/app/models/assignment_override.rb +0 -0
  181. /data/spec/{dummy → internal}/app/models/context_module.rb +0 -0
  182. /data/spec/{dummy → internal}/app/models/context_module_item.rb +0 -0
  183. /data/spec/{dummy → internal}/app/models/course_progress.rb +0 -0
  184. /data/spec/{dummy → internal}/app/models/enrollment.rb +0 -0
  185. /data/spec/{dummy → internal}/app/models/grading_period.rb +0 -0
  186. /data/spec/{dummy → internal}/app/models/grading_period_group.rb +0 -0
  187. /data/spec/{dummy → internal}/app/models/group.rb +0 -0
  188. /data/spec/{dummy → internal}/app/models/group_membership.rb +0 -0
  189. /data/spec/{dummy → internal}/app/models/learning_outcome_result.rb +0 -0
  190. /data/spec/{dummy → internal}/app/models/pseudonym.rb +0 -0
  191. /data/spec/{dummy → internal}/app/models/role.rb +0 -0
  192. /data/spec/{dummy → internal}/app/models/rubric.rb +0 -0
  193. /data/spec/{dummy → internal}/app/models/rubric_assessment.rb +0 -0
  194. /data/spec/{dummy → internal}/app/models/rubric_association.rb +0 -0
  195. /data/spec/{dummy → internal}/app/models/score.rb +0 -0
  196. /data/spec/{dummy → internal}/app/models/section.rb +0 -0
  197. /data/spec/{dummy → internal}/app/models/submission.rb +0 -0
  198. /data/spec/{dummy → internal}/app/models/term.rb +0 -0
  199. /data/spec/{dummy → internal}/app/models/user.rb +0 -0
  200. /data/spec/{dummy → internal}/app/models/user_observer.rb +0 -0
  201. /data/spec/{dummy/db/migrate/20190702203621_create_courses.rb → internal/db/migrate/20250912205138_create_courses.rb} +0 -0
  202. /data/spec/{dummy/db/migrate/20190702203624_create_enrollments.rb → internal/db/migrate/20250912205143_create_enrollments.rb} +0 -0
  203. /data/spec/{dummy/db/migrate/20250319194134_create_course_nicknames.rb → internal/db/migrate/20250912205158_create_course_nicknames.rb} +0 -0
  204. /data/spec/{dummy/db/migrate/20250319194135_create_rubrics.rb → internal/db/migrate/20250912205159_create_rubrics.rb} +0 -0
  205. /data/spec/{dummy/db/migrate/20241223080202_create_assignment_overrides.rb → internal/db/migrate/20250912205163_create_assignment_overrides.rb} +0 -0
  206. /data/spec/{dummy/db/migrate/20250626194330_create_scores.rb → internal/db/migrate/20250912205164_create_scores.rb} +0 -0
@@ -1,531 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class BatchTestWorker < BatchTestJobBase
4
- def perform
5
- end
6
- end
7
-
8
- RSpec.describe CanvasSync::JobBatches::Batch do
9
- describe '#initialize' do
10
- subject { described_class }
11
-
12
- it 'creates bid when called without it' do
13
- expect(subject.new.bid).not_to be_nil
14
- end
15
-
16
- it 'reuses bid when called with it' do
17
- batch = subject.new('dayPO5KxuRXXxw')
18
- expect(batch.bid).to eq('dayPO5KxuRXXxw')
19
- end
20
- end
21
-
22
- describe '#description' do
23
- let(:description) { 'custom description' }
24
- before do
25
- subject.description = description
26
- subject.jobs { }
27
- end
28
-
29
- it 'sets descriptions' do
30
- expect(subject.description).to eq(description)
31
- end
32
-
33
- it 'persists description' do
34
- expect(CanvasSync::JobBatches::Batch.redis { |r| r.hget("BID-#{subject.bid}", 'description') })
35
- .to eq(description)
36
- end
37
- end
38
-
39
- describe '#callback_queue' do
40
- let(:callback_queue) { 'custom_queue' }
41
- before do
42
- subject.callback_queue = callback_queue
43
- subject.jobs { }
44
- end
45
-
46
- it 'sets callback_queue' do
47
- expect(subject.callback_queue).to eq(callback_queue)
48
- end
49
-
50
- it 'persists callback_queue' do
51
- expect(CanvasSync::JobBatches::Batch.redis { |r| r.hget("BID-#{subject.bid}", 'callback_queue') })
52
- .to eq(callback_queue)
53
- end
54
- end
55
-
56
- describe '#jobs' do
57
- it 'throws error if no block given' do
58
- expect { subject.jobs }.to raise_error CanvasSync::JobBatches::Batch::NoBlockGivenError
59
- end
60
-
61
- it 'increments to_process (when started)'
62
-
63
- it 'decrements to_process (when finished)'
64
- # it 'calls process_successful_job to wait for block to finish' do
65
- # batch = CanvasSync::JobBatches::Batch.new
66
- # expect(CanvasSync::JobBatches::Batch).to receive(:process_successful_job).with(batch.bid)
67
- # batch.jobs {}
68
- # end
69
-
70
- it 'sets Thread.current bid' do
71
- batch = CanvasSync::JobBatches::Batch.new
72
- batch.jobs do
73
- expect(Thread.current[CanvasSync::JobBatches::CURRENT_BATCH_THREAD_KEY]).to eq(batch)
74
- end
75
- end
76
- end
77
-
78
- describe '#invalidate_all' do
79
- class InvalidatableJob < BatchTestJobBase
80
- def perform
81
- return unless valid_within_batch?
82
- was_performed
83
- end
84
-
85
- def was_performed; end
86
- end
87
-
88
- it 'marks batch in redis as invalidated' do
89
- batch = CanvasSync::JobBatches::Batch.new
90
- job = InvalidatableJob.new
91
- allow(job).to receive(:was_performed)
92
-
93
- batch.invalidate_all
94
- batch.jobs { job.perform }
95
-
96
- expect(job).not_to have_received(:was_performed)
97
- end
98
-
99
- context 'nested batches' do
100
- let(:batch_parent) { CanvasSync::JobBatches::Batch.new }
101
- let(:batch_child_1) { CanvasSync::JobBatches::Batch.new }
102
- let(:batch_child_2) { CanvasSync::JobBatches::Batch.new }
103
- let(:job_of_parent) { InvalidatableJob.new }
104
- let(:job_of_child_1) { InvalidatableJob.new }
105
- let(:job_of_child_2) { InvalidatableJob.new }
106
-
107
- before do
108
- allow(job_of_parent).to receive(:was_performed)
109
- allow(job_of_child_1).to receive(:was_performed)
110
- allow(job_of_child_2).to receive(:was_performed)
111
- end
112
-
113
- it 'invalidates all job if parent batch is marked as invalidated' do
114
- batch_parent.invalidate_all
115
- batch_parent.jobs do
116
- [
117
- job_of_parent.perform,
118
- batch_child_1.jobs do
119
- [
120
- job_of_child_1.perform,
121
- batch_child_2.jobs { job_of_child_2.perform }
122
- ]
123
- end
124
- ]
125
- end
126
-
127
- expect(job_of_parent).not_to have_received(:was_performed)
128
- expect(job_of_child_1).not_to have_received(:was_performed)
129
- expect(job_of_child_2).not_to have_received(:was_performed)
130
- end
131
-
132
- it 'invalidates only requested batch' do
133
- batch_child_2.invalidate_all
134
- batch_parent.jobs do
135
- [
136
- job_of_parent.perform,
137
- batch_child_1.jobs do
138
- [
139
- job_of_child_1.perform,
140
- batch_child_2.jobs { job_of_child_2.perform }
141
- ]
142
- end
143
- ]
144
- end
145
-
146
- expect(job_of_parent).to have_received(:was_performed)
147
- expect(job_of_child_1).to have_received(:was_performed)
148
- expect(job_of_child_2).not_to have_received(:was_performed)
149
- end
150
- end
151
- end
152
-
153
- describe '#process_failed_job' do
154
- let(:batch) { CanvasSync::JobBatches::Batch.new }
155
- let(:bid) { batch.bid }
156
- let(:jid) { 'ABCD' }
157
- before { CanvasSync::JobBatches::Batch.redis { |r| r.hset("BID-#{bid}", 'pending', 1) } }
158
-
159
- context 'complete' do
160
- let(:failed_jid) { 'xxx' }
161
-
162
- it 'tries to call complete callback' do
163
- expect(CanvasSync::JobBatches::Batch).to receive(:enqueue_callbacks).with(:complete, bid)
164
- CanvasSync::JobBatches::Batch.process_failed_job(bid, failed_jid)
165
- end
166
-
167
- it 'add job to failed list' do
168
- CanvasSync::JobBatches::Batch.process_failed_job(bid, 'failed-job-id')
169
- CanvasSync::JobBatches::Batch.process_failed_job(bid, failed_jid)
170
- failed = CanvasSync::JobBatches::Batch.redis { |r| r.smembers("BID-#{bid}-failed") }
171
- expect(failed).to contain_exactly('xxx', 'failed-job-id')
172
- end
173
- end
174
- end
175
-
176
- describe '#process_dead_job' do
177
- let(:batch) { CanvasSync::JobBatches::Batch.new }
178
- let(:bid) { batch.bid }
179
- let(:jid) { 'ABCD' }
180
- before { CanvasSync::JobBatches::Batch.redis { |r| r.hset("BID-#{bid}", 'pending', 1) } }
181
-
182
- context 'dead' do
183
- let(:failed_jid) { 'xxx' }
184
-
185
- it 'tries to call death callback' do
186
- allow(CanvasSync::JobBatches::Batch).to receive(:enqueue_callbacks).with(:stagnated, bid)
187
- expect(CanvasSync::JobBatches::Batch).to receive(:enqueue_callbacks).with(:death, bid)
188
- CanvasSync::JobBatches::Batch.process_dead_job(bid, failed_jid)
189
- end
190
-
191
- it 'add job to failed list' do
192
- CanvasSync::JobBatches::Batch.process_dead_job(bid, 'failed-job-id')
193
- CanvasSync::JobBatches::Batch.process_dead_job(bid, failed_jid)
194
- failed = CanvasSync::JobBatches::Batch.redis { |r| r.smembers("BID-#{bid}-dead") }
195
- expect(failed).to contain_exactly('xxx', 'failed-job-id')
196
- end
197
-
198
- it 'automattically triggers the :stagnated callback' do
199
- expect(CanvasSync::JobBatches::Batch).to receive(:enqueue_callbacks).with(:stagnated, bid)
200
- allow(CanvasSync::JobBatches::Batch).to receive(:enqueue_callbacks).with(:death, bid)
201
- CanvasSync::JobBatches::Batch.process_dead_job(bid, failed_jid)
202
- end
203
-
204
- it 'does not trigger :stagnated if pending jobs are still present' do
205
- CanvasSync::JobBatches::Batch.redis { |r| r.hset("BID-#{bid}", 'pending', 2) }
206
- expect(CanvasSync::JobBatches::Batch).to_not receive(:enqueue_callbacks).with(:stagnated, bid)
207
- CanvasSync::JobBatches::Batch.process_dead_job(bid, failed_jid)
208
- end
209
-
210
- it 'does not trigger :stagnated if pending batches are still present' do
211
- CanvasSync::JobBatches::Batch.redis { |r| r.hset("BID-#{bid}", 'pending', 2) }
212
- expect(CanvasSync::JobBatches::Batch).to_not receive(:enqueue_callbacks).with(:stagnated, bid)
213
- CanvasSync::JobBatches::Batch.process_dead_job(bid, failed_jid)
214
- end
215
- end
216
- end
217
-
218
- describe '#process_successful_job' do
219
- let(:batch) { CanvasSync::JobBatches::Batch.new }
220
- let(:bid) { batch.bid }
221
- let(:jid) { 'ABCD' }
222
- before { CanvasSync::JobBatches::Batch.redis { |r| r.hset("BID-#{bid}", 'pending', 1) } }
223
-
224
- context 'complete' do
225
- before { batch.on(:complete, Object) }
226
- # before { batch.append_jobs(bid) }
227
- # before { batch.jobs do BatchTestWorker.perform_async end }
228
- # before { CanvasSync::JobBatches::Batch.process_failed_job(bid, 'failed-job-id') }
229
-
230
- it 'tries to call complete callback' do
231
- expect(CanvasSync::JobBatches::Batch).to receive(:enqueue_callbacks).with(:complete, bid)
232
- CanvasSync::JobBatches::Batch.process_failed_job(bid, 'failed-job-id')
233
- end
234
- end
235
-
236
- context 'success' do
237
- before { batch.on(:complete, Object) }
238
-
239
- it 'tries to call complete callback' do
240
- expect(CanvasSync::JobBatches::Batch).to receive(:enqueue_callbacks).with(:complete, bid).ordered
241
- expect(CanvasSync::JobBatches::Batch).to receive(:enqueue_callbacks).with(:success, bid).ordered
242
- CanvasSync::JobBatches::Batch.process_successful_job(bid, jid)
243
- end
244
-
245
- it 'tries to call success callback after a previous failure' do
246
- expect(CanvasSync::JobBatches::Batch).to receive(:enqueue_callbacks).with(:complete, bid).ordered
247
- CanvasSync::JobBatches::Batch.process_failed_job(bid, jid)
248
-
249
- expect(CanvasSync::JobBatches::Batch).to receive(:enqueue_callbacks).with(:complete, bid).ordered
250
- expect(CanvasSync::JobBatches::Batch).to receive(:enqueue_callbacks).with(:success, bid).ordered
251
- CanvasSync::JobBatches::Batch.process_successful_job(bid, jid)
252
- end
253
-
254
- it 'triggers callbacks as expected' do
255
- ActiveJob::Base.queue_adapter = :sidekiq
256
- CanvasSync::JobBatches::Batch::Callback.worker_class = CanvasSync::JobBatches::Compat::Sidekiq::SidekiqCallbackWorker
257
-
258
- callback_instance = double('SampleCallback')
259
- expect(SampleCallback).to receive(:new).at_least(1).times.and_return(callback_instance)
260
- expect(callback_instance).to receive(:on_complete)
261
- expect(callback_instance).to receive(:on_success)
262
-
263
- batch.on(:complete, SampleCallback)
264
- batch.on(:success, SampleCallback)
265
-
266
- Sidekiq::Testing.inline! do
267
- CanvasSync::JobBatches::Batch.process_failed_job(bid, jid)
268
- CanvasSync::JobBatches::Batch.process_successful_job(bid, jid)
269
- end
270
- end
271
-
272
- it 'delays triggering callbacks if keep_open is set' do
273
- ActiveJob::Base.queue_adapter = :sidekiq
274
- CanvasSync::JobBatches::Batch::Callback.worker_class = CanvasSync::JobBatches::Compat::Sidekiq::SidekiqCallbackWorker
275
-
276
- callback_instance = double('SampleCallback')
277
- expect(SampleCallback).to receive(:new).at_least(1).times.and_return(callback_instance)
278
- expect(callback_instance).not_to receive(:on_complete)
279
- expect(callback_instance).not_to receive(:on_success)
280
-
281
- batch.on(:complete, SampleCallback)
282
- batch.on(:success, SampleCallback)
283
- batch.keep_open!
284
-
285
- Sidekiq::Testing.inline! do
286
- CanvasSync::JobBatches::Batch.process_failed_job(bid, jid)
287
- CanvasSync::JobBatches::Batch.process_successful_job(bid, jid)
288
- end
289
-
290
- RSpec::Mocks.space.proxy_for(callback_instance).reset
291
-
292
- expect(callback_instance).to receive(:on_complete)
293
- expect(callback_instance).to receive(:on_success)
294
-
295
- Sidekiq::Testing.inline! do
296
- batch.let_close!
297
- end
298
- end
299
-
300
- it 'triggers callbacks as expected' do
301
- ActiveJob::Base.queue_adapter = :sidekiq
302
- CanvasSync::JobBatches::Batch.redis { |r| r.hset("BID-#{bid}", 'pending', 0) }
303
-
304
- class RetryingJob < BatchTestJobBase
305
- @@failed = false
306
-
307
- def perform
308
- unless @@failed
309
- @@failed = true
310
- raise "A Failure"
311
- end
312
- end
313
- end
314
-
315
- callback_instance = double('SampleCallback')
316
- expect(SampleCallback).to receive(:new).at_least(1).times.and_return(callback_instance)
317
- expect(callback_instance).to receive(:on_complete)
318
- expect(callback_instance).to receive(:on_success)
319
-
320
- batch.on(:complete, SampleCallback)
321
- batch.on(:success, SampleCallback)
322
-
323
- batch.jobs do
324
- RetryingJob.perform_later
325
- end
326
-
327
- job_def = Sidekiq::Worker.jobs[0]
328
- int_job_class = job_def["class"].constantize
329
-
330
- begin
331
- int_job_class.process_job(job_def)
332
- rescue
333
- end
334
- Sidekiq::Worker.drain_all
335
- end
336
-
337
- it 'cleanups redis key' do
338
- CanvasSync::JobBatches::Batch.process_successful_job(bid, jid)
339
- expect(CanvasSync::JobBatches::Batch.redis { |r| r.get("BID-#{bid}-pending") }.to_i).to eq(0)
340
- end
341
- end
342
- end
343
-
344
- describe '#append_jobs' do
345
- let(:batch) { CanvasSync::JobBatches::Batch.new }
346
-
347
- it 'increments pending' do
348
- batch.jobs do BatchTestWorker.perform_async end
349
- pending = CanvasSync::JobBatches::Batch.redis { |r| r.hget("BID-#{batch.bid}", 'pending') }
350
- expect(pending).to eq('1')
351
- end
352
- end
353
-
354
- describe '#enqueue_callbacks' do
355
- let(:callback) { double('callback') }
356
- let(:event) { :complete }
357
-
358
- context 'on :success' do
359
- let(:event) { :success }
360
- context 'when no callbacks are defined' do
361
- it 'clears redis keys' do
362
- batch = CanvasSync::JobBatches::Batch.new
363
- batch.jobs {}
364
- expect(CanvasSync::JobBatches::Batch).to receive(:cleanup_redis).with(batch.bid)
365
- CanvasSync::JobBatches::Batch.enqueue_callbacks(event, batch.bid)
366
- end
367
- end
368
- end
369
-
370
- context 'when already called' do
371
- it 'returns and does not enqueue callbacks' do
372
- batch = CanvasSync::JobBatches::Batch.new
373
- batch.on(event, SampleCallback)
374
- CanvasSync::JobBatches::Batch.redis { |r| r.hset("BID-#{batch.bid}", event, "true") }
375
-
376
- expect(batch).not_to receive(:push_callbacks)
377
- CanvasSync::JobBatches::Batch.enqueue_callbacks(event, batch.bid)
378
- end
379
- end
380
-
381
- context 'With ActiveJob Adapter' do
382
- around(:all) do |block|
383
- CanvasSync::JobBatches::Batch::Callback.worker_class = CanvasSync::JobBatches::Compat::ActiveJob::ActiveJobCallbackWorker
384
- block.run
385
- end
386
-
387
- context 'when not yet called' do
388
- context 'when there is no callback' do
389
- it 'it returns' do
390
- batch = CanvasSync::JobBatches::Batch.new
391
-
392
- expect(batch).not_to receive(:push_callbacks)
393
- CanvasSync::JobBatches::Batch.enqueue_callbacks(event, batch.bid)
394
- end
395
- end
396
-
397
- context 'when callback defined' do
398
- let(:opts) { { 'a' => 'b' } }
399
-
400
- it 'calls it passing options' do
401
- ActiveJob::Base.queue_adapter = :test
402
-
403
- batch = CanvasSync::JobBatches::Batch.new
404
- batch.on(event, SampleCallback, opts)
405
- batch.jobs {}
406
-
407
- CanvasSync::JobBatches::Batch.enqueue_callbacks(event, batch.bid)
408
-
409
- expect(CanvasSync::JobBatches::Batch::Callback.worker_class).to have_been_enqueued.with(
410
- 'SampleCallback', event.to_s, opts, batch.bid, nil
411
- )
412
- end
413
- end
414
-
415
- context 'when multiple callbacks are defined' do
416
- let(:opts) { { 'a' => 'b' } }
417
- let(:opts2) { { 'b' => 'a' } }
418
-
419
- it 'enqueues each callback passing their options' do
420
- ActiveJob::Base.queue_adapter = :test
421
-
422
- batch = CanvasSync::JobBatches::Batch.new
423
- batch.on(event, SampleCallback, opts)
424
- batch.on(event, SampleCallback2, opts2)
425
- batch.jobs{}
426
-
427
- CanvasSync::JobBatches::Batch.enqueue_callbacks(event, batch.bid)
428
- expect(CanvasSync::JobBatches::Batch::Callback.worker_class).to have_been_enqueued.with(
429
- 'SampleCallback2', event.to_s, opts2, batch.bid, nil
430
- )
431
- expect(CanvasSync::JobBatches::Batch::Callback.worker_class).to have_been_enqueued.with(
432
- 'SampleCallback', event.to_s, opts, batch.bid, nil
433
- )
434
- end
435
- end
436
- end
437
- end
438
-
439
- context 'With Sidekiq Adapter' do
440
- around(:all) do |block|
441
- CanvasSync::JobBatches::Batch::Callback.worker_class = CanvasSync::JobBatches::Compat::Sidekiq::SidekiqCallbackWorker
442
- block.run
443
- end
444
-
445
- context 'when not yet called' do
446
- context 'when there is no callback' do
447
- it 'it returns' do
448
- batch = CanvasSync::JobBatches::Batch.new
449
-
450
- expect(batch).not_to receive(:push_callbacks)
451
- CanvasSync::JobBatches::Batch.enqueue_callbacks(event, batch.bid)
452
- end
453
- end
454
-
455
- context 'when callback defined' do
456
- let(:opts) { { 'a' => 'b' } }
457
-
458
- it 'calls it passing options' do
459
- batch = CanvasSync::JobBatches::Batch.new
460
- batch.on(event, SampleCallback, opts)
461
- batch.jobs{}
462
-
463
- expect(Sidekiq::Client).to receive(:push_bulk).with(
464
- 'class' => Sidekiq::Batch::Callback.worker_class,
465
- 'args' => [['SampleCallback', event.to_s, opts, batch.bid, nil]],
466
- 'queue' => 'default'
467
- )
468
-
469
- CanvasSync::JobBatches::Batch.enqueue_callbacks(event, batch.bid)
470
- end
471
- end
472
-
473
- context 'when multiple callbacks are defined' do
474
- let(:opts) { { 'a' => 'b' } }
475
- let(:opts2) { { 'b' => 'a' } }
476
-
477
- it 'enqueues each callback passing their options' do
478
- batch = CanvasSync::JobBatches::Batch.new
479
- batch.on(event, SampleCallback, opts)
480
- batch.on(event, SampleCallback2, opts2)
481
- batch.jobs{}
482
-
483
- expect(Sidekiq::Client).to receive(:push_bulk).with(
484
- 'class' => Sidekiq::Batch::Callback.worker_class,
485
- 'args' => array_including(
486
- ['SampleCallback', event.to_s, opts, batch.bid, nil],
487
- ['SampleCallback2', event.to_s, opts2, batch.bid, nil],
488
- ),
489
- 'queue' => 'default'
490
- )
491
-
492
- CanvasSync::JobBatches::Batch.enqueue_callbacks(event, batch.bid)
493
- end
494
- end
495
- end
496
- end
497
- end
498
-
499
- describe '.redis' do
500
- it 'returns the same connection if called when nested' do
501
- CanvasSync::JobBatches::Batch.redis do |r1|
502
- CanvasSync::JobBatches::Batch.redis do |r2|
503
- expect(r1).to be r2
504
- end
505
- end
506
- end
507
-
508
- it 'returns a RedisProxy object if no block is given' do
509
- expect(CanvasSync::JobBatches::Batch.redis).to be_a(CanvasSync::JobBatches::Batch::RedisProxy)
510
- end
511
-
512
- describe 'RedisProxy' do
513
- let!(:proxy) { CanvasSync::JobBatches::Batch.redis }
514
-
515
- it 'calls Batch.redis with a block' do
516
- expect(CanvasSync::JobBatches::Batch).to receive(:redis) do |&block|
517
- expect(block).to be_a Proc
518
- end
519
- proxy.sadd('KEY', 5)
520
- end
521
-
522
- describe '#multi' do
523
- it 'works with 1 arity' do
524
- proxy.multi do |r|
525
- r.sadd('KEY', 5)
526
- end
527
- end
528
- end
529
- end
530
- end
531
- end
@@ -1,38 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe CanvasSync::JobBatches::Batch::Callback.worker_class do
4
- describe '#perform' do
5
- it 'does not do anything if it cannot find the callback class' do
6
- subject.perform('SampleCallback', 'complete', {}, 'ABCD', 'EFGH')
7
- end
8
-
9
- it 'does not do anything if event is different from complete or success' do
10
- expect(SampleCallback).not_to receive(:new)
11
- subject.perform('SampleCallback', 'ups', {}, 'ABCD', 'EFGH')
12
- end
13
-
14
- it 'calls on_success if defined' do
15
- callback_instance = double('SampleCallback', on_success: true)
16
- expect(SampleCallback).to receive(:new).and_return(callback_instance)
17
- expect(callback_instance).to receive(:on_success)
18
- .with(instance_of(CanvasSync::JobBatches::Batch::Status), {})
19
- subject.perform('SampleCallback', 'success', {}, 'ABCD', 'EFGH')
20
- end
21
-
22
- it 'calls on_complete if defined' do
23
- callback_instance = double('SampleCallback')
24
- expect(SampleCallback).to receive(:new).and_return(callback_instance)
25
- expect(callback_instance).to receive(:on_complete)
26
- .with(instance_of(CanvasSync::JobBatches::Batch::Status), {})
27
- subject.perform('SampleCallback', 'complete', {}, 'ABCD', 'EFGH')
28
- end
29
-
30
- it 'calls specific callback if defined' do
31
- callback_instance = double('SampleCallback')
32
- expect(SampleCallback).to receive(:new).and_return(callback_instance)
33
- expect(callback_instance).to receive(:sample_method)
34
- .with(instance_of(CanvasSync::JobBatches::Batch::Status), {})
35
- subject.perform('SampleCallback#sample_method', 'complete', {}, 'ABCD', 'EFGH')
36
- end
37
- end
38
- end
@@ -1,107 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe CanvasSync::JobBatches::Compat::ActiveJob do
4
- describe CanvasSync::JobBatches::Compat::ActiveJob::BatchAwareJob do
5
- include ActiveJob::TestHelper
6
-
7
- after do
8
- clear_enqueued_jobs
9
- clear_performed_jobs
10
- end
11
-
12
- context "When Performing" do
13
- context 'when without batch' do
14
- it 'just yields' do
15
- expect(CanvasSync::JobBatches::Batch).not_to receive(:process_successful_job)
16
- expect(CanvasSync::JobBatches::Batch).not_to receive(:process_failed_job)
17
- expect_any_instance_of(BatchTestJobBase).to receive(:perform)
18
-
19
- BatchTestJobBase.perform_now
20
- end
21
- end
22
-
23
- context 'when in batch' do
24
- let(:bid) { 'SAMPLEBID' }
25
-
26
- context 'when successful' do
27
- it 'yields' do
28
- expect_any_instance_of(BatchTestJobBase).to receive(:perform)
29
- BatchTestJobBase.perform_now
30
- end
31
-
32
- it 'calls process_successful_job' do
33
- job = BatchTestJobBase.new
34
- job.instance_variable_set(:@bid, bid)
35
- expect(CanvasSync::JobBatches::Batch).to receive(:process_successful_job).with(bid, job.job_id)
36
- job.perform_now
37
- end
38
- end
39
-
40
- context 'when failed' do
41
- it 'calls process_failed_job and reraises exception' do
42
- reraised = false
43
- job = FailingBatchTestJobBase.new
44
- job.instance_variable_set(:@bid, bid)
45
- expect(CanvasSync::JobBatches::Batch).to receive(:process_failed_job)
46
- begin
47
- job.perform_now
48
- rescue
49
- reraised = true
50
- end
51
- expect(reraised).to be_truthy
52
- end
53
- end
54
- end
55
- end
56
-
57
- context "When Enqueueing" do
58
- context 'when without batch' do
59
- it 'just yields' do
60
- expect(CanvasSync::JobBatches::Batch).not_to receive(:append_jobs)
61
- BatchTestJobBase.perform_later
62
- expect(BatchTestJobBase).to have_been_enqueued
63
- end
64
- end
65
-
66
- context 'when in batch' do
67
- let(:bid) { 'SAMPLEBID' }
68
-
69
- before do
70
- Thread.current[CanvasSync::JobBatches::CURRENT_BATCH_THREAD_KEY] = CanvasSync::JobBatches::Batch.new(bid)
71
- Thread.current[CanvasSync::JobBatches::CURRENT_BATCH_THREAD_KEY].instance_variable_set(:@open, true)
72
- end
73
- after { Thread.current[CanvasSync::JobBatches::CURRENT_BATCH_THREAD_KEY] = nil }
74
-
75
- it 'yields' do
76
- expect {
77
- BatchTestJobBase.perform_later
78
- }.to enqueue_job(BatchTestJobBase)
79
- end
80
-
81
- it 'assigns bid to job metadata' do
82
- job = BatchTestJobBase.perform_later
83
- expect(job.bid).to eq bid
84
- expect(job.serialize['batch_id']).to eq bid
85
- end
86
- end
87
- end
88
-
89
- context 'worker' do
90
- it 'defines method bid' do
91
- expect(ActiveJob::Base.instance_methods).to include(:bid)
92
- end
93
-
94
- it 'defines method batch' do
95
- expect(ActiveJob::Base.instance_methods).to include(:batch)
96
- end
97
-
98
- it 'defines method valid_within_batch?' do
99
- expect(ActiveJob::Base.instance_methods).to include(:valid_within_batch?)
100
- end
101
- end
102
- end
103
-
104
- describe ".handle_job_death" do
105
-
106
- end
107
- end