canvas_sync 0.23.5 → 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 (205) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +2 -4
  3. data/lib/canvas_sync/version.rb +1 -1
  4. data/lib/canvas_sync.rb +6 -4
  5. data/spec/canvas_sync/canvas_sync_spec.rb +11 -11
  6. data/spec/canvas_sync/live_events/process_event_job_spec.rb +1 -0
  7. data/spec/{dummy → internal}/app/models/application_record.rb +1 -0
  8. data/spec/{dummy → internal}/app/models/content_migration.rb +0 -0
  9. data/spec/{dummy → internal}/app/models/course.rb +0 -1
  10. data/spec/{dummy → internal}/app/models/course_nickname.rb +0 -0
  11. data/spec/{dummy → internal}/app/models/learning_outcome.rb +0 -0
  12. data/spec/{dummy → internal}/app/services/live_events/assignment_event.rb +0 -0
  13. data/spec/{dummy → internal}/app/services/live_events/course_event.rb +0 -0
  14. data/spec/{dummy → internal}/app/services/live_events/course_section_event.rb +0 -0
  15. data/spec/{dummy → internal}/app/services/live_events/enrollment_event.rb +0 -0
  16. data/spec/{dummy → internal}/app/services/live_events/grade_event.rb +0 -0
  17. data/spec/{dummy → internal}/app/services/live_events/module_event.rb +0 -0
  18. data/spec/{dummy → internal}/app/services/live_events/module_item_event.rb +0 -0
  19. data/spec/{dummy → internal}/app/services/live_events/submission_event.rb +0 -0
  20. data/spec/{dummy → internal}/app/services/live_events/syllabus_event.rb +0 -0
  21. data/spec/{dummy → internal}/app/services/live_events/user_event.rb +0 -0
  22. data/spec/internal/bin/rails +9 -0
  23. data/spec/internal/config/database.yml +5 -0
  24. data/spec/internal/config/routes.rb +5 -0
  25. data/spec/internal/config/storage.yml +3 -0
  26. data/spec/{dummy/db/migrate/20220926221926_create_users.rb → internal/db/migrate/20250912205136_create_users.rb} +0 -0
  27. data/spec/{dummy/db/migrate/20201016181346_create_pseudonyms.rb → internal/db/migrate/20250912205137_create_pseudonyms.rb} +0 -0
  28. data/spec/{dummy/db/migrate/20200415171620_create_groups.rb → internal/db/migrate/20250912205139_create_groups.rb} +0 -0
  29. data/spec/{dummy/db/migrate/20200416214248_create_group_memberships.rb → internal/db/migrate/20250912205140_create_group_memberships.rb} +0 -0
  30. data/spec/{dummy/db/migrate/20190702203622_create_accounts.rb → internal/db/migrate/20250912205141_create_accounts.rb} +0 -0
  31. data/spec/{dummy/db/migrate/20190702203623_create_terms.rb → internal/db/migrate/20250912205142_create_terms.rb} +0 -0
  32. data/spec/{dummy/db/migrate/20190702203625_create_sections.rb → internal/db/migrate/20250912205144_create_sections.rb} +0 -0
  33. data/spec/{dummy/db/migrate/20190702203626_create_assignments.rb → internal/db/migrate/20250912205145_create_assignments.rb} +0 -0
  34. data/spec/{dummy/db/migrate/20190702203627_create_submissions.rb → internal/db/migrate/20250912205146_create_submissions.rb} +0 -0
  35. data/spec/{dummy/db/migrate/20190927204545_create_roles.rb → internal/db/migrate/20250912205147_create_roles.rb} +2 -2
  36. data/spec/{dummy/db/migrate/20190927204546_create_admins.rb → internal/db/migrate/20250912205148_create_admins.rb} +0 -0
  37. data/spec/{dummy/db/migrate/20190702203630_create_assignment_groups.rb → internal/db/migrate/20250912205149_create_assignment_groups.rb} +0 -0
  38. data/spec/{dummy/db/migrate/20190702203631_create_context_modules.rb → internal/db/migrate/20250912205150_create_context_modules.rb} +0 -0
  39. data/spec/{dummy/db/migrate/20190702203632_create_context_module_items.rb → internal/db/migrate/20250912205151_create_context_module_items.rb} +0 -0
  40. data/spec/{dummy/db/migrate/20210907233329_create_user_observers.rb → internal/db/migrate/20250912205152_create_user_observers.rb} +0 -0
  41. data/spec/{dummy/db/migrate/20210907233330_create_grading_periods.rb → internal/db/migrate/20250912205153_create_grading_periods.rb} +0 -0
  42. data/spec/{dummy/db/migrate/20211001184920_create_grading_period_groups.rb → internal/db/migrate/20250912205154_create_grading_period_groups.rb} +0 -0
  43. data/spec/{dummy/db/migrate/20220308072643_create_content_migrations.rb → internal/db/migrate/20250912205155_create_content_migrations.rb} +0 -0
  44. data/spec/{dummy/db/migrate/20220712210559_create_learning_outcomes.rb → internal/db/migrate/20250912205156_create_learning_outcomes.rb} +0 -0
  45. data/spec/{dummy/db/migrate/20240523101010_create_learning_outcome_results.rb → internal/db/migrate/20250912205157_create_learning_outcome_results.rb} +0 -0
  46. data/spec/{dummy/db/migrate/20240510094100_create_rubric_associations.rb → internal/db/migrate/20250912205160_create_rubric_associations.rb} +0 -0
  47. data/spec/{dummy/db/migrate/20240510101100_create_rubric_assessments.rb → internal/db/migrate/20250912205161_create_rubric_assessments.rb} +0 -0
  48. data/spec/{dummy/db/migrate/20240828161300_create_course_progresses.rb → internal/db/migrate/20250912205162_create_course_progresses.rb} +0 -0
  49. data/spec/internal/db/schema.rb +6 -0
  50. data/spec/spec_helper.rb +8 -4
  51. metadata +182 -372
  52. data/lib/canvas_sync/job_batches/batch.rb +0 -595
  53. data/lib/canvas_sync/job_batches/callback.rb +0 -135
  54. data/lib/canvas_sync/job_batches/chain_builder.rb +0 -247
  55. data/lib/canvas_sync/job_batches/compat/active_job.rb +0 -108
  56. data/lib/canvas_sync/job_batches/compat/sidekiq/web/batches_assets/css/styles.less +0 -182
  57. data/lib/canvas_sync/job_batches/compat/sidekiq/web/batches_assets/js/batch_tree.js +0 -108
  58. data/lib/canvas_sync/job_batches/compat/sidekiq/web/batches_assets/js/util.js +0 -2
  59. data/lib/canvas_sync/job_batches/compat/sidekiq/web/helpers.rb +0 -41
  60. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/_batch_tree.erb +0 -6
  61. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/_batches_table.erb +0 -44
  62. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/_common.erb +0 -13
  63. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/_jobs_table.erb +0 -21
  64. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/_pagination.erb +0 -26
  65. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/batch.erb +0 -81
  66. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/batches.erb +0 -23
  67. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/pool.erb +0 -137
  68. data/lib/canvas_sync/job_batches/compat/sidekiq/web/views/pools.erb +0 -47
  69. data/lib/canvas_sync/job_batches/compat/sidekiq/web.rb +0 -218
  70. data/lib/canvas_sync/job_batches/compat/sidekiq.rb +0 -149
  71. data/lib/canvas_sync/job_batches/compat.rb +0 -20
  72. data/lib/canvas_sync/job_batches/context_hash.rb +0 -157
  73. data/lib/canvas_sync/job_batches/hier_batch_ids.lua +0 -25
  74. data/lib/canvas_sync/job_batches/jobs/base_job.rb +0 -5
  75. data/lib/canvas_sync/job_batches/jobs/concurrent_batch_job.rb +0 -20
  76. data/lib/canvas_sync/job_batches/jobs/managed_batch_job.rb +0 -175
  77. data/lib/canvas_sync/job_batches/jobs/serial_batch_job.rb +0 -20
  78. data/lib/canvas_sync/job_batches/pool.rb +0 -254
  79. data/lib/canvas_sync/job_batches/pool_refill.lua +0 -47
  80. data/lib/canvas_sync/job_batches/redis_model.rb +0 -67
  81. data/lib/canvas_sync/job_batches/redis_script.rb +0 -161
  82. data/lib/canvas_sync/job_batches/schedule_callback.lua +0 -14
  83. data/lib/canvas_sync/job_batches/status.rb +0 -89
  84. data/lib/canvas_sync/job_uniqueness/compat/active_job.rb +0 -75
  85. data/lib/canvas_sync/job_uniqueness/compat/sidekiq.rb +0 -135
  86. data/lib/canvas_sync/job_uniqueness/compat.rb +0 -20
  87. data/lib/canvas_sync/job_uniqueness/configuration.rb +0 -25
  88. data/lib/canvas_sync/job_uniqueness/job_uniqueness.rb +0 -47
  89. data/lib/canvas_sync/job_uniqueness/lock_context.rb +0 -199
  90. data/lib/canvas_sync/job_uniqueness/locksmith.rb +0 -92
  91. data/lib/canvas_sync/job_uniqueness/on_conflict/base.rb +0 -32
  92. data/lib/canvas_sync/job_uniqueness/on_conflict/log.rb +0 -13
  93. data/lib/canvas_sync/job_uniqueness/on_conflict/null_strategy.rb +0 -9
  94. data/lib/canvas_sync/job_uniqueness/on_conflict/raise.rb +0 -11
  95. data/lib/canvas_sync/job_uniqueness/on_conflict/reject.rb +0 -21
  96. data/lib/canvas_sync/job_uniqueness/on_conflict/reschedule.rb +0 -20
  97. data/lib/canvas_sync/job_uniqueness/on_conflict.rb +0 -62
  98. data/lib/canvas_sync/job_uniqueness/strategy/base.rb +0 -107
  99. data/lib/canvas_sync/job_uniqueness/strategy/until_and_while_executing.rb +0 -35
  100. data/lib/canvas_sync/job_uniqueness/strategy/until_executed.rb +0 -20
  101. data/lib/canvas_sync/job_uniqueness/strategy/until_executing.rb +0 -20
  102. data/lib/canvas_sync/job_uniqueness/strategy/until_expired.rb +0 -16
  103. data/lib/canvas_sync/job_uniqueness/strategy/while_executing.rb +0 -26
  104. data/lib/canvas_sync/job_uniqueness/strategy.rb +0 -27
  105. data/lib/canvas_sync/job_uniqueness/unique_job_common.rb +0 -79
  106. data/spec/dummy/README.rdoc +0 -1
  107. data/spec/dummy/Rakefile +0 -6
  108. data/spec/dummy/app/services/live_events/assignment_created_event.rb +0 -12
  109. data/spec/dummy/app/services/live_events/assignment_updated_event.rb +0 -12
  110. data/spec/dummy/app/services/live_events/base_event.rb +0 -52
  111. data/spec/dummy/app/services/live_events/course_created_event.rb +0 -12
  112. data/spec/dummy/app/services/live_events/course_section_created_event.rb +0 -12
  113. data/spec/dummy/app/services/live_events/course_section_updated_event.rb +0 -12
  114. data/spec/dummy/app/services/live_events/course_updated_event.rb +0 -12
  115. data/spec/dummy/app/services/live_events/enrollment_created_event.rb +0 -12
  116. data/spec/dummy/app/services/live_events/enrollment_updated_event.rb +0 -12
  117. data/spec/dummy/app/services/live_events/grade_changed_event.rb +0 -12
  118. data/spec/dummy/app/services/live_events/module_created_event.rb +0 -12
  119. data/spec/dummy/app/services/live_events/module_item_created_event.rb +0 -12
  120. data/spec/dummy/app/services/live_events/module_item_updated_event.rb +0 -12
  121. data/spec/dummy/app/services/live_events/module_updated_event.rb +0 -12
  122. data/spec/dummy/app/services/live_events/submission_created_event.rb +0 -12
  123. data/spec/dummy/app/services/live_events/submission_updated_event.rb +0 -12
  124. data/spec/dummy/app/services/live_events/syllabus_updated_event.rb +0 -12
  125. data/spec/dummy/app/services/live_events/user_created_event.rb +0 -12
  126. data/spec/dummy/app/services/live_events/user_updated_event.rb +0 -12
  127. data/spec/dummy/bin/rails +0 -4
  128. data/spec/dummy/config/application.rb +0 -39
  129. data/spec/dummy/config/boot.rb +0 -5
  130. data/spec/dummy/config/database.yml +0 -25
  131. data/spec/dummy/config/environment.rb +0 -5
  132. data/spec/dummy/config/environments/development.rb +0 -41
  133. data/spec/dummy/config/environments/test.rb +0 -44
  134. data/spec/dummy/config/initializers/assets.rb +0 -11
  135. data/spec/dummy/config/initializers/session_store.rb +0 -3
  136. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
  137. data/spec/dummy/config/routes.rb +0 -3
  138. data/spec/dummy/config/secrets.yml +0 -22
  139. data/spec/dummy/config.ru +0 -4
  140. data/spec/dummy/db/schema.rb +0 -563
  141. data/spec/job_batching/batch_spec.rb +0 -531
  142. data/spec/job_batching/callback_spec.rb +0 -38
  143. data/spec/job_batching/compat/active_job_spec.rb +0 -107
  144. data/spec/job_batching/compat/sidekiq_spec.rb +0 -127
  145. data/spec/job_batching/context_hash_spec.rb +0 -54
  146. data/spec/job_batching/flow_spec.rb +0 -82
  147. data/spec/job_batching/integration/fail_then_succeed.rb +0 -42
  148. data/spec/job_batching/integration/integration.rb +0 -57
  149. data/spec/job_batching/integration/nested.rb +0 -88
  150. data/spec/job_batching/integration/simple.rb +0 -47
  151. data/spec/job_batching/integration/workflow.rb +0 -134
  152. data/spec/job_batching/integration_helper.rb +0 -50
  153. data/spec/job_batching/pool_spec.rb +0 -161
  154. data/spec/job_batching/status_spec.rb +0 -76
  155. data/spec/job_batching/support/base_job.rb +0 -14
  156. data/spec/job_batching/support/sample_callback.rb +0 -2
  157. data/spec/job_uniqueness/compat/active_job_spec.rb +0 -49
  158. data/spec/job_uniqueness/compat/sidekiq_spec.rb +0 -68
  159. data/spec/job_uniqueness/lock_context_spec.rb +0 -106
  160. data/spec/job_uniqueness/on_conflict/log_spec.rb +0 -11
  161. data/spec/job_uniqueness/on_conflict/raise_spec.rb +0 -10
  162. data/spec/job_uniqueness/on_conflict/reschedule_spec.rb +0 -63
  163. data/spec/job_uniqueness/on_conflict_spec.rb +0 -16
  164. data/spec/job_uniqueness/spec_helper.rb +0 -17
  165. data/spec/job_uniqueness/strategy/base_spec.rb +0 -100
  166. data/spec/job_uniqueness/strategy/until_and_while_executing_spec.rb +0 -48
  167. data/spec/job_uniqueness/strategy/until_executed_spec.rb +0 -23
  168. data/spec/job_uniqueness/strategy/until_executing_spec.rb +0 -23
  169. data/spec/job_uniqueness/strategy/until_expired_spec.rb +0 -23
  170. data/spec/job_uniqueness/strategy/while_executing_spec.rb +0 -33
  171. data/spec/job_uniqueness/support/lock_strategy.rb +0 -28
  172. data/spec/job_uniqueness/support/on_conflict.rb +0 -24
  173. data/spec/job_uniqueness/support/test_worker.rb +0 -19
  174. data/spec/job_uniqueness/unique_job_common_spec.rb +0 -45
  175. /data/spec/{dummy → internal}/app/models/account.rb +0 -0
  176. /data/spec/{dummy → internal}/app/models/admin.rb +0 -0
  177. /data/spec/{dummy → internal}/app/models/assignment.rb +0 -0
  178. /data/spec/{dummy → internal}/app/models/assignment_group.rb +0 -0
  179. /data/spec/{dummy → internal}/app/models/assignment_override.rb +0 -0
  180. /data/spec/{dummy → internal}/app/models/context_module.rb +0 -0
  181. /data/spec/{dummy → internal}/app/models/context_module_item.rb +0 -0
  182. /data/spec/{dummy → internal}/app/models/course_progress.rb +0 -0
  183. /data/spec/{dummy → internal}/app/models/enrollment.rb +0 -0
  184. /data/spec/{dummy → internal}/app/models/grading_period.rb +0 -0
  185. /data/spec/{dummy → internal}/app/models/grading_period_group.rb +0 -0
  186. /data/spec/{dummy → internal}/app/models/group.rb +0 -0
  187. /data/spec/{dummy → internal}/app/models/group_membership.rb +0 -0
  188. /data/spec/{dummy → internal}/app/models/learning_outcome_result.rb +0 -0
  189. /data/spec/{dummy → internal}/app/models/pseudonym.rb +0 -0
  190. /data/spec/{dummy → internal}/app/models/role.rb +0 -0
  191. /data/spec/{dummy → internal}/app/models/rubric.rb +0 -0
  192. /data/spec/{dummy → internal}/app/models/rubric_assessment.rb +0 -0
  193. /data/spec/{dummy → internal}/app/models/rubric_association.rb +0 -0
  194. /data/spec/{dummy → internal}/app/models/score.rb +0 -0
  195. /data/spec/{dummy → internal}/app/models/section.rb +0 -0
  196. /data/spec/{dummy → internal}/app/models/submission.rb +0 -0
  197. /data/spec/{dummy → internal}/app/models/term.rb +0 -0
  198. /data/spec/{dummy → internal}/app/models/user.rb +0 -0
  199. /data/spec/{dummy → internal}/app/models/user_observer.rb +0 -0
  200. /data/spec/{dummy/db/migrate/20190702203621_create_courses.rb → internal/db/migrate/20250912205138_create_courses.rb} +0 -0
  201. /data/spec/{dummy/db/migrate/20190702203624_create_enrollments.rb → internal/db/migrate/20250912205143_create_enrollments.rb} +0 -0
  202. /data/spec/{dummy/db/migrate/20250319194134_create_course_nicknames.rb → internal/db/migrate/20250912205158_create_course_nicknames.rb} +0 -0
  203. /data/spec/{dummy/db/migrate/20250319194135_create_rubrics.rb → internal/db/migrate/20250912205159_create_rubrics.rb} +0 -0
  204. /data/spec/{dummy/db/migrate/20241223080202_create_assignment_overrides.rb → internal/db/migrate/20250912205163_create_assignment_overrides.rb} +0 -0
  205. /data/spec/{dummy/db/migrate/20250626194330_create_scores.rb → internal/db/migrate/20250912205164_create_scores.rb} +0 -0
@@ -1,161 +0,0 @@
1
- require 'pathname'
2
- require 'digest/sha1'
3
- require 'erb'
4
-
5
- # Modified from https://github.com/Shopify/wolverine/blob/master/lib/wolverine/script.rb
6
-
7
- module CanvasSync::JobBatches
8
- # {RedisScript} represents a lua script in the filesystem. It loads the script
9
- # from disk and handles talking to redis to execute it. Error handling
10
- # is handled by {LuaError}.
11
- class RedisScript
12
-
13
- # Loads the script file from disk and calculates its +SHA1+ sum.
14
- #
15
- # @param file [Pathname] the full path to the indicated file
16
- def initialize(file)
17
- @file = Pathname.new(file)
18
- end
19
-
20
- # Passes the script and supplied arguments to redis for evaulation.
21
- # It first attempts to use a script redis has already cached by using
22
- # the +EVALSHA+ command, but falls back to providing the full script
23
- # text via +EVAL+ if redis has not seen this script before. Future
24
- # invocations will then use +EVALSHA+ without erroring.
25
- #
26
- # @param redis [Redis] the redis connection to run against
27
- # @param args [*Objects] the arguments to the script
28
- # @return [Object] the value passed back by redis after script execution
29
- # @raise [LuaError] if the script failed to compile of encountered a
30
- # runtime error
31
- def call(redis, *args)
32
- t = Time.now
33
- begin
34
- redis.evalsha(digest, *args)
35
- rescue => e
36
- e.message =~ /NOSCRIPT/ ? redis.eval(content, *args) : raise
37
- end
38
- rescue => e
39
- if LuaError.intercepts?(e)
40
- raise LuaError.new(e, @file, content)
41
- else
42
- raise
43
- end
44
- end
45
-
46
- def content
47
- @content ||= load_lua(@file)
48
- end
49
-
50
- def digest
51
- @digest ||= Digest::SHA1.hexdigest content
52
- end
53
-
54
- private
55
-
56
- def script_path
57
- Rails.root + 'app/redis_lua'
58
- end
59
-
60
- def relative_path
61
- @path ||= @file.relative_path_from(script_path)
62
- end
63
-
64
- def load_lua(file)
65
- TemplateContext.new(script_path).template(script_path + file)
66
- end
67
-
68
- class TemplateContext
69
- def initialize(script_path)
70
- @script_path = script_path
71
- end
72
-
73
- def template(pathname)
74
- @partial_templates ||= {}
75
- ERB.new(File.read(pathname)).result binding
76
- end
77
-
78
- # helper method to include a lua partial within another lua script
79
- #
80
- # @param relative_path [String] the relative path to the script from
81
- # `script_path`
82
- def include_partial(relative_path)
83
- unless @partial_templates.has_key? relative_path
84
- @partial_templates[relative_path] = nil
85
- template( Pathname.new("#{@script_path}/#{relative_path}") )
86
- end
87
- end
88
- end
89
-
90
- # Reformats errors raised by redis representing failures while executing
91
- # a lua script. The default errors have confusing messages and backtraces,
92
- # and a type of +RuntimeError+. This class improves the message and
93
- # modifies the backtrace to include the lua script itself in a reasonable
94
- # way.
95
- class LuaError < StandardError
96
- PATTERN = /ERR Error (compiling|running) script \(.*?\): .*?:(\d+): (.*)/
97
- WOLVERINE_LIB_PATH = File.expand_path('../../', __FILE__)
98
- CONTEXT_LINE_NUMBER = 2
99
-
100
- attr_reader :error, :file, :content
101
-
102
- # Is this error one that should be reformatted?
103
- #
104
- # @param error [StandardError] the original error raised by redis
105
- # @return [Boolean] is this an error that should be reformatted?
106
- def self.intercepts? error
107
- error.message =~ PATTERN
108
- end
109
-
110
- # Initialize a new {LuaError} from an existing redis error, adjusting
111
- # the message and backtrace in the process.
112
- #
113
- # @param error [StandardError] the original error raised by redis
114
- # @param file [Pathname] full path to the lua file the error ocurred in
115
- # @param content [String] lua file content the error ocurred in
116
- def initialize error, file, content
117
- @error = error
118
- @file = file
119
- @content = content
120
-
121
- @error.message =~ PATTERN
122
- _stage, line_number, message = $1, $2, $3
123
- error_context = generate_error_context(content, line_number.to_i)
124
-
125
- super "#{message}\n\n#{error_context}\n\n"
126
- set_backtrace generate_backtrace file, line_number
127
- end
128
-
129
- private
130
-
131
- def generate_error_context(content, line_number)
132
- lines = content.lines.to_a
133
- beginning_line_number = [1, line_number - CONTEXT_LINE_NUMBER].max
134
- ending_line_number = [lines.count, line_number + CONTEXT_LINE_NUMBER].min
135
- line_number_width = ending_line_number.to_s.length
136
-
137
- (beginning_line_number..ending_line_number).map do |number|
138
- indicator = number == line_number ? '=>' : ' '
139
- formatted_number = "%#{line_number_width}d" % number
140
- " #{indicator} #{formatted_number}: #{lines[number - 1]}"
141
- end.join.chomp
142
- end
143
-
144
- def generate_backtrace(file, line_number)
145
- pre_wolverine = backtrace_before_entering_wolverine(@error.backtrace)
146
- index_of_first_wolverine_line = (@error.backtrace.size - pre_wolverine.size - 1)
147
- pre_wolverine.unshift(@error.backtrace[index_of_first_wolverine_line])
148
- pre_wolverine.unshift("#{file}:#{line_number}")
149
- pre_wolverine
150
- end
151
-
152
- def backtrace_before_entering_wolverine(backtrace)
153
- backtrace.reverse.take_while { |line| ! line_from_wolverine(line) }.reverse
154
- end
155
-
156
- def line_from_wolverine(line)
157
- line.split(':').first.include?(WOLVERINE_LIB_PATH)
158
- end
159
- end
160
- end
161
- end
@@ -1,14 +0,0 @@
1
-
2
- local previously_scheduled = redis.call('HGET', KEYS[1], ARGV[1])
3
- redis.call('HSET', KEYS[1], ARGV[1], 'true')
4
-
5
- if previously_scheduled ~= 'true' then
6
- local pcb_key = KEYS[1] .. '-pending_callbacks'
7
- redis.call('SADD', pcb_key, ARGV[1] .. '-finalize')
8
- if ARGV[2] == 'true' then
9
- redis.call('SADD', pcb_key, ARGV[1])
10
- end
11
- redis.call('EXPIRE', pcb_key, ARGV[3])
12
- end
13
-
14
- return previously_scheduled
@@ -1,89 +0,0 @@
1
- module CanvasSync::JobBatches
2
- class Batch
3
- class Status
4
- attr_reader :bid
5
-
6
- def initialize(bid)
7
- bid = bid.bid if bid.is_a?(Batch)
8
- @bid = bid
9
- end
10
-
11
- def join
12
- raise "Not supported"
13
- end
14
-
15
- def pending
16
- Batch.redis { |r| r.hget("BID-#{bid}", 'pending') }.to_i
17
- end
18
-
19
- def failures
20
- Batch.redis { |r| r.scard("BID-#{bid}-failed") }.to_i
21
- end
22
-
23
- def dead
24
- Batch.redis { |r| r.scard("BID-#{bid}-dead") }.to_i
25
- end
26
-
27
- def completed_count
28
- job_count - pending
29
- end
30
-
31
- def job_count
32
- Batch.redis { |r| r.hget("BID-#{bid}", "job_count") }.to_i
33
- end
34
-
35
- def created_at
36
- Batch.redis { |r| r.hget("BID-#{bid}", 'created_at') }
37
- end
38
-
39
- def parent_bid
40
- Batch.redis { |r| r.hget("BID-#{bid}", "parent_bid") }
41
- end
42
-
43
- def failure_info
44
- Batch.redis { |r| r.smembers("BID-#{bid}-failed") } || []
45
- end
46
-
47
- def complete?
48
- 'true' == Batch.redis { |r| r.hget("BID-#{bid}", 'complete') }
49
- end
50
-
51
- def success?
52
- 'true' == Batch.redis { |r| r.hget("BID-#{bid}", 'success') }
53
- end
54
-
55
- def child_count
56
- Batch.redis { |r| r.hget("BID-#{bid}", 'children') }.to_i
57
- end
58
-
59
- def completed_children_count
60
- Batch.redis { |r| r.scard("BID-#{bid}-batches-complete") }.to_i
61
- end
62
-
63
- def successful_children_count
64
- Batch.redis { |r| r.scard("BID-#{bid}-batches-success") }.to_i
65
- end
66
-
67
- def failed_children_count
68
- Batch.redis { |r| r.scard("BID-#{bid}-batches-failed") }.to_i
69
- end
70
-
71
- def data
72
- {
73
- bid: bid,
74
- failures: failures,
75
- pending: pending,
76
- created_at: created_at,
77
- complete: complete?,
78
- success: success?,
79
- failure_info: failure_info,
80
- parent_bid: parent_bid,
81
- child_count: child_count,
82
- completed_children_count: completed_children_count,
83
- successful_children_count: successful_children_count,
84
- failed_children_count: failed_children_count,
85
- }
86
- end
87
- end
88
- end
89
- end
@@ -1,75 +0,0 @@
1
-
2
- module CanvasSync::JobUniqueness
3
- module Compat
4
- module ActiveJob
5
-
6
- class ActiveJobLockContext < LockContext
7
- def job_scheduled_at
8
- job_instance&.scheduled_at
9
- end
10
-
11
- def reenqueue(schedule_in:)
12
- job_class.set(
13
- queue: job_queue.to_sym,
14
- wait: schedule_in,
15
- priortity: job_instance.priority,
16
- ).perform_later(*job_instance.arguments)
17
- end
18
- end
19
-
20
- module UniqueJobExtension
21
- extend ActiveSupport::Concern
22
-
23
- included do
24
- set_callback(:enqueue, :around, prepend: true) do |job, block|
25
- ctx = uniqueness_lock_context
26
- @uniqueness_cache_data = ctx.cache_data
27
- ctx.handle_lifecycle!(:enqueue, &block)
28
- end
29
-
30
- around_perform do |job, block|
31
- ctx = uniqueness_lock_context
32
- ctx.handle_lifecycle!(:perform, &block)
33
- end
34
- end
35
-
36
- def serialize
37
- super.tap do |data|
38
- data['uniqueness_cache_data'] = @uniqueness_cache_data.stringify_keys
39
- end
40
- end
41
-
42
- def deserialize(data)
43
- super
44
- @uniqueness_cache_data = data['uniqueness_cache_data']&.symbolize_keys
45
- end
46
-
47
- def uniqueness_lock_context
48
- ActiveJobLockContext.new({
49
- job_clazz: self.class,
50
- jid: self.job_id,
51
- args: self.arguments,
52
- queue: self.queue_name,
53
- **(@uniqueness_cache_data || {})
54
- }, job_instance: self)
55
- end
56
- end
57
-
58
- module JobExtension
59
- extend ActiveSupport::Concern
60
- include UniqueJobCommon
61
-
62
- class_methods do
63
- def ensure_uniqueness(**kwargs)
64
- super(**kwargs)
65
- include UniqueJobExtension
66
- end
67
- end
68
- end
69
-
70
- def self.configure
71
- ::ActiveJob::Base.include JobExtension
72
- end
73
- end
74
- end
75
- end
@@ -1,135 +0,0 @@
1
-
2
- module CanvasSync::JobUniqueness
3
- module Compat
4
- module Sidekiq
5
- module WorkerExtension
6
- extend ActiveSupport::Concern
7
- include UniqueJobCommon
8
-
9
- class_methods do
10
- def ensure_uniqueness(**kwargs)
11
- super(**kwargs)
12
- if !(defined?(@@validated_config) && @@validated_config)
13
- Compat::Sidekiq.validate_middleware_placement!()
14
- @@validated_config = true
15
- end
16
- end
17
- end
18
- end
19
-
20
- class SidekiqLockContext < LockContext
21
- def job_scheduled_at
22
- @job_instance&.[]("at")
23
- end
24
-
25
- def reenqueue(schedule_in:)
26
- job_class.set(queue: job_queue.to_sym).perform_in(schedule_in, *@job_instance["args"])
27
- end
28
- end
29
-
30
- class CommonMiddleware
31
- def lock_context(msg)
32
- opts = worker_uniqueness(msg)
33
- return nil unless opts
34
-
35
- SidekiqLockContext.new({
36
- job_clazz: msg['class'],
37
- jid: msg['jid'],
38
- queue: msg['queue'],
39
- args: msg['args'],
40
- # kwargs: msg['kwargs'],
41
- **(msg['uniqueness_cache_data']&.symbolize_keys || {}),
42
- }, job_instance: msg)
43
- end
44
-
45
- def worker_uniqueness(msg)
46
- return nil if Compat::Sidekiq.is_activejob_job?(msg)
47
-
48
- worker_class = msg['class'].constantize
49
- return nil unless worker_class.respond_to?(:unique_job_options)
50
-
51
- worker_class.unique_job_options
52
- end
53
- end
54
-
55
- class ClientMiddleware < CommonMiddleware
56
- include ::Sidekiq::ClientMiddleware if defined? ::Sidekiq::ClientMiddleware
57
-
58
- def call(_worker, msg, _queue, _redis_pool = nil, &blk)
59
- ctx = lock_context(msg)
60
- return blk.call unless ctx
61
- msg['uniqueness_cache_data'] = ctx.cache_data.stringify_keys
62
- ctx.handle_lifecycle!(:enqueue, &blk)
63
- end
64
- end
65
-
66
- class ServerMiddleware < CommonMiddleware
67
- include ::Sidekiq::ServerMiddleware if defined? ::Sidekiq::ServerMiddleware
68
-
69
- def call(_worker, msg, _queue, &blk)
70
- ctx = lock_context(msg)
71
- return blk.call unless ctx
72
- ctx.handle_lifecycle!(:perform, &blk)
73
- end
74
- end
75
-
76
- def self.is_activejob_job?(msg)
77
- return false unless defined?(::ActiveJob)
78
-
79
- msg['class'] == 'ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper' && (msg['wrapped'].to_s).constantize < Compat::ActiveJob::UniqueJobExtension
80
- end
81
-
82
- def self.validate_middleware_order(chain, order)
83
- chain_classes = chain.entries.map(&:klass)
84
- filtered = chain_classes.select { |klass| order.include?(klass) }
85
- raise "Middleware chain does not contain all required middleware: #{order - filtered}" unless order.all? { |klass| filtered.include?(klass) }
86
- raise "Middleware must be in order: #{order.inspect}" if filtered != order
87
- end
88
-
89
- def self.sidekiq_middleware(placement, &blk)
90
- install_middleware = ->(config) do
91
- config.send("#{placement}_middleware") do |chain|
92
- blk.call(chain)
93
- end
94
- end
95
-
96
- ::Sidekiq.configure_client(&install_middleware) if placement == :client
97
- ::Sidekiq.configure_server(&install_middleware)
98
- end
99
-
100
- def self.validate_middleware_placement!
101
- sidekiq_middleware(:client) do |chain|
102
- # Unique middleware must come _before_ the Batch middleware so that the uniqueness middleware can wrap the job in a batch
103
- validate_middleware_order(chain, [
104
- CanvasSync::JobUniqueness::Compat::Sidekiq::ClientMiddleware,
105
- CanvasSync::JobBatches::Compat::Sidekiq::ClientMiddleware,
106
- ])
107
- end
108
-
109
- sidekiq_middleware(:server) do |chain|
110
- # Unique middleware must com _after_ the Batch middleware so that the Batch is loaded before reaching the uniqueness middleware
111
- validate_middleware_order(chain, [
112
- CanvasSync::JobBatches::Compat::Sidekiq::ServerMiddleware,
113
- CanvasSync::JobUniqueness::Compat::Sidekiq::ServerMiddleware,
114
- ])
115
- end
116
- end
117
-
118
- def self.configure
119
- sidekiq_middleware(:client) do |chain|
120
- chain.insert_before CanvasSync::JobBatches::Compat::Sidekiq::ClientMiddleware, Compat::Sidekiq::ClientMiddleware
121
- end
122
-
123
- sidekiq_middleware(:server) do |chain|
124
- chain.insert_after CanvasSync::JobBatches::Compat::Sidekiq::ServerMiddleware, Compat::Sidekiq::ServerMiddleware
125
- end
126
-
127
- ::Sidekiq::Worker.extend(ActiveSupport::Concern) unless ::Sidekiq::Worker < ActiveSupport::Concern
128
-
129
- ::Sidekiq::Worker.send(:include, Compat::Sidekiq::WorkerExtension)
130
- end
131
- end
132
- end
133
- end
134
-
135
- # require_relative 'sidekiq/web'
@@ -1,20 +0,0 @@
1
-
2
- module CanvasSync::JobUniqueness
3
- module Compat
4
- def self.load_compat(name)
5
- name = name.to_s
6
- begin
7
- require name
8
- rescue LoadError
9
- end
10
-
11
- if name.classify.safe_constantize
12
- require_relative "./compat/#{name}"
13
- "#{self.name}::#{name.classify}".constantize.configure
14
- end
15
- end
16
-
17
- load_compat(:active_job)
18
- load_compat(:sidekiq)
19
- end
20
- end
@@ -1,25 +0,0 @@
1
- module CanvasSync::JobUniqueness
2
- class Configuration
3
- include ActiveSupport::Configurable
4
-
5
- config_accessor(:lock_ttl) { 14.days.to_i }
6
- config_accessor(:lock_prefix) { 'uniquejob' }
7
- config_accessor(:on_conflict) { :raise }
8
-
9
- config_accessor(:lock_strategies) { {} }
10
- config_accessor(:conflict_strategies) { {} }
11
-
12
- config_accessor(:redis_version) { nil }
13
- def on_conflict=(action)
14
- validate_on_conflict_action!(action)
15
-
16
- config.on_conflict = action
17
- end
18
-
19
- def validate_on_conflict_action!(action)
20
- return if action.nil? || %i[log raise].include?(action) || action.respond_to?(:call)
21
-
22
- raise ActiveJob::Uniqueness::InvalidOnConflictAction, "Unexpected '#{action}' action on conflict"
23
- end
24
- end
25
- end
@@ -1,47 +0,0 @@
1
-
2
- require 'canvas_sync/job_uniqueness/lock_context'
3
- require 'canvas_sync/job_uniqueness/unique_job_common'
4
-
5
- require 'canvas_sync/job_uniqueness/strategy'
6
- require 'canvas_sync/job_uniqueness/on_conflict'
7
- require 'canvas_sync/job_uniqueness/compat'
8
-
9
- module CanvasSync::JobUniqueness
10
- extend ActiveSupport::Autoload
11
-
12
- autoload :Locksmith
13
- autoload :Configuration
14
-
15
- class Conflict < StandardError
16
- attr_reader :lock_context
17
-
18
- def initialize(lock_context)
19
- super()
20
- @lock_context = lock_context
21
- end
22
- end
23
-
24
- class CouldNotLockError < StandardError
25
- attr_reader :lock_context, :source
26
-
27
- def initialize(lock_context, source:)
28
- super()
29
- @lock_context = lock_context
30
- @source = source
31
- end
32
- end
33
-
34
- class << self
35
- def configure
36
- yield config
37
- end
38
-
39
- def config
40
- @config ||= Configuration.new
41
- end
42
-
43
- def logger
44
- CanvasSync.logger
45
- end
46
- end
47
- end