canvas_sync 0.17.17.beta1 → 0.17.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/canvas_sync/job_batches/batch.rb +9 -0
- data/lib/canvas_sync/job_batches/chain_builder.rb +8 -0
- data/lib/canvas_sync/job_batches/hier_batch_ids.lua +25 -0
- data/lib/canvas_sync/job_batches/sidekiq/web.rb +93 -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/version.rb +1 -1
- metadata +11 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 30e1a16308bbc8795dc671c19f35d29577665213261829d3180a9efeefab4adf
|
4
|
+
data.tar.gz: bade0d8907b22bf252b85ba4067798ebd3b6582deed06adfccf7a8951a6164b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a155b415154694a42c218bd5ef91f21ca7cdcc81967cc2f2c16a180eebfb32d1b279c72ea2eab58beaabb8e8a8905fe4ef4086ce758c9ee14b1583eccf06849
|
7
|
+
data.tar.gz: 3269c39188c086e7b3b03d6280414fbdc7a32c6780af5744da08f3f9432f4eb5ed993c3af4d22e2fe477d92ca8e4d705c62ba9e9005559a9e1145922f565aa4f
|
@@ -28,6 +28,7 @@ module CanvasSync
|
|
28
28
|
|
29
29
|
BID_EXPIRE_TTL = 2_592_000
|
30
30
|
SCHEDULE_CALLBACK = RedisScript.new(Pathname.new(__FILE__) + "../schedule_callback.lua")
|
31
|
+
BID_HIERARCHY = RedisScript.new(Pathname.new(__FILE__) + "../hier_batch_ids.lua")
|
31
32
|
|
32
33
|
attr_reader :bid
|
33
34
|
|
@@ -423,6 +424,14 @@ module CanvasSync
|
|
423
424
|
def push_callbacks(args, queue)
|
424
425
|
Batch::Callback::worker_class.enqueue_all(args, queue)
|
425
426
|
end
|
427
|
+
|
428
|
+
def bid_hierarchy(bid, depth: 4, per_depth: 5, slice: nil)
|
429
|
+
args = [bid, depth, per_depth]
|
430
|
+
args << slice if slice
|
431
|
+
redis do |r|
|
432
|
+
BID_HIERARCHY.call(r, [], args)
|
433
|
+
end
|
434
|
+
end
|
426
435
|
end
|
427
436
|
end
|
428
437
|
|
@@ -172,6 +172,14 @@ module CanvasSync
|
|
172
172
|
mapper[key] ||= []
|
173
173
|
end
|
174
174
|
|
175
|
+
# TODO: Add a Chain progress web View
|
176
|
+
# Augment Batch tree-view with Chain data
|
177
|
+
# > [DONE] Tree view w/o Chain will only show Parent/Current batches and Job Counts
|
178
|
+
# > If augmented with Chain data, the above will be annotated with Chain-related info and will be able to show Jobs defined in the Chain
|
179
|
+
# > Chain-jobs will be supplied chain_id and chain_step_id metadata
|
180
|
+
# > Using server-middleware, if a Chain-job (has chain_id and chain_step_id) creates a Batch, tag the Batch w/ the chain_id and chain_step_id
|
181
|
+
# > UI will map Batches to Chain-steps using the chain_step_id. UI will add entries for any Chain-steps that were not tied to a Batch
|
182
|
+
# > [DONE] Use a Lua script to find child batch IDs. Support max_depth, items_per_depth, top_depth_slice parameters
|
175
183
|
def enqueue_job(job_def)
|
176
184
|
job_class = job_def[:job].constantize
|
177
185
|
job_options = job_def[:parameters] || []
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
local function add_bids(root, depth)
|
3
|
+
local result_data = {}
|
4
|
+
|
5
|
+
if depth > 0 then
|
6
|
+
local sbids
|
7
|
+
if depth == tonumber(ARGV[2]) and ARGV[4] then
|
8
|
+
local min, max = ARGV[4]:match('(%d+):(%d+)')
|
9
|
+
sbids = redis.call('ZRANGE', 'BID-' .. root .. '-bids', min, max)
|
10
|
+
else
|
11
|
+
sbids = redis.call('ZRANGE', 'BID-' .. root .. '-bids', 0, tonumber(ARGV[3]) - 1)
|
12
|
+
end
|
13
|
+
|
14
|
+
local sub_data = {}
|
15
|
+
for _,v in ipairs(sbids) do
|
16
|
+
table.insert(sub_data, add_bids(v, depth - 1))
|
17
|
+
end
|
18
|
+
|
19
|
+
return { root, sub_data }
|
20
|
+
end
|
21
|
+
|
22
|
+
return { root, result_data}
|
23
|
+
end
|
24
|
+
|
25
|
+
return add_bids(ARGV[1], tonumber(ARGV[2]))
|
@@ -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"
|
@@ -0,0 +1,178 @@
|
|
1
|
+
|
2
|
+
@color-green: #25c766;
|
3
|
+
@color-red: #c7254e;
|
4
|
+
@color-yellow: #c4c725;
|
5
|
+
|
6
|
+
.code-wrap.batch-context .args-extended {
|
7
|
+
white-space: pre;
|
8
|
+
|
9
|
+
.key {
|
10
|
+
white-space: pre-wrap;
|
11
|
+
margin-left: 2em;
|
12
|
+
text-indent: -2em;
|
13
|
+
display: inline-block;
|
14
|
+
}
|
15
|
+
|
16
|
+
.own {
|
17
|
+
color: @color-green;
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
|
22
|
+
.batch-tree {
|
23
|
+
.status-block {
|
24
|
+
.tree-stat {
|
25
|
+
margin: 0 4px;
|
26
|
+
|
27
|
+
&.pending {
|
28
|
+
color: @color-yellow;
|
29
|
+
}
|
30
|
+
&.failed {
|
31
|
+
color: @color-red;
|
32
|
+
}
|
33
|
+
&.success {
|
34
|
+
color: @color-green;
|
35
|
+
}
|
36
|
+
&.total {
|
37
|
+
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
.text-inactive {
|
43
|
+
color: darken(#fff, 35%);
|
44
|
+
font-size: 80%;
|
45
|
+
}
|
46
|
+
|
47
|
+
.tree-header {
|
48
|
+
position: relative;
|
49
|
+
|
50
|
+
.status-block {
|
51
|
+
position: absolute;
|
52
|
+
bottom: 0;
|
53
|
+
width: 100%;
|
54
|
+
|
55
|
+
margin-right: 8px;
|
56
|
+
font-size: 90%;
|
57
|
+
text-align: right;
|
58
|
+
|
59
|
+
.tree-stat {
|
60
|
+
font-style: italic;
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
.tree-entry {
|
66
|
+
> .header {
|
67
|
+
display: flex;
|
68
|
+
align-items: center;
|
69
|
+
|
70
|
+
.header-inner {
|
71
|
+
padding: 4px 0;
|
72
|
+
border-bottom: 1px dashed white;
|
73
|
+
display: flex;
|
74
|
+
align-items: center;
|
75
|
+
flex: 1;
|
76
|
+
}
|
77
|
+
|
78
|
+
&:hover {
|
79
|
+
background-color: rgba(0,0,0,0.20);
|
80
|
+
border-radius: 3px;
|
81
|
+
}
|
82
|
+
|
83
|
+
.row-toggle {
|
84
|
+
width: 16px;
|
85
|
+
height: 16px;
|
86
|
+
text-align: center;
|
87
|
+
align-self: center;
|
88
|
+
border-radius: 50%;
|
89
|
+
border: 1px solid #999;
|
90
|
+
text-decoration: none;
|
91
|
+
margin: 0 4px;
|
92
|
+
font-size: 16px;
|
93
|
+
line-height: 15px;
|
94
|
+
|
95
|
+
&.not_applicable {
|
96
|
+
opacity: 0;
|
97
|
+
pointer-events: none;
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
.main {
|
102
|
+
flex: 1;
|
103
|
+
display: flex;
|
104
|
+
align-items: baseline;
|
105
|
+
|
106
|
+
.bid {
|
107
|
+
font-family: monospace;
|
108
|
+
padding: 3px 6px;
|
109
|
+
background: rgba(0,0,0,0.2);
|
110
|
+
border-radius: 3px;
|
111
|
+
font-size: 12px;
|
112
|
+
margin: 0 12px 0 0;
|
113
|
+
|
114
|
+
&:hover {
|
115
|
+
.bid-goto {
|
116
|
+
display: inline-block;
|
117
|
+
padding: 0 0 0 4px;
|
118
|
+
font-size: 200%;
|
119
|
+
line-height: 10px;
|
120
|
+
vertical-align: sub;
|
121
|
+
text-decoration: dotted;
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
125
|
+
.bid-goto {
|
126
|
+
display: none;
|
127
|
+
}
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
.goto-link {
|
132
|
+
margin: 0 8px;
|
133
|
+
display: inline-block;
|
134
|
+
height: 16px;
|
135
|
+
font-size: 90%;
|
136
|
+
border-bottom: 1px dotted white;
|
137
|
+
}
|
138
|
+
|
139
|
+
.status-label {
|
140
|
+
font-family: monospace;
|
141
|
+
padding: 3px 6px;
|
142
|
+
background: rgba(0,0,0,0.2);
|
143
|
+
border-radius: 3px;
|
144
|
+
font-size: 12px;
|
145
|
+
margin: 0 12px 0 0;
|
146
|
+
|
147
|
+
&.deleted {
|
148
|
+
background: #99999933;
|
149
|
+
}
|
150
|
+
&.failed, &.complete {
|
151
|
+
background: #99000033;
|
152
|
+
}
|
153
|
+
&.success {
|
154
|
+
background: #00990033;
|
155
|
+
}
|
156
|
+
}
|
157
|
+
|
158
|
+
.status-block {
|
159
|
+
width: 10em;
|
160
|
+
text-align: center;
|
161
|
+
}
|
162
|
+
}
|
163
|
+
|
164
|
+
> .subitems {
|
165
|
+
padding-left: 16px;
|
166
|
+
|
167
|
+
>.load-more {
|
168
|
+
padding: 4px 0;
|
169
|
+
text-align: center;
|
170
|
+
border-bottom: 1px dashed white;
|
171
|
+
a {
|
172
|
+
border-bottom: 1px dotted white;
|
173
|
+
text-decoration: none;
|
174
|
+
}
|
175
|
+
}
|
176
|
+
}
|
177
|
+
}
|
178
|
+
}
|
@@ -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>
|
data/lib/canvas_sync/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: canvas_sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.17.
|
4
|
+
version: 0.17.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nate Collings
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -442,6 +442,7 @@ files:
|
|
442
442
|
- lib/canvas_sync/job_batches/callback.rb
|
443
443
|
- lib/canvas_sync/job_batches/chain_builder.rb
|
444
444
|
- lib/canvas_sync/job_batches/context_hash.rb
|
445
|
+
- lib/canvas_sync/job_batches/hier_batch_ids.lua
|
445
446
|
- lib/canvas_sync/job_batches/hincr_max.lua
|
446
447
|
- lib/canvas_sync/job_batches/jobs/base_job.rb
|
447
448
|
- lib/canvas_sync/job_batches/jobs/concurrent_batch_job.rb
|
@@ -453,8 +454,13 @@ files:
|
|
453
454
|
- lib/canvas_sync/job_batches/schedule_callback.lua
|
454
455
|
- lib/canvas_sync/job_batches/sidekiq.rb
|
455
456
|
- lib/canvas_sync/job_batches/sidekiq/web.rb
|
457
|
+
- lib/canvas_sync/job_batches/sidekiq/web/batches_assets/css/styles.less
|
458
|
+
- lib/canvas_sync/job_batches/sidekiq/web/batches_assets/js/batch_tree.js
|
459
|
+
- lib/canvas_sync/job_batches/sidekiq/web/batches_assets/js/util.js
|
456
460
|
- lib/canvas_sync/job_batches/sidekiq/web/helpers.rb
|
461
|
+
- lib/canvas_sync/job_batches/sidekiq/web/views/_batch_tree.erb
|
457
462
|
- lib/canvas_sync/job_batches/sidekiq/web/views/_batches_table.erb
|
463
|
+
- lib/canvas_sync/job_batches/sidekiq/web/views/_common.erb
|
458
464
|
- lib/canvas_sync/job_batches/sidekiq/web/views/_jobs_table.erb
|
459
465
|
- lib/canvas_sync/job_batches/sidekiq/web/views/_pagination.erb
|
460
466
|
- lib/canvas_sync/job_batches/sidekiq/web/views/batch.erb
|
@@ -673,11 +679,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
673
679
|
version: '0'
|
674
680
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
675
681
|
requirements:
|
676
|
-
- - "
|
682
|
+
- - ">="
|
677
683
|
- !ruby/object:Gem::Version
|
678
|
-
version:
|
684
|
+
version: '0'
|
679
685
|
requirements: []
|
680
|
-
rubygems_version: 3.0.3
|
686
|
+
rubygems_version: 3.0.3
|
681
687
|
signing_key:
|
682
688
|
specification_version: 4
|
683
689
|
summary: Gem for generating Canvas models and migrations and syncing data from Canvas
|