canvas_sync 0.16.4 → 0.21.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +235 -151
- data/app/controllers/{api → canvas_sync/api}/v1/health_check_controller.rb +1 -1
- data/app/controllers/canvas_sync/api/v1/live_events_controller.rb +122 -0
- data/app/models/canvas_sync/sync_batch.rb +5 -0
- data/config/initializers/apartment.rb +10 -1
- data/config/routes.rb +7 -0
- data/db/migrate/20170915210836_create_canvas_sync_job_log.rb +12 -31
- data/db/migrate/20180725155729_add_job_id_to_canvas_sync_job_logs.rb +4 -13
- data/db/migrate/20190916154829_add_fork_count_to_canvas_sync_job_logs.rb +3 -11
- data/db/migrate/20201018210836_create_canvas_sync_sync_batches.rb +11 -0
- data/db/migrate/20201030210836_add_full_sync_to_canvas_sync_sync_batch.rb +7 -0
- data/lib/canvas_sync/batch_processor.rb +41 -0
- data/lib/canvas_sync/concerns/ability_helper.rb +72 -0
- data/lib/canvas_sync/concerns/account/ancestry.rb +2 -0
- data/lib/canvas_sync/concerns/account/base.rb +15 -0
- data/lib/canvas_sync/concerns/api_syncable.rb +17 -10
- data/lib/canvas_sync/concerns/live_event_sync.rb +46 -0
- data/lib/canvas_sync/concerns/role/base.rb +57 -0
- data/lib/canvas_sync/concerns/sync_mapping.rb +120 -0
- data/lib/canvas_sync/engine.rb +80 -0
- data/lib/canvas_sync/generators/install_generator.rb +1 -0
- data/lib/canvas_sync/generators/install_live_events_generator.rb +0 -1
- data/lib/canvas_sync/generators/templates/migrations/create_content_migrations.rb +24 -0
- data/lib/canvas_sync/generators/templates/migrations/create_course_nicknames.rb +17 -0
- data/lib/canvas_sync/generators/templates/migrations/create_grading_period_groups.rb +18 -0
- data/lib/canvas_sync/generators/templates/migrations/create_grading_periods.rb +22 -0
- data/lib/canvas_sync/generators/templates/migrations/create_learning_outcome_results.rb +46 -0
- data/lib/canvas_sync/generators/templates/migrations/create_learning_outcomes.rb +30 -0
- data/lib/canvas_sync/generators/templates/migrations/create_rubric_assessments.rb +31 -0
- data/lib/canvas_sync/generators/templates/migrations/create_rubric_associations.rb +36 -0
- data/lib/canvas_sync/generators/templates/migrations/create_rubrics.rb +38 -0
- data/lib/canvas_sync/generators/templates/migrations/create_user_observers.rb +17 -0
- data/lib/canvas_sync/generators/templates/migrations/create_users.rb +0 -1
- data/lib/canvas_sync/generators/templates/models/account.rb +3 -0
- data/lib/canvas_sync/generators/templates/models/admin.rb +2 -0
- data/lib/canvas_sync/generators/templates/models/assignment.rb +3 -0
- data/lib/canvas_sync/generators/templates/models/assignment_group.rb +3 -0
- data/lib/canvas_sync/generators/templates/models/content_migration.rb +12 -0
- data/lib/canvas_sync/generators/templates/models/context_module.rb +3 -0
- data/lib/canvas_sync/generators/templates/models/context_module_item.rb +3 -0
- data/lib/canvas_sync/generators/templates/models/course.rb +11 -0
- data/lib/canvas_sync/generators/templates/models/course_nickname.rb +13 -0
- data/lib/canvas_sync/generators/templates/models/enrollment.rb +14 -0
- data/lib/canvas_sync/generators/templates/models/grading_period.rb +10 -0
- data/lib/canvas_sync/generators/templates/models/grading_period_group.rb +9 -0
- data/lib/canvas_sync/generators/templates/models/group.rb +2 -0
- data/lib/canvas_sync/generators/templates/models/group_membership.rb +2 -0
- data/lib/canvas_sync/generators/templates/models/learning_outcome.rb +24 -0
- data/lib/canvas_sync/generators/templates/models/learning_outcome_result.rb +48 -0
- data/lib/canvas_sync/generators/templates/models/pseudonym.rb +2 -0
- data/lib/canvas_sync/generators/templates/models/role.rb +2 -0
- data/lib/canvas_sync/generators/templates/models/rubric.rb +29 -0
- data/lib/canvas_sync/generators/templates/models/rubric_assessment.rb +17 -0
- data/lib/canvas_sync/generators/templates/models/rubric_association.rb +14 -0
- data/lib/canvas_sync/generators/templates/models/section.rb +9 -0
- data/lib/canvas_sync/generators/templates/models/submission.rb +3 -0
- data/lib/canvas_sync/generators/templates/models/term.rb +3 -0
- data/lib/canvas_sync/generators/templates/models/user.rb +11 -0
- data/lib/canvas_sync/generators/templates/models/user_observer.rb +13 -0
- data/lib/canvas_sync/generators/templates/services/live_events/assignment_event.rb +1 -1
- data/lib/canvas_sync/generators/templates/services/live_events/assignment_group_event.rb +1 -1
- data/lib/canvas_sync/generators/templates/services/live_events/course_event.rb +1 -3
- data/lib/canvas_sync/generators/templates/services/live_events/course_section_event.rb +1 -1
- data/lib/canvas_sync/generators/templates/services/live_events/enrollment_event.rb +1 -1
- data/lib/canvas_sync/generators/templates/services/live_events/grade_event.rb +1 -1
- data/lib/canvas_sync/generators/templates/services/live_events/module_event.rb +1 -1
- data/lib/canvas_sync/generators/templates/services/live_events/module_item_event.rb +1 -1
- data/lib/canvas_sync/generators/templates/services/live_events/submission_event.rb +1 -1
- data/lib/canvas_sync/generators/templates/services/live_events/syllabus_event.rb +1 -1
- data/lib/canvas_sync/generators/templates/services/live_events/user_event.rb +1 -3
- data/lib/canvas_sync/importers/bulk_importer.rb +138 -31
- data/lib/canvas_sync/job.rb +7 -5
- data/lib/canvas_sync/job_batches/active_job.rb +108 -0
- data/lib/canvas_sync/job_batches/batch.rb +543 -0
- data/lib/canvas_sync/job_batches/callback.rb +149 -0
- data/lib/canvas_sync/job_batches/chain_builder.rb +249 -0
- data/lib/canvas_sync/job_batches/context_hash.rb +159 -0
- data/lib/canvas_sync/job_batches/hier_batch_ids.lua +25 -0
- data/lib/canvas_sync/job_batches/jobs/base_job.rb +7 -0
- data/lib/canvas_sync/job_batches/jobs/concurrent_batch_job.rb +22 -0
- data/lib/canvas_sync/job_batches/jobs/managed_batch_job.rb +170 -0
- data/lib/canvas_sync/job_batches/jobs/serial_batch_job.rb +22 -0
- data/lib/canvas_sync/job_batches/pool.rb +245 -0
- data/lib/canvas_sync/job_batches/pool_refill.lua +47 -0
- data/lib/canvas_sync/job_batches/redis_model.rb +69 -0
- data/lib/canvas_sync/job_batches/redis_script.rb +163 -0
- data/lib/canvas_sync/job_batches/schedule_callback.lua +14 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/batches_assets/css/styles.less +182 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/batches_assets/js/batch_tree.js +108 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/batches_assets/js/util.js +2 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/helpers.rb +41 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/views/_batch_tree.erb +6 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/views/_batches_table.erb +44 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/views/_common.erb +13 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/views/_jobs_table.erb +21 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/views/_pagination.erb +26 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/views/batch.erb +81 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/views/batches.erb +23 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/views/pool.erb +137 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/views/pools.erb +47 -0
- data/lib/canvas_sync/job_batches/sidekiq/web.rb +218 -0
- data/lib/canvas_sync/job_batches/sidekiq.rb +136 -0
- data/lib/canvas_sync/job_batches/status.rb +91 -0
- data/lib/canvas_sync/jobs/begin_sync_chain_job.rb +99 -0
- data/lib/canvas_sync/jobs/canvas_process_waiter.rb +41 -0
- data/lib/canvas_sync/jobs/report_checker.rb +70 -8
- data/lib/canvas_sync/jobs/report_processor_job.rb +4 -7
- data/lib/canvas_sync/jobs/report_starter.rb +34 -20
- data/lib/canvas_sync/jobs/sync_accounts_job.rb +3 -5
- data/lib/canvas_sync/jobs/sync_admins_job.rb +2 -4
- data/lib/canvas_sync/jobs/sync_assignment_groups_job.rb +2 -4
- data/lib/canvas_sync/jobs/sync_assignments_job.rb +2 -4
- data/lib/canvas_sync/jobs/sync_content_migrations_job.rb +20 -0
- data/lib/canvas_sync/jobs/sync_context_module_items_job.rb +2 -4
- data/lib/canvas_sync/jobs/sync_context_modules_job.rb +2 -4
- data/lib/canvas_sync/jobs/sync_provisioning_report_job.rb +16 -50
- data/lib/canvas_sync/jobs/sync_roles_job.rb +2 -5
- data/lib/canvas_sync/jobs/sync_rubric_assessments_job.rb +15 -0
- data/lib/canvas_sync/jobs/sync_rubric_associations_job.rb +15 -0
- data/lib/canvas_sync/jobs/sync_rubrics_job.rb +15 -0
- data/lib/canvas_sync/jobs/sync_simple_table_job.rb +11 -32
- data/lib/canvas_sync/jobs/sync_submissions_job.rb +6 -4
- data/lib/canvas_sync/jobs/sync_terms_job.rb +9 -8
- data/lib/canvas_sync/jobs/term_batches_job.rb +50 -0
- data/lib/canvas_sync/{generators/templates/services/live_events/base_event.rb → live_events/base_handler.rb} +6 -10
- data/lib/canvas_sync/live_events/process_event_job.rb +26 -0
- data/lib/canvas_sync/live_events.rb +38 -0
- data/lib/canvas_sync/misc_helper.rb +63 -0
- data/lib/canvas_sync/processors/assignment_groups_processor.rb +3 -8
- data/lib/canvas_sync/processors/assignments_processor.rb +3 -8
- data/lib/canvas_sync/processors/content_migrations_processor.rb +19 -0
- data/lib/canvas_sync/processors/context_module_items_processor.rb +3 -8
- data/lib/canvas_sync/processors/context_modules_processor.rb +3 -8
- data/lib/canvas_sync/processors/model_mappings.yml +420 -0
- data/lib/canvas_sync/processors/normal_processor.rb +3 -3
- data/lib/canvas_sync/processors/provisioning_report_processor.rb +42 -55
- data/lib/canvas_sync/processors/report_processor.rb +15 -9
- data/lib/canvas_sync/processors/rubric_assessments_processor.rb +19 -0
- data/lib/canvas_sync/processors/rubric_associations_processor.rb +19 -0
- data/lib/canvas_sync/processors/rubrics_processor.rb +19 -0
- data/lib/canvas_sync/processors/submissions_processor.rb +3 -8
- data/lib/canvas_sync/record.rb +103 -0
- data/lib/canvas_sync/version.rb +1 -1
- data/lib/canvas_sync.rb +124 -125
- data/spec/canvas_sync/canvas_sync_spec.rb +224 -155
- data/spec/canvas_sync/jobs/canvas_process_waiter_spec.rb +34 -0
- data/spec/canvas_sync/jobs/job_spec.rb +9 -17
- data/spec/canvas_sync/jobs/report_checker_spec.rb +1 -3
- data/spec/canvas_sync/jobs/report_processor_job_spec.rb +0 -3
- data/spec/canvas_sync/jobs/report_starter_spec.rb +19 -28
- data/spec/canvas_sync/jobs/sync_admins_job_spec.rb +1 -4
- data/spec/canvas_sync/jobs/sync_assignment_groups_job_spec.rb +2 -1
- data/spec/canvas_sync/jobs/sync_assignments_job_spec.rb +3 -2
- data/spec/canvas_sync/jobs/sync_content_migrations_job_spec.rb +30 -0
- data/spec/canvas_sync/jobs/sync_context_module_items_job_spec.rb +3 -2
- data/spec/canvas_sync/jobs/sync_context_modules_job_spec.rb +3 -2
- data/spec/canvas_sync/jobs/sync_provisioning_report_job_spec.rb +7 -41
- data/spec/canvas_sync/jobs/sync_roles_job_spec.rb +1 -4
- data/spec/canvas_sync/jobs/sync_simple_table_job_spec.rb +5 -12
- data/spec/canvas_sync/jobs/sync_submissions_job_spec.rb +8 -2
- data/spec/canvas_sync/jobs/sync_terms_job_spec.rb +1 -4
- data/spec/canvas_sync/live_events/live_event_sync_spec.rb +27 -0
- data/spec/canvas_sync/live_events/live_events_controller_spec.rb +54 -0
- data/spec/canvas_sync/live_events/process_event_job_spec.rb +38 -0
- data/spec/canvas_sync/misc_helper_spec.rb +58 -0
- data/spec/canvas_sync/models/assignment_spec.rb +1 -1
- data/spec/canvas_sync/processors/content_migrations_processor_spec.rb +13 -0
- data/spec/canvas_sync/processors/provisioning_report_processor_spec.rb +101 -1
- data/spec/canvas_sync/processors/rubric_assessments_spec.rb +16 -0
- data/spec/canvas_sync/processors/rubric_associations_spec.rb +16 -0
- data/spec/canvas_sync/processors/rubrics_processor_spec.rb +17 -0
- data/spec/dummy/app/models/account.rb +6 -0
- data/spec/dummy/app/models/admin.rb +2 -0
- data/spec/dummy/app/models/assignment.rb +3 -0
- data/spec/dummy/app/models/assignment_group.rb +3 -0
- data/spec/dummy/app/models/content_migration.rb +18 -0
- data/spec/dummy/app/models/context_module.rb +3 -0
- data/spec/dummy/app/models/context_module_item.rb +3 -0
- data/spec/dummy/app/models/course.rb +11 -0
- data/spec/dummy/app/models/course_nickname.rb +19 -0
- data/spec/dummy/app/models/enrollment.rb +14 -0
- data/spec/dummy/app/models/grading_period.rb +16 -0
- data/spec/dummy/app/models/grading_period_group.rb +15 -0
- data/spec/dummy/app/models/group.rb +2 -0
- data/spec/dummy/app/models/group_membership.rb +2 -0
- data/spec/dummy/app/models/learning_outcome.rb +30 -0
- data/spec/dummy/app/models/learning_outcome_result.rb +54 -0
- data/spec/dummy/app/models/pseudonym.rb +16 -0
- data/spec/dummy/app/models/role.rb +2 -0
- data/spec/dummy/app/models/rubric.rb +35 -0
- data/spec/dummy/app/models/rubric_assessment.rb +22 -0
- data/spec/dummy/app/models/rubric_association.rb +20 -0
- data/spec/dummy/app/models/section.rb +9 -0
- data/spec/dummy/app/models/submission.rb +4 -0
- data/spec/dummy/app/models/term.rb +3 -0
- data/spec/dummy/app/models/user.rb +11 -0
- data/spec/dummy/app/models/user_observer.rb +19 -0
- data/spec/dummy/app/services/live_events/assignment_event.rb +1 -1
- data/spec/dummy/app/services/live_events/course_event.rb +1 -3
- data/spec/dummy/app/services/live_events/course_section_event.rb +1 -1
- data/spec/dummy/app/services/live_events/enrollment_event.rb +1 -1
- data/spec/dummy/app/services/live_events/grade_event.rb +1 -1
- data/spec/dummy/app/services/live_events/module_event.rb +1 -1
- data/spec/dummy/app/services/live_events/module_item_event.rb +1 -1
- data/spec/dummy/app/services/live_events/submission_event.rb +1 -1
- data/spec/dummy/app/services/live_events/syllabus_event.rb +1 -1
- data/spec/dummy/app/services/live_events/user_event.rb +1 -3
- data/spec/dummy/config/environments/test.rb +2 -0
- data/spec/dummy/config/routes.rb +1 -0
- data/spec/dummy/db/migrate/20201016181346_create_pseudonyms.rb +24 -0
- data/spec/dummy/db/migrate/20210907233329_create_user_observers.rb +23 -0
- data/spec/dummy/db/migrate/20210907233330_create_grading_periods.rb +28 -0
- data/spec/dummy/db/migrate/20211001184920_create_grading_period_groups.rb +24 -0
- data/spec/dummy/db/migrate/20220308072643_create_content_migrations.rb +30 -0
- data/spec/dummy/db/migrate/20220712210559_create_learning_outcomes.rb +36 -0
- data/spec/dummy/db/migrate/{20190702203620_create_users.rb → 20220926221926_create_users.rb} +0 -1
- data/spec/dummy/db/migrate/20240408223326_create_course_nicknames.rb +23 -0
- data/spec/dummy/db/migrate/20240509105100_create_rubrics.rb +44 -0
- data/spec/dummy/db/migrate/20240510094100_create_rubric_associations.rb +42 -0
- data/spec/dummy/db/migrate/20240510101100_create_rubric_assessments.rb +37 -0
- data/spec/dummy/db/migrate/20240523101010_create_learning_outcome_results.rb +52 -0
- data/spec/dummy/db/schema.rb +244 -5
- data/spec/factories/user_factory.rb +0 -1
- data/spec/job_batching/active_job_spec.rb +107 -0
- data/spec/job_batching/batch_spec.rb +489 -0
- data/spec/job_batching/callback_spec.rb +38 -0
- data/spec/job_batching/context_hash_spec.rb +54 -0
- data/spec/job_batching/flow_spec.rb +82 -0
- data/spec/job_batching/integration/fail_then_succeed.rb +42 -0
- data/spec/job_batching/integration/integration.rb +57 -0
- data/spec/job_batching/integration/nested.rb +88 -0
- data/spec/job_batching/integration/simple.rb +47 -0
- data/spec/job_batching/integration/workflow.rb +134 -0
- data/spec/job_batching/integration_helper.rb +50 -0
- data/spec/job_batching/pool_spec.rb +161 -0
- data/spec/job_batching/sidekiq_spec.rb +125 -0
- data/spec/job_batching/status_spec.rb +76 -0
- data/spec/job_batching/support/base_job.rb +14 -0
- data/spec/job_batching/support/sample_callback.rb +2 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/support/fixtures/reports/content_migrations.csv +3 -0
- data/spec/support/fixtures/reports/course_nicknames.csv +3 -0
- data/spec/support/fixtures/reports/grading_period_groups.csv +2 -0
- data/spec/support/fixtures/reports/grading_periods.csv +3 -0
- data/spec/support/fixtures/reports/learning_outcome_results.csv +3 -0
- data/spec/support/fixtures/reports/learning_outcomes.csv +3 -0
- data/spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv +3 -0
- data/spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv +4 -0
- data/spec/support/fixtures/reports/rubric_assessments.csv +3 -0
- data/spec/support/fixtures/reports/rubric_associations.csv +3 -0
- data/spec/support/fixtures/reports/rubrics.csv +3 -0
- data/spec/support/fixtures/reports/user_observers.csv +3 -0
- data/spec/support/fixtures/reports/users.csv +3 -2
- data/spec/support/fixtures/reports/xlist.csv +1 -1
- metadata +329 -27
- data/app/controllers/api/v1/live_events_controller.rb +0 -18
- data/lib/canvas_sync/job_chain.rb +0 -57
- data/lib/canvas_sync/jobs/fork_gather.rb +0 -59
- data/spec/canvas_sync/jobs/fork_gather_spec.rb +0 -73
@@ -0,0 +1,137 @@
|
|
1
|
+
<h3><%= t('Pool') %></h3>
|
2
|
+
|
3
|
+
<div class="table_container">
|
4
|
+
<table class="table table-striped table-bordered table-white table-hover">
|
5
|
+
<tbody>
|
6
|
+
<tr>
|
7
|
+
<th scope=row><%= t('PID') %></td>
|
8
|
+
<td><%= @pool.pid %></td>
|
9
|
+
</tr>
|
10
|
+
<tr>
|
11
|
+
<th scope=row><%= t('Created') %></td>
|
12
|
+
<td><%= safe_relative_time(@pool.created_at.to_f) %></td>
|
13
|
+
</tr>
|
14
|
+
<tr>
|
15
|
+
<th scope=row><%= t('Description') %></td>
|
16
|
+
<td><%= @pool.description %></td>
|
17
|
+
</tr>
|
18
|
+
<tr>
|
19
|
+
<th scope=row><%= t('Type') %></td>
|
20
|
+
<td><%= @pool.order.to_s.upcase %></td>
|
21
|
+
</tr>
|
22
|
+
<tr>
|
23
|
+
<th scope=row><%= t('Concurrency') %></td>
|
24
|
+
<td><%= @pool.concurrency %></td>
|
25
|
+
</tr>
|
26
|
+
<tr>
|
27
|
+
<th scope=row><%= t('Utilization') %></td>
|
28
|
+
<td><%= @pool.active_count %></td>
|
29
|
+
</tr>
|
30
|
+
<tr>
|
31
|
+
<th scope=row><%= t('Pending Tasks') %></td>
|
32
|
+
<td><%= @pool.pending_count %></td>
|
33
|
+
</tr>
|
34
|
+
<tr>
|
35
|
+
<th scope=row><%= t('Returned Tasks') %></td>
|
36
|
+
<td><%= @pool.complete_count %></td>
|
37
|
+
</tr>
|
38
|
+
</tbody>
|
39
|
+
</table>
|
40
|
+
</div>
|
41
|
+
|
42
|
+
<%# Queued/Active Tasks %>
|
43
|
+
<header class="row">
|
44
|
+
<div class="col-sm-5">
|
45
|
+
<h3>
|
46
|
+
<%= t('Queued/Active Tasks') %>
|
47
|
+
</h3>
|
48
|
+
</div>
|
49
|
+
</header>
|
50
|
+
|
51
|
+
<% if @active_tasks.any? %>
|
52
|
+
<div class="table_container">
|
53
|
+
<table class="table table-striped table-bordered table-hover">
|
54
|
+
<thead>
|
55
|
+
<tr>
|
56
|
+
<th><%= t('Wrapper Batch BID') %></th>
|
57
|
+
<th><%= t('Job Class') %></th>
|
58
|
+
<th><%= t('Parameters') %></th>
|
59
|
+
</tr>
|
60
|
+
</thead>
|
61
|
+
|
62
|
+
<% @active_tasks.each do |job_desc| %>
|
63
|
+
<tr>
|
64
|
+
<td><a href="<%= root_path %>batches/<%= job_desc['pool_wrapper_batch'] %>"><%= job_desc['pool_wrapper_batch'] %></a></td>
|
65
|
+
<td><%= job_desc['job'] %></td>
|
66
|
+
<td>
|
67
|
+
<code class="code-wrap">
|
68
|
+
<div class="args-extended">
|
69
|
+
<%= job_desc['args']&.to_json %>
|
70
|
+
<%= job_desc['kwargs']&.to_json %>
|
71
|
+
</div>
|
72
|
+
</code>
|
73
|
+
</td>
|
74
|
+
</tr>
|
75
|
+
<% end %>
|
76
|
+
</table>
|
77
|
+
</div>
|
78
|
+
<% end %>
|
79
|
+
|
80
|
+
<%# Pending Tasks %>
|
81
|
+
<header class="row">
|
82
|
+
<div class="col-sm-5">
|
83
|
+
<h3>
|
84
|
+
<%= t('Pending Tasks') %>
|
85
|
+
</h3>
|
86
|
+
</div>
|
87
|
+
<%
|
88
|
+
@current_page = @current_jobs_page
|
89
|
+
@total_size = @total_jobs_size
|
90
|
+
%>
|
91
|
+
<% if @jobs.any? && @total_size > @count.to_i %>
|
92
|
+
<div class="col-sm-4">
|
93
|
+
<%= erb get_template(:_pagination), locals: { url: "#{root_path}pools/#{@pool.pid}", page_key: :job_page } %>
|
94
|
+
</div>
|
95
|
+
<% end %>
|
96
|
+
</header>
|
97
|
+
|
98
|
+
<% if @jobs.any? %>
|
99
|
+
<div class="table_container">
|
100
|
+
<table class="table table-striped table-bordered table-hover">
|
101
|
+
<thead>
|
102
|
+
<tr>
|
103
|
+
<th><%= t('Job Class') %></th>
|
104
|
+
<th><%= t('Parameters') %></th>
|
105
|
+
<th><%= t('Wrapper Batch BID') %></th>
|
106
|
+
<% if @pool.order == 'priority' %>
|
107
|
+
<th><%= t('Priority') %></th>
|
108
|
+
<% end %>
|
109
|
+
</tr>
|
110
|
+
</thead>
|
111
|
+
|
112
|
+
<% @jobs.each do |job_desc| %>
|
113
|
+
<tr>
|
114
|
+
<td><%= job_desc['job'] %></td>
|
115
|
+
<td>
|
116
|
+
<code class="code-wrap">
|
117
|
+
<div class="args-extended">
|
118
|
+
<%= job_desc['args']&.to_json %>
|
119
|
+
<%= job_desc['kwargs']&.to_json %>
|
120
|
+
</div>
|
121
|
+
</code>
|
122
|
+
</td>
|
123
|
+
<td><a href="<%= root_path %>batches/<%= job_desc['pool_wrapper_batch'] %>"><%= job_desc['pool_wrapper_batch'] %></a></td>
|
124
|
+
<% if @pool.order == 'priority' %>
|
125
|
+
<td><%= job_desc['priority'] %></td>
|
126
|
+
<% end %>
|
127
|
+
</tr>
|
128
|
+
<% end %>
|
129
|
+
</table>
|
130
|
+
</div>
|
131
|
+
<% end %>
|
132
|
+
|
133
|
+
<form class="form-horizontal" action="<%= root_path %>pools/<%= @pool.pid %>" method="post">
|
134
|
+
<%= csrf_tag %>
|
135
|
+
<a class="btn btn-default" href="<%= root_path %>pools"><%= t('GoBack') %></a>
|
136
|
+
<input class="btn btn-danger" type="submit" name="delete" value="<%= t('Delete') %>" data-confirm="<%= t('AreYouSure') %>" />
|
137
|
+
</form>
|
@@ -0,0 +1,47 @@
|
|
1
|
+
<header class="row">
|
2
|
+
<div class="col-sm-5">
|
3
|
+
<h3>
|
4
|
+
<%= t('Pools') %>
|
5
|
+
</h3>
|
6
|
+
</div>
|
7
|
+
<% if @pools.any? && @total_size > @count.to_i %>
|
8
|
+
<div class="col-sm-4">
|
9
|
+
<%= erb get_template(:_pagination), locals: { url: "#{root_path}pools" } %>
|
10
|
+
</div>
|
11
|
+
<% end %>
|
12
|
+
</header>
|
13
|
+
|
14
|
+
<% if @pools.any? %>
|
15
|
+
<div class="table_container">
|
16
|
+
<table class="table table-striped table-bordered table-hover">
|
17
|
+
<thead>
|
18
|
+
<tr>
|
19
|
+
<th><%= t('Created') %></th>
|
20
|
+
<th><%= t('PID') %></th>
|
21
|
+
<th><%= t('Description') %></th>
|
22
|
+
<th><%= t('Type') %></th>
|
23
|
+
<th><%= t('Concurrency') %></th>
|
24
|
+
<th><%= t('Utilization') %></th>
|
25
|
+
<th><%= t('Pending Tasks') %></th>
|
26
|
+
</tr>
|
27
|
+
</thead>
|
28
|
+
|
29
|
+
<% @pools.each do |pool| %>
|
30
|
+
<tr>
|
31
|
+
<td><%= safe_relative_time(pool.created_at.to_f) %></th>
|
32
|
+
<td><a href="<%= root_path %>pools/<%= pool.pid %>"><%= pool.pid %></a></td>
|
33
|
+
<td><%= pool.description %></th>
|
34
|
+
<td><%= pool.order.to_s.upcase %></th>
|
35
|
+
<td><%= pool.concurrency %></th>
|
36
|
+
<td><%= pool.active_count %></th>
|
37
|
+
<td><%= pool.pending_count %></th>
|
38
|
+
</tr>
|
39
|
+
<% end %>
|
40
|
+
</table>
|
41
|
+
</div>
|
42
|
+
<% end %>
|
43
|
+
|
44
|
+
<form action="<%= root_path %>pools/all" method="post">
|
45
|
+
<%= csrf_tag %>
|
46
|
+
<input class="btn btn-danger btn-xs pull-right flip" type="submit" name="delete" value="<%= t('DeleteAll') %>" data-confirm="<%= t('AreYouSure') %>" />
|
47
|
+
</form>
|
@@ -0,0 +1,218 @@
|
|
1
|
+
|
2
|
+
begin
|
3
|
+
require "sidekiq/web"
|
4
|
+
rescue LoadError
|
5
|
+
# client-only usage
|
6
|
+
end
|
7
|
+
|
8
|
+
require_relative "web/helpers"
|
9
|
+
|
10
|
+
module CanvasSync::JobBatches::Sidekiq
|
11
|
+
module Web
|
12
|
+
DEV_MODE = (defined?(Rails) && !Rails.env.production?) || !!ENV["SIDEKIQ_WEB_TESTING"]
|
13
|
+
Sidekiq::WebHelpers::SAFE_QPARAMS << 'all_batches'
|
14
|
+
Sidekiq::WebHelpers::SAFE_QPARAMS << 'count'
|
15
|
+
|
16
|
+
def self.registered(app) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
17
|
+
app.helpers do
|
18
|
+
include Web::Helpers
|
19
|
+
|
20
|
+
def dev_mode?
|
21
|
+
DEV_MODE
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# =============== BATCHES =============== #
|
26
|
+
|
27
|
+
app.get "/batches" do
|
28
|
+
@count = (params['count'] || 25).to_i
|
29
|
+
|
30
|
+
source_key = params['all_batches'] ? "batches" : "BID-ROOT-bids"
|
31
|
+
@current_page, @total_size, @batches = page(source_key, params['page'], @count)
|
32
|
+
@batches = @batches.map {|b, score| CanvasSync::JobBatches::Batch.new(b) }
|
33
|
+
|
34
|
+
erb(get_template(:batches))
|
35
|
+
end
|
36
|
+
|
37
|
+
app.get "/batches/:bid" do
|
38
|
+
@bid = params[:bid]
|
39
|
+
@batch = CanvasSync::JobBatches::Batch.new(@bid)
|
40
|
+
|
41
|
+
@tree_data = tree_data(@bid)
|
42
|
+
|
43
|
+
@count = (params['count'] || 25).to_i
|
44
|
+
@current_batches_page, @total_batches_size, @sub_batches = page("BID-#{@batch.bid}-bids", params['batch_page'], @count)
|
45
|
+
@sub_batches = @sub_batches.map {|b, score| CanvasSync::JobBatches::Batch.new(b) }
|
46
|
+
|
47
|
+
@current_jobs_page, @total_jobs_size, @jobs = page("BID-#{@batch.bid}-jids", params['job_page'], @count)
|
48
|
+
@jobs = @jobs.map do |jid, score|
|
49
|
+
{ jid: jid, }
|
50
|
+
end
|
51
|
+
|
52
|
+
erb(get_template(:batch))
|
53
|
+
end
|
54
|
+
|
55
|
+
app.get "/batches/:bid/tree" do
|
56
|
+
@bid = params[:bid]
|
57
|
+
|
58
|
+
json(tree_data(@bid, slice: params[:slice]))
|
59
|
+
end
|
60
|
+
|
61
|
+
app.helpers do
|
62
|
+
def tree_data(root_bid, slice: nil)
|
63
|
+
tree_bids = CanvasSync::JobBatches::Batch.bid_hierarchy(root_bid, slice: slice)
|
64
|
+
|
65
|
+
CanvasSync::JobBatches::Batch.redis do |r|
|
66
|
+
layer_data = ->(layer, parent = nil) {
|
67
|
+
bid = layer[0]
|
68
|
+
batch = CanvasSync::JobBatches::Batch.new(bid)
|
69
|
+
|
70
|
+
jobs_total = r.hget("BID-#{bid}", "job_count").to_i
|
71
|
+
jobs_pending = r.hget("BID-#{bid}", 'pending').to_i
|
72
|
+
jobs_failed = r.scard("BID-#{bid}-failed").to_i
|
73
|
+
jobs_dead = r.scard("BID-#{bid}-dead").to_i
|
74
|
+
jobs_success = jobs_total - jobs_pending
|
75
|
+
|
76
|
+
batches_total = r.hget("BID-#{bid}", 'children').to_i
|
77
|
+
batches_success = r.scard("BID-#{bid}-batches-success").to_i
|
78
|
+
batches_pending = batches_total - batches_success
|
79
|
+
batches_failed = r.scard("BID-#{bid}-batches-failed").to_i
|
80
|
+
|
81
|
+
status = 'in_progress'
|
82
|
+
status = 'complete' if batches_pending == batches_failed && jobs_pending == jobs_failed
|
83
|
+
status = 'success' if batches_pending == 0 && jobs_pending == 0
|
84
|
+
status = 'deleted' if bid != root_bid && !batch.parent_bid
|
85
|
+
|
86
|
+
{
|
87
|
+
bid: bid,
|
88
|
+
created_at: r.hget("BID-#{bid}", 'created_at'),
|
89
|
+
status: status,
|
90
|
+
parent_bid: parent ? parent.bid : batch.parent_bid,
|
91
|
+
description: batch.description,
|
92
|
+
jobs: {
|
93
|
+
pending_count: jobs_pending,
|
94
|
+
successful_count: jobs_success,
|
95
|
+
failed_count: jobs_failed,
|
96
|
+
dead_count: jobs_dead,
|
97
|
+
total_count: jobs_total,
|
98
|
+
# items: batches.map{|b| layer_data[b] },
|
99
|
+
},
|
100
|
+
batches: {
|
101
|
+
pending_count: batches_pending,
|
102
|
+
successful_count: batches_success,
|
103
|
+
failed_count: batches_failed,
|
104
|
+
total_count: batches_total,
|
105
|
+
items: layer[1].map{|b| layer_data[b, batch] },
|
106
|
+
},
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
data = layer_data[tree_bids]
|
111
|
+
data[:batches][:slice] = slice if slice
|
112
|
+
data
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def format_context(batch)
|
117
|
+
bits = []
|
118
|
+
own_keys = batch.context.own.keys
|
119
|
+
batch.context.flatten.each do |k,v|
|
120
|
+
added = own_keys.include? k
|
121
|
+
bits << " <span class=\"key #{added ? 'own' : 'inherited'}\">\"#{k}\": #{v.to_json},</span>"
|
122
|
+
end
|
123
|
+
bits = [
|
124
|
+
"{ // <span class=\"own\">Added</span> / <span class=\"inherited\">Inherited</span>",
|
125
|
+
*bits,
|
126
|
+
'}'
|
127
|
+
]
|
128
|
+
bits.join("\n")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
app.post "/batches/all" do
|
133
|
+
if params['delete']
|
134
|
+
index_key = CanvasSync::JobBatches::Batch::INDEX_ALL_BATCHES ? "batches" : "BID-ROOT-bids"
|
135
|
+
drain_zset(index_key) do |batches|
|
136
|
+
batches.each do |bid|
|
137
|
+
CanvasSync::JobBatches::Batch.cleanup_redis(bid)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
redirect "#{root_path}batches"
|
143
|
+
end
|
144
|
+
|
145
|
+
app.post "/batches/:bid" do
|
146
|
+
@bid = params[:bid]
|
147
|
+
@batch = CanvasSync::JobBatches::Batch.new(@bid)
|
148
|
+
|
149
|
+
if params['delete']
|
150
|
+
CanvasSync::JobBatches::Batch.delete_prematurely!(@bid)
|
151
|
+
end
|
152
|
+
|
153
|
+
redirect_with_query("#{root_path}batches")
|
154
|
+
end
|
155
|
+
|
156
|
+
# =============== POOLS =============== #
|
157
|
+
|
158
|
+
app.get "/pools" do
|
159
|
+
@count = (params['count'] || 25).to_i
|
160
|
+
@current_page, @total_size, @pools = page('pools', params['page'], @count)
|
161
|
+
@pools = @pools.map {|b, score| CanvasSync::JobBatches::Pool.new(b) }
|
162
|
+
|
163
|
+
erb(get_template(:pools))
|
164
|
+
end
|
165
|
+
|
166
|
+
app.get "/pools/:pid" do
|
167
|
+
@pid = params[:pid]
|
168
|
+
@pool = CanvasSync::JobBatches::Pool.new(@pid)
|
169
|
+
|
170
|
+
@active_tasks = @pool.active_jobs
|
171
|
+
|
172
|
+
@count = (params['count'] || 25).to_i
|
173
|
+
@current_jobs_page, @total_jobs_size, @jobs = page("POOLID-#{@pool.pid}-jobs", params['job_page'], @count)
|
174
|
+
@jobs = @jobs.map {|desc, score=nil| JSON.parse(desc)[0] }
|
175
|
+
|
176
|
+
erb(get_template(:pool))
|
177
|
+
end
|
178
|
+
|
179
|
+
app.post "/pools/all" do
|
180
|
+
if params['delete']
|
181
|
+
drain_zset('pools') do |pools|
|
182
|
+
pools.each do |pid|
|
183
|
+
CanvasSync::JobBatches::Pool.from_pid(pid).cleanup_redis
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
redirect "#{root_path}pools"
|
189
|
+
end
|
190
|
+
|
191
|
+
app.post "/pools/:pid" do
|
192
|
+
@pid = params[:pid]
|
193
|
+
@pool = CanvasSync::JobBatches::Pool.from_pid(@pid)
|
194
|
+
|
195
|
+
if params['delete']
|
196
|
+
@pool.cleanup_redis
|
197
|
+
end
|
198
|
+
|
199
|
+
redirect_with_query("#{root_path}pools")
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
if defined?(::Sidekiq::Web)
|
206
|
+
rules = []
|
207
|
+
rules = [[:all, {"Cache-Control" => "public, max-age=86400"}]] unless CanvasSync::JobBatches::Sidekiq::Web::DEV_MODE
|
208
|
+
|
209
|
+
::Sidekiq::Web.use Rack::Static, urls: ["/batches_assets"],
|
210
|
+
root: File.expand_path("#{File.dirname(__FILE__)}/web"),
|
211
|
+
cascade: true,
|
212
|
+
header_rules: rules
|
213
|
+
|
214
|
+
::Sidekiq::Web.register CanvasSync::JobBatches::Sidekiq::Web
|
215
|
+
::Sidekiq::Web.tabs["Batches"] = "batches"
|
216
|
+
::Sidekiq::Web.tabs["Pools"] = "pools"
|
217
|
+
::Sidekiq::Web.settings.locales << File.join(File.dirname(__FILE__), "locales")
|
218
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
begin
|
2
|
+
require 'sidekiq/batch'
|
3
|
+
rescue LoadError
|
4
|
+
end
|
5
|
+
|
6
|
+
module CanvasSync
|
7
|
+
module JobBatches
|
8
|
+
module Sidekiq
|
9
|
+
module WorkerExtension
|
10
|
+
def bid
|
11
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY].bid
|
12
|
+
end
|
13
|
+
|
14
|
+
def batch
|
15
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY]
|
16
|
+
end
|
17
|
+
|
18
|
+
def batch_context
|
19
|
+
batch&.context || {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid_within_batch?
|
23
|
+
batch.valid?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class SidekiqCallbackWorker
|
28
|
+
include ::Sidekiq::Worker
|
29
|
+
include WorkerExtension
|
30
|
+
include Batch::Callback::CallbackWorkerCommon
|
31
|
+
|
32
|
+
def self.enqueue_all(args, queue)
|
33
|
+
return if args.empty?
|
34
|
+
|
35
|
+
::Sidekiq::Client.push_bulk(
|
36
|
+
'class' => self,
|
37
|
+
'args' => args,
|
38
|
+
'queue' => queue
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class ClientMiddleware
|
44
|
+
def call(_worker, msg, _queue, _redis_pool = nil)
|
45
|
+
if (batch = Thread.current[CURRENT_BATCH_THREAD_KEY]) && should_handle_batch?(msg)
|
46
|
+
batch.increment_job_queue(msg['jid']) if (msg[:bid] = batch.bid)
|
47
|
+
end
|
48
|
+
yield
|
49
|
+
end
|
50
|
+
|
51
|
+
def should_handle_batch?(msg)
|
52
|
+
return false if JobBatches::Sidekiq.is_activejob_job?(msg)
|
53
|
+
true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class ServerMiddleware
|
58
|
+
def call(_worker, msg, _queue)
|
59
|
+
if (bid = msg['bid'])
|
60
|
+
prev_batch = Thread.current[CURRENT_BATCH_THREAD_KEY]
|
61
|
+
begin
|
62
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY] = Batch.new(bid)
|
63
|
+
yield
|
64
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY].save_context_changes
|
65
|
+
Batch.process_successful_job(bid, msg['jid'])
|
66
|
+
rescue
|
67
|
+
Batch.process_failed_job(bid, msg['jid'])
|
68
|
+
raise
|
69
|
+
ensure
|
70
|
+
Thread.current[CURRENT_BATCH_THREAD_KEY] = prev_batch
|
71
|
+
end
|
72
|
+
else
|
73
|
+
yield
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.is_activejob_job?(msg)
|
79
|
+
return false unless defined?(::ActiveJob)
|
80
|
+
|
81
|
+
msg['class'] == 'ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper' && (msg['wrapped'].to_s).constantize < JobBatches::ActiveJob::BatchAwareJob
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.switch_tenant(job)
|
85
|
+
if defined?(::Apartment)
|
86
|
+
::Apartment::Tenant.switch(job['apartment'] || 'public') do
|
87
|
+
yield
|
88
|
+
end
|
89
|
+
else
|
90
|
+
yield
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.configure
|
95
|
+
if defined?(::Sidekiq::Batch) && ::Sidekiq::Batch != JobBatches::Batch
|
96
|
+
print "WARNING: Detected Sidekiq Pro or sidekiq-batch. CanvasSync JobBatches may not be fully compatible!"
|
97
|
+
end
|
98
|
+
|
99
|
+
::Sidekiq.configure_client do |config|
|
100
|
+
config.client_middleware do |chain|
|
101
|
+
chain.remove ::Sidekiq::Batch::Middleware::ClientMiddleware if defined?(::Sidekiq::Batch::Middleware::ClientMiddleware)
|
102
|
+
chain.add JobBatches::Sidekiq::ClientMiddleware
|
103
|
+
end
|
104
|
+
end
|
105
|
+
::Sidekiq.configure_server do |config|
|
106
|
+
config.client_middleware do |chain|
|
107
|
+
chain.remove ::Sidekiq::Batch::Middleware::ClientMiddleware if defined?(::Sidekiq::Batch::Middleware::ClientMiddleware)
|
108
|
+
chain.add JobBatches::Sidekiq::ClientMiddleware
|
109
|
+
end
|
110
|
+
|
111
|
+
config.server_middleware do |chain|
|
112
|
+
chain.remove ::Sidekiq::Batch::Middleware::ServerMiddleware if defined?(::Sidekiq::Batch::Middleware::ServerMiddleware)
|
113
|
+
chain.add JobBatches::Sidekiq::ServerMiddleware
|
114
|
+
end
|
115
|
+
|
116
|
+
config.death_handlers << ->(job, ex) do
|
117
|
+
switch_tenant(job) do
|
118
|
+
if is_activejob_job?(job)
|
119
|
+
JobBatches::ActiveJob.handle_job_death(job["args"][0], ex)
|
120
|
+
elsif job['bid'].present?
|
121
|
+
::Sidekiq::Batch.process_dead_job(job['bid'], job['jid'])
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
::Sidekiq.const_set(:Batch, CanvasSync::JobBatches::Batch)
|
127
|
+
# This alias helps apartment-sidekiq set itself up correctly
|
128
|
+
::Sidekiq::Batch.const_set(:Server, CanvasSync::JobBatches::Sidekiq::ServerMiddleware)
|
129
|
+
::Sidekiq::Worker.send(:include, JobBatches::Sidekiq::WorkerExtension)
|
130
|
+
Batch::Callback.worker_class = SidekiqCallbackWorker
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
require_relative 'sidekiq/web'
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module CanvasSync
|
2
|
+
module JobBatches
|
3
|
+
class Batch
|
4
|
+
class Status
|
5
|
+
attr_reader :bid
|
6
|
+
|
7
|
+
def initialize(bid)
|
8
|
+
bid = bid.bid if bid.is_a?(Batch)
|
9
|
+
@bid = bid
|
10
|
+
end
|
11
|
+
|
12
|
+
def join
|
13
|
+
raise "Not supported"
|
14
|
+
end
|
15
|
+
|
16
|
+
def pending
|
17
|
+
Batch.redis { |r| r.hget("BID-#{bid}", 'pending') }.to_i
|
18
|
+
end
|
19
|
+
|
20
|
+
def failures
|
21
|
+
Batch.redis { |r| r.scard("BID-#{bid}-failed") }.to_i
|
22
|
+
end
|
23
|
+
|
24
|
+
def dead
|
25
|
+
Batch.redis { |r| r.scard("BID-#{bid}-dead") }.to_i
|
26
|
+
end
|
27
|
+
|
28
|
+
def completed_count
|
29
|
+
job_count - pending
|
30
|
+
end
|
31
|
+
|
32
|
+
def job_count
|
33
|
+
Batch.redis { |r| r.hget("BID-#{bid}", "job_count") }.to_i
|
34
|
+
end
|
35
|
+
|
36
|
+
def created_at
|
37
|
+
Batch.redis { |r| r.hget("BID-#{bid}", 'created_at') }
|
38
|
+
end
|
39
|
+
|
40
|
+
def parent_bid
|
41
|
+
Batch.redis { |r| r.hget("BID-#{bid}", "parent_bid") }
|
42
|
+
end
|
43
|
+
|
44
|
+
def failure_info
|
45
|
+
Batch.redis { |r| r.smembers("BID-#{bid}-failed") } || []
|
46
|
+
end
|
47
|
+
|
48
|
+
def complete?
|
49
|
+
'true' == Batch.redis { |r| r.hget("BID-#{bid}", 'complete') }
|
50
|
+
end
|
51
|
+
|
52
|
+
def success?
|
53
|
+
'true' == Batch.redis { |r| r.hget("BID-#{bid}", 'success') }
|
54
|
+
end
|
55
|
+
|
56
|
+
def child_count
|
57
|
+
Batch.redis { |r| r.hget("BID-#{bid}", 'children') }.to_i
|
58
|
+
end
|
59
|
+
|
60
|
+
def completed_children_count
|
61
|
+
Batch.redis { |r| r.scard("BID-#{bid}-batches-complete") }.to_i
|
62
|
+
end
|
63
|
+
|
64
|
+
def successful_children_count
|
65
|
+
Batch.redis { |r| r.scard("BID-#{bid}-batches-success") }.to_i
|
66
|
+
end
|
67
|
+
|
68
|
+
def failed_children_count
|
69
|
+
Batch.redis { |r| r.scard("BID-#{bid}-batches-failed") }.to_i
|
70
|
+
end
|
71
|
+
|
72
|
+
def data
|
73
|
+
{
|
74
|
+
bid: bid,
|
75
|
+
failures: failures,
|
76
|
+
pending: pending,
|
77
|
+
created_at: created_at,
|
78
|
+
complete: complete?,
|
79
|
+
success: success?,
|
80
|
+
failure_info: failure_info,
|
81
|
+
parent_bid: parent_bid,
|
82
|
+
child_count: child_count,
|
83
|
+
completed_children_count: completed_children_count,
|
84
|
+
successful_children_count: successful_children_count,
|
85
|
+
failed_children_count: failed_children_count,
|
86
|
+
}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|