canvas_sync 0.17.17.beta1 → 0.17.23.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +45 -1
- data/lib/canvas_sync/concerns/sync_mapping.rb +112 -0
- data/lib/canvas_sync/generators/install_generator.rb +1 -0
- data/lib/canvas_sync/generators/templates/migrations/create_grading_period_groups.rb +22 -0
- data/lib/canvas_sync/generators/templates/migrations/create_grading_periods.rb +22 -0
- data/lib/canvas_sync/generators/templates/migrations/create_user_observers.rb +17 -0
- data/lib/canvas_sync/generators/templates/models/grading_period.rb +8 -0
- data/lib/canvas_sync/generators/templates/models/grading_period_group.rb +9 -0
- data/lib/canvas_sync/generators/templates/models/user_observer.rb +11 -0
- data/lib/canvas_sync/importers/bulk_importer.rb +27 -16
- data/lib/canvas_sync/job_batches/batch.rb +9 -0
- data/lib/canvas_sync/job_batches/chain_builder.rb +9 -1
- data/lib/canvas_sync/job_batches/hier_batch_ids.lua +25 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/batches_assets/css/styles.less +178 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/batches_assets/js/batch_tree.js +106 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/batches_assets/js/util.js +2 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/views/_batch_tree.erb +6 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/views/_common.erb +13 -0
- data/lib/canvas_sync/job_batches/sidekiq/web/views/batch.erb +15 -88
- data/lib/canvas_sync/job_batches/sidekiq/web.rb +93 -0
- data/lib/canvas_sync/jobs/begin_sync_chain_job.rb +1 -1
- data/lib/canvas_sync/jobs/report_checker.rb +37 -4
- data/lib/canvas_sync/jobs/report_starter.rb +2 -2
- data/lib/canvas_sync/processors/assignment_groups_processor.rb +1 -7
- data/lib/canvas_sync/processors/assignments_processor.rb +1 -7
- data/lib/canvas_sync/processors/context_module_items_processor.rb +1 -7
- data/lib/canvas_sync/processors/context_modules_processor.rb +1 -7
- data/lib/canvas_sync/processors/model_mappings.yml +68 -0
- data/lib/canvas_sync/processors/normal_processor.rb +3 -3
- data/lib/canvas_sync/processors/provisioning_report_processor.rb +21 -63
- data/lib/canvas_sync/processors/report_processor.rb +14 -9
- data/lib/canvas_sync/processors/submissions_processor.rb +1 -7
- data/lib/canvas_sync/record.rb +4 -0
- data/lib/canvas_sync/version.rb +1 -1
- data/lib/canvas_sync.rb +4 -1
- data/spec/canvas_sync/processors/provisioning_report_processor_spec.rb +40 -0
- data/spec/dummy/app/models/grading_period.rb +14 -0
- data/spec/dummy/app/models/grading_period_group.rb +15 -0
- data/spec/dummy/app/models/user_observer.rb +17 -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/20210907233331_create_grading_period_groups.rb +28 -0
- data/spec/dummy/db/schema.rb +42 -1
- data/spec/dummy/log/development.log +1167 -0
- data/spec/dummy/log/test.log +2775 -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/user_observers.csv +3 -0
- metadata +38 -17
@@ -0,0 +1,106 @@
|
|
1
|
+
import { h, Component, render } from 'https://unpkg.com/preact?module';
|
2
|
+
import htm from 'https://unpkg.com/htm?module';
|
3
|
+
import { root_url } from './util.js';
|
4
|
+
|
5
|
+
// Initialize htm with Preact
|
6
|
+
const html = htm.bind(h);
|
7
|
+
|
8
|
+
const StatusBlock = (props) => html`
|
9
|
+
<div class="status-block ${props.class || ''}">
|
10
|
+
${props.title && props.title + ':'}
|
11
|
+
<span class="tree-stat pending">${props.pending_count}</span>
|
12
|
+
|
|
13
|
+
<span class="tree-stat failed">${props.failed_count}</span>
|
14
|
+
|
|
15
|
+
<span class="tree-stat success">${props.successful_count}</span>
|
16
|
+
/
|
17
|
+
<span class="tree-stat total">${props.total_count}</span>
|
18
|
+
</div>
|
19
|
+
`
|
20
|
+
|
21
|
+
class TreeLevel extends Component {
|
22
|
+
get bid() {
|
23
|
+
return this.props.data.bid;
|
24
|
+
}
|
25
|
+
|
26
|
+
get batch() {
|
27
|
+
return this.props.data;
|
28
|
+
}
|
29
|
+
|
30
|
+
load_more = async (event) => {
|
31
|
+
event.preventDefault();
|
32
|
+
const l = this.batch.batches.items.length;
|
33
|
+
const resp = await fetch(`${root_url}batches/${this.bid}/tree?slice=${l}:${l + 5 - 1}`)
|
34
|
+
const result = await resp.json()
|
35
|
+
const newEntries = result.batches.items;
|
36
|
+
for (let ent of newEntries) {
|
37
|
+
this.batch.batches.items.push(ent)
|
38
|
+
}
|
39
|
+
this.forceUpdate()
|
40
|
+
}
|
41
|
+
|
42
|
+
toggle = (event) => {
|
43
|
+
event.preventDefault();
|
44
|
+
this.setState({ collapsed: !this.state.collapsed })
|
45
|
+
}
|
46
|
+
|
47
|
+
render() {
|
48
|
+
const { data: bd } = this.props;
|
49
|
+
|
50
|
+
let sub_entries = [];
|
51
|
+
let sub_batches = bd.batches.items;
|
52
|
+
for (let b of sub_batches) {
|
53
|
+
sub_entries.push(html`<${TreeLevel} data=${b} />`)
|
54
|
+
}
|
55
|
+
|
56
|
+
let fully_loaded = !(sub_batches.length < bd.batches.total_count);
|
57
|
+
|
58
|
+
const load_more_elem = html`<div class="load-more">
|
59
|
+
${sub_entries.length} / ${bd.batches.total_count} Items Loaded - <a href="#" onClick=${this.load_more}>Load More</a>
|
60
|
+
</div>`
|
61
|
+
|
62
|
+
return html`<div class="tree-entry tree-batch">
|
63
|
+
<div class="header">
|
64
|
+
<a class="row-toggle ${!bd.batches.total_count && 'not_applicable'}" onClick=${this.toggle} href="#">
|
65
|
+
${this.state.collapsed ? '+' : '-'}
|
66
|
+
</a>
|
67
|
+
|
68
|
+
<div class="header-inner">
|
69
|
+
<div class="main">
|
70
|
+
<span class="bid">
|
71
|
+
${bd.bid}
|
72
|
+
<a class="bid-goto" href="${root_url}batches/${bd.bid}">⇢</a>
|
73
|
+
</span>
|
74
|
+
${bd.description || (bd.status == 'deleted' && html`<i class="text-inactive">Deleted</i>`) || html`<i class="text-inactive">No Description</i>`}
|
75
|
+
</div>
|
76
|
+
|
77
|
+
<span class="status-label ${bd.status}">${bd.status}</span>
|
78
|
+
|
79
|
+
${bd.status != 'deleted' && html`
|
80
|
+
<${StatusBlock} class="job-status" title="Jobs" ...${bd.jobs} />
|
81
|
+
<${StatusBlock} class="batch-status" title="Batches" ...${bd.batches} />
|
82
|
+
`}
|
83
|
+
</div>
|
84
|
+
</div>
|
85
|
+
|
86
|
+
<div class="subitems ${this.state.collapsed ? 'hidden' : ''}">
|
87
|
+
${sub_entries}
|
88
|
+
${!fully_loaded && load_more_elem}
|
89
|
+
</div>
|
90
|
+
</div>`
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
class TreeRoot extends Component {
|
95
|
+
render() {
|
96
|
+
const tree_data = JSON.parse(document.querySelector('#batch-tree #initial-data').innerHTML);
|
97
|
+
return html`
|
98
|
+
<div class="tree-header">
|
99
|
+
<${StatusBlock} pending_count="pending" failed_count="failed" successful_count="successful" total_count="total" />
|
100
|
+
</div>
|
101
|
+
<${TreeLevel} data=${tree_data} />
|
102
|
+
`;
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
render(html`<${TreeRoot} />`, document.querySelector('#batch-tree'));
|
@@ -0,0 +1,13 @@
|
|
1
|
+
|
2
|
+
<% add_to_head do %>
|
3
|
+
<meta name="sidekiq-baseurl" content="<%= root_path %>" />
|
4
|
+
<% if dev_mode? %>
|
5
|
+
<link href="<%= root_path %>batches_assets/css/styles.less" media="screen" rel="stylesheet/less" type="text/css" />
|
6
|
+
<script async type="text/javascript" src="https://unpkg.com/less@4.1.1/dist/less.js" data-async="true"></script>
|
7
|
+
<% else %>
|
8
|
+
<link href="<%= root_path %>batches_assets/css/styles.less" media="screen" rel="stylesheet/less" type="text/css" />
|
9
|
+
<script async type="text/javascript" src="https://unpkg.com/less@4.1.1/dist/less.js" data-async="true"></script>
|
10
|
+
<%# TODO: Pre-compile LESS %>
|
11
|
+
<!-- <link href="<%= root_path %>batches_assets/css/styles.css" media="screen" rel="stylesheet" type="text/css" /> -->
|
12
|
+
<% end %>
|
13
|
+
<% end %>
|
@@ -1,3 +1,5 @@
|
|
1
|
+
<%= erb get_template(:_common) %>
|
2
|
+
|
1
3
|
<h3><%= t('Batch') %></h3>
|
2
4
|
<% status = CanvasSync::JobBatches::Batch::Status.new(@batch) %>
|
3
5
|
|
@@ -17,70 +19,13 @@
|
|
17
19
|
<td><%= @batch.description %></td>
|
18
20
|
</tr>
|
19
21
|
<tr>
|
20
|
-
<th colspan="2" scope=row><%= t('
|
22
|
+
<th colspan="2" scope=row><%= t('Context') %></td>
|
21
23
|
<td>
|
22
|
-
<code class="code-wrap">
|
23
|
-
<div class="args-extended"><%= @batch
|
24
|
+
<code class="code-wrap batch-context">
|
25
|
+
<div class="args-extended"><%= format_context(@batch) %></div>
|
24
26
|
</code>
|
25
27
|
</td>
|
26
28
|
</tr>
|
27
|
-
<tr>
|
28
|
-
<th colspan="2" scope=row><%= t('Full Context') %></td>
|
29
|
-
<td>
|
30
|
-
<code class="code-wrap">
|
31
|
-
<div class="args-extended"><%= @batch.context.flatten.to_json %></div>
|
32
|
-
</code>
|
33
|
-
</td>
|
34
|
-
</tr>
|
35
|
-
|
36
|
-
<tr>
|
37
|
-
<th colspan="3">Jobs</th>
|
38
|
-
</tr>
|
39
|
-
<tr>
|
40
|
-
<th></th>
|
41
|
-
<th><%= t('Pending') %></th>
|
42
|
-
<td><%= status.pending %></th>
|
43
|
-
</tr>
|
44
|
-
<tr>
|
45
|
-
<th></th>
|
46
|
-
<th><%= t('Failed') %></th>
|
47
|
-
<td><%= status.failures %></th>
|
48
|
-
</tr>
|
49
|
-
<tr>
|
50
|
-
<th></th>
|
51
|
-
<th><%= t('Complete') %></th>
|
52
|
-
<td><%= status.completed_count %></th>
|
53
|
-
</tr>
|
54
|
-
<tr>
|
55
|
-
<th></th>
|
56
|
-
<th><%= t('Total') %></th>
|
57
|
-
<td><%= status.job_count %></th>
|
58
|
-
</tr>
|
59
|
-
|
60
|
-
<tr>
|
61
|
-
<th colspan="3">Batches</th>
|
62
|
-
</tr>
|
63
|
-
<tr>
|
64
|
-
<th></th>
|
65
|
-
<th><%= t('Pending') %></th>
|
66
|
-
<td><%= status.child_count - status.successful_children_count %></th>
|
67
|
-
</tr>
|
68
|
-
<tr>
|
69
|
-
<th></th>
|
70
|
-
<th><%= t('Failed') %></th>
|
71
|
-
<td><%= status.failed_children_count %></th>
|
72
|
-
</tr>
|
73
|
-
<tr>
|
74
|
-
<th></th>
|
75
|
-
<th><%= t('Success') %></th>
|
76
|
-
<td><%= status.successful_children_count %></th>
|
77
|
-
</tr>
|
78
|
-
<tr>
|
79
|
-
<th></th>
|
80
|
-
<th><%= t('Total') %></th>
|
81
|
-
<td><%= status.child_count %></th>
|
82
|
-
</tr>
|
83
|
-
|
84
29
|
</tbody>
|
85
30
|
</table>
|
86
31
|
</div>
|
@@ -88,51 +33,33 @@
|
|
88
33
|
<header class="row">
|
89
34
|
<div class="col-sm-5">
|
90
35
|
<h3>
|
91
|
-
<%= t('
|
36
|
+
<%= t('Child Batches') %>
|
92
37
|
</h3>
|
93
38
|
</div>
|
94
|
-
<%
|
95
|
-
@current_page = @current_jobs_page
|
96
|
-
@total_size = @total_jobs_size
|
97
|
-
%>
|
98
|
-
<% if @jobs.any? && @total_size > @count.to_i %>
|
99
|
-
<div class="col-sm-4">
|
100
|
-
<%= erb get_template(:_pagination), locals: { url: "#{root_path}batches/#{@batch.bid}", page_key: :job_page } %>
|
101
|
-
</div>
|
102
|
-
<% end %>
|
103
39
|
</header>
|
104
40
|
|
105
|
-
|
106
|
-
<div class="table_container">
|
107
|
-
<%= erb get_template(:_jobs_table), locals: { jobs: @jobs } %>
|
108
|
-
</div>
|
109
|
-
<% end %>
|
41
|
+
<%= erb get_template(:_batch_tree), locals: { } %>
|
110
42
|
|
111
43
|
<header class="row">
|
112
44
|
<div class="col-sm-5">
|
113
45
|
<h3>
|
114
|
-
<%= t('
|
46
|
+
<%= t('Jobs') %>
|
47
|
+
<i>(Queued and Current)</i>
|
115
48
|
</h3>
|
116
49
|
</div>
|
117
50
|
<%
|
118
|
-
@current_page = @
|
119
|
-
@total_size = @
|
51
|
+
@current_page = @current_jobs_page
|
52
|
+
@total_size = @total_jobs_size
|
120
53
|
%>
|
121
|
-
<% if @
|
54
|
+
<% if @jobs.any? && @total_size > @count.to_i %>
|
122
55
|
<div class="col-sm-4">
|
123
|
-
<%= erb get_template(:_pagination), locals: { url: "#{root_path}batches/#{@batch.bid}", page_key: :
|
56
|
+
<%= erb get_template(:_pagination), locals: { url: "#{root_path}batches/#{@batch.bid}", page_key: :job_page } %>
|
124
57
|
</div>
|
125
58
|
<% end %>
|
126
59
|
</header>
|
127
60
|
|
128
|
-
<% if @
|
61
|
+
<% if @jobs.any? %>
|
129
62
|
<div class="table_container">
|
130
|
-
<%= erb get_template(:
|
63
|
+
<%= erb get_template(:_jobs_table), locals: { jobs: @jobs } %>
|
131
64
|
</div>
|
132
65
|
<% end %>
|
133
|
-
|
134
|
-
<form class="form-horizontal" action="<%= root_path %>batches/<%= @batch.bid %>" method="post">
|
135
|
-
<%= csrf_tag %>
|
136
|
-
<a class="btn btn-default" href="<%= root_path %>batches"><%= t('GoBack') %></a>
|
137
|
-
<input class="btn btn-danger" type="submit" name="delete" value="<%= t('Delete') %>" data-confirm="<%= t('AreYouSure') %>" />
|
138
|
-
</form>
|
@@ -9,11 +9,19 @@ require_relative "web/helpers"
|
|
9
9
|
|
10
10
|
module CanvasSync::JobBatches::Sidekiq
|
11
11
|
module Web
|
12
|
+
DEV_MODE = (defined?(Rails) && !Rails.env.production?) || !!ENV["SIDEKIQ_WEB_TESTING"]
|
13
|
+
|
12
14
|
def self.registered(app) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
13
15
|
app.helpers do
|
14
16
|
include Web::Helpers
|
17
|
+
|
18
|
+
def dev_mode?
|
19
|
+
DEV_MODE
|
20
|
+
end
|
15
21
|
end
|
16
22
|
|
23
|
+
# =============== BATCHES =============== #
|
24
|
+
|
17
25
|
app.get "/batches" do
|
18
26
|
@count = (params['count'] || 25).to_i
|
19
27
|
@current_page, @total_size, @batches = page('batches', params['page'], @count)
|
@@ -26,6 +34,8 @@ module CanvasSync::JobBatches::Sidekiq
|
|
26
34
|
@bid = params[:bid]
|
27
35
|
@batch = CanvasSync::JobBatches::Batch.new(@bid)
|
28
36
|
|
37
|
+
@tree_data = tree_data(@bid)
|
38
|
+
|
29
39
|
@count = (params['count'] || 25).to_i
|
30
40
|
@current_batches_page, @total_batches_size, @sub_batches = page("BID-#{@batch.bid}-bids", params['batch_page'], @count)
|
31
41
|
@sub_batches = @sub_batches.map {|b, score| CanvasSync::JobBatches::Batch.new(b) }
|
@@ -36,6 +46,81 @@ module CanvasSync::JobBatches::Sidekiq
|
|
36
46
|
erb(get_template(:batch))
|
37
47
|
end
|
38
48
|
|
49
|
+
app.get "/batches/:bid/tree" do
|
50
|
+
@bid = params[:bid]
|
51
|
+
|
52
|
+
json(tree_data(@bid, slice: params[:slice]))
|
53
|
+
end
|
54
|
+
|
55
|
+
app.helpers do
|
56
|
+
def tree_data(root_bid, slice: nil)
|
57
|
+
tree_bids = CanvasSync::JobBatches::Batch.bid_hierarchy(root_bid, slice: slice)
|
58
|
+
|
59
|
+
CanvasSync::JobBatches::Batch.redis do |r|
|
60
|
+
layer_data = ->(layer, parent = nil) {
|
61
|
+
bid = layer[0]
|
62
|
+
batch = CanvasSync::JobBatches::Batch.new(bid)
|
63
|
+
|
64
|
+
jobs_total = r.hget("BID-#{bid}", "job_count").to_i
|
65
|
+
jobs_pending = r.hget("BID-#{bid}", 'pending').to_i
|
66
|
+
jobs_failed = r.scard("BID-#{bid}-failed").to_i
|
67
|
+
jobs_success = jobs_total - jobs_pending
|
68
|
+
|
69
|
+
batches_total = r.hget("BID-#{bid}", 'children').to_i
|
70
|
+
batches_success = r.scard("BID-#{bid}-batches-success").to_i
|
71
|
+
batches_pending = batches_total - batches_success
|
72
|
+
batches_failed = r.scard("BID-#{bid}-batches-failed").to_i
|
73
|
+
|
74
|
+
status = 'in_progress'
|
75
|
+
status = 'complete' if batches_pending == batches_failed && jobs_pending == jobs_failed
|
76
|
+
status = 'success' if batches_pending == 0 && jobs_pending == 0
|
77
|
+
status = 'deleted' if bid != root_bid && !batch.parent_bid
|
78
|
+
|
79
|
+
{
|
80
|
+
bid: bid,
|
81
|
+
created_at: r.hget("BID-#{bid}", 'created_at'),
|
82
|
+
status: status,
|
83
|
+
parent_bid: parent ? parent.bid : batch.parent_bid,
|
84
|
+
description: batch.description,
|
85
|
+
jobs: {
|
86
|
+
pending_count: jobs_pending,
|
87
|
+
successful_count: jobs_success,
|
88
|
+
failed_count: jobs_failed,
|
89
|
+
total_count: jobs_total,
|
90
|
+
# items: batches.map{|b| layer_data[b] },
|
91
|
+
},
|
92
|
+
batches: {
|
93
|
+
pending_count: batches_pending,
|
94
|
+
successful_count: batches_success,
|
95
|
+
failed_count: batches_failed,
|
96
|
+
total_count: batches_total,
|
97
|
+
items: layer[1].map{|b| layer_data[b, batch] },
|
98
|
+
},
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
data = layer_data[tree_bids]
|
103
|
+
data[:batches][:slice] = slice if slice
|
104
|
+
data
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def format_context(batch)
|
109
|
+
bits = []
|
110
|
+
own_keys = batch.context.own.keys
|
111
|
+
batch.context.flatten.each do |k,v|
|
112
|
+
added = own_keys.include? k
|
113
|
+
bits << " <span class=\"key #{added ? 'own' : 'inherited'}\">\"#{k}\": #{v.to_json},</span>"
|
114
|
+
end
|
115
|
+
bits = [
|
116
|
+
"{ // <span class=\"own\">Added</span> / <span class=\"inherited\">Inherited</span>",
|
117
|
+
*bits,
|
118
|
+
'}'
|
119
|
+
]
|
120
|
+
bits.join("\n")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
39
124
|
app.post "/batches/all" do
|
40
125
|
if params['delete']
|
41
126
|
drain_zset('batches') do |batches|
|
@@ -107,6 +192,14 @@ module CanvasSync::JobBatches::Sidekiq
|
|
107
192
|
end
|
108
193
|
|
109
194
|
if defined?(::Sidekiq::Web)
|
195
|
+
rules = []
|
196
|
+
rules = [[:all, {"Cache-Control" => "public, max-age=86400"}]] unless CanvasSync::JobBatches::Sidekiq::Web::DEV_MODE
|
197
|
+
|
198
|
+
::Sidekiq::Web.use Rack::Static, urls: ["/batches_assets"],
|
199
|
+
root: File.expand_path("#{File.dirname(__FILE__)}/web"),
|
200
|
+
cascade: true,
|
201
|
+
header_rules: rules
|
202
|
+
|
110
203
|
::Sidekiq::Web.register CanvasSync::JobBatches::Sidekiq::Web
|
111
204
|
::Sidekiq::Web.tabs["Batches"] = "batches"
|
112
205
|
::Sidekiq::Web.tabs["Pools"] = "pools"
|
@@ -46,7 +46,7 @@ module CanvasSync
|
|
46
46
|
m = Regexp.last_match
|
47
47
|
day = m[1]
|
48
48
|
skip = m[2] || "1"
|
49
|
-
|
49
|
+
DateTime.now.send(:"#{day}?") && last_full_sync.end_of_day <= (skip.to_i.weeks.ago.end_of_day)
|
50
50
|
when opt.match?(%r{^(\d+)\%$})
|
51
51
|
m = Regexp.last_match
|
52
52
|
rand(100) < m[1].to_i
|
@@ -4,8 +4,9 @@ module CanvasSync
|
|
4
4
|
# Re-enqueues itself if the report is still processing on Canvas.
|
5
5
|
# Enqueues the ReportProcessor when the report has completed.
|
6
6
|
class ReportChecker < CanvasSync::Job
|
7
|
-
REPORT_TIMEOUT =
|
7
|
+
REPORT_TIMEOUT = 24.hours
|
8
8
|
COMPILATION_TIMEOUT = 1.hour
|
9
|
+
MAX_TRIES = 3
|
9
10
|
|
10
11
|
# @param report_name [Hash] e.g., 'provisioning_csv'
|
11
12
|
# @param report_id [Integer]
|
@@ -13,6 +14,7 @@ module CanvasSync
|
|
13
14
|
# @param options [Hash] hash of options that will be passed to the job processor
|
14
15
|
# @return [nil]
|
15
16
|
def perform(report_name, report_id, processor, options, checker_context = {}) # rubocop:disable Metrics/AbcSize
|
17
|
+
max_tries = options[:report_max_tries] || batch_context[:report_max_tries] || MAX_TRIES
|
16
18
|
account_id = options[:account_id] || batch_context[:account_id] || "self"
|
17
19
|
report_status = CanvasSync.get_canvas_sync_client(batch_context)
|
18
20
|
.report_status(account_id, report_name, report_id)
|
@@ -27,9 +29,17 @@ module CanvasSync
|
|
27
29
|
report_id,
|
28
30
|
)
|
29
31
|
when "error", "deleted"
|
30
|
-
|
32
|
+
checker_context[:failed_attempts] ||= 0
|
33
|
+
checker_context[:failed_attempts] += 1
|
34
|
+
failed_attempts = checker_context[:failed_attempts]
|
35
|
+
message = "Report failed to process; status was #{report_status} for report_name: #{report_name}, report_id: #{report_id}, #{current_organization.name}. This report has now failed #{checker_context[:failed_attempts]} time." # rubocop:disable Metrics/LineLength
|
31
36
|
Rails.logger.error(message)
|
32
|
-
|
37
|
+
if failed_attempts >= max_tries
|
38
|
+
Rails.logger.error("This report has failed #{failed_attempts} times. Giving up.")
|
39
|
+
raise message
|
40
|
+
else
|
41
|
+
restart_report(options, report_name, processor, checker_context)
|
42
|
+
end
|
33
43
|
else
|
34
44
|
report_timeout = parse_timeout(options[:report_timeout] || batch_context[:report_timeout] || REPORT_TIMEOUT)
|
35
45
|
if timeout_met?(options[:sync_start_time], report_timeout)
|
@@ -51,7 +61,7 @@ module CanvasSync
|
|
51
61
|
report_id,
|
52
62
|
processor,
|
53
63
|
options,
|
54
|
-
checker_context
|
64
|
+
checker_context
|
55
65
|
)
|
56
66
|
end
|
57
67
|
end
|
@@ -66,6 +76,29 @@ module CanvasSync
|
|
66
76
|
def parse_timeout(val)
|
67
77
|
val
|
68
78
|
end
|
79
|
+
|
80
|
+
def restart_report(options, report_name, processor, checker_context)
|
81
|
+
account_id = options[:account_id] || batch_context[:account_id] || "self"
|
82
|
+
options[:sync_start_time] = DateTime.now.utc.iso8601
|
83
|
+
new_context = {}
|
84
|
+
new_context[:failed_attempts] = checker_context[:failed_attempts]
|
85
|
+
report_id = start_report(account_id, report_name, options[:report_params])
|
86
|
+
CanvasSync::Jobs::ReportChecker
|
87
|
+
.set(wait: report_checker_wait_time)
|
88
|
+
.perform_later(
|
89
|
+
report_name,
|
90
|
+
report_id,
|
91
|
+
processor,
|
92
|
+
options,
|
93
|
+
new_context
|
94
|
+
)
|
95
|
+
end
|
96
|
+
|
97
|
+
def start_report(account_id, report_name, report_params)
|
98
|
+
report = CanvasSync.get_canvas_sync_client(batch_context)
|
99
|
+
.start_report(account_id, report_name, report_params)
|
100
|
+
report["id"]
|
101
|
+
end
|
69
102
|
end
|
70
103
|
end
|
71
104
|
end
|