canvas_sync 0.17.3.beta3 → 0.17.6.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.
@@ -0,0 +1,114 @@
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
+ def self.registered(app) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
13
+ app.helpers do
14
+ include Web::Helpers
15
+ end
16
+
17
+ app.get "/batches" do
18
+ @count = (params['count'] || 25).to_i
19
+ @current_page, @total_size, @batches = page('batches', params['page'], @count)
20
+ @batches = @batches.map {|b, score| CanvasSync::JobBatches::Batch.new(b) }
21
+
22
+ erb(get_template(:batches))
23
+ end
24
+
25
+ app.get "/batches/:bid" do
26
+ @bid = params[:bid]
27
+ @batch = CanvasSync::JobBatches::Batch.new(@bid)
28
+
29
+ @count = (params['count'] || 25).to_i
30
+ @current_batches_page, @total_batches_size, @sub_batches = page("BID-#{@batch.bid}-bids", params['batch_page'], @count)
31
+ @sub_batches = @sub_batches.map {|b, score| CanvasSync::JobBatches::Batch.new(b) }
32
+
33
+ @current_jobs_page, @total_jobs_size, @jobs = page("BID-#{@batch.bid}-jids", params['job_page'], @count)
34
+ @jobs = @jobs.map {|jid, score| jid }
35
+
36
+ erb(get_template(:batch))
37
+ end
38
+
39
+ app.post "/batches/all" do
40
+ if params['delete']
41
+ drain_zset('batches') do |batches|
42
+ batches.each do |bid|
43
+ CanvasSync::JobBatches::Batch.cleanup_redis(bid)
44
+ end
45
+ end
46
+ end
47
+
48
+ redirect "#{root_path}batches"
49
+ end
50
+
51
+ app.post "/batches/:bid" do
52
+ @bid = params[:bid]
53
+ @batch = CanvasSync::JobBatches::Batch.new(@bid)
54
+
55
+ if params['delete']
56
+ CanvasSync::JobBatches::Batch.delete_prematurely!(@bid)
57
+ end
58
+
59
+ redirect_with_query("#{root_path}batches")
60
+ end
61
+
62
+ # =============== POOLS =============== #
63
+
64
+ app.get "/pools" do
65
+ @count = (params['count'] || 25).to_i
66
+ @current_page, @total_size, @pools = page('pools', params['page'], @count)
67
+ @pools = @pools.map {|b, score| CanvasSync::JobBatches::Pool.new(b) }
68
+
69
+ erb(get_template(:pools))
70
+ end
71
+
72
+ app.get "/pools/:pid" do
73
+ @pid = params[:pid]
74
+ @pool = CanvasSync::JobBatches::Pool.new(@pid)
75
+
76
+ @count = (params['count'] || 25).to_i
77
+ @current_jobs_page, @total_jobs_size, @jobs = page("POOLID-#{@pool.pid}-jobs", params['job_page'], @count)
78
+ @jobs = @jobs.map {|desc, score=nil| JSON.parse(desc)[0] }
79
+
80
+ erb(get_template(:pool))
81
+ end
82
+
83
+ app.post "/pools/all" do
84
+ if params['delete']
85
+ drain_zset('pools') do |pools|
86
+ pools.each do |pid|
87
+ CanvasSync::JobBatches::Pool.from_pid(pid).cleanup_redis
88
+ end
89
+ end
90
+ end
91
+
92
+ redirect "#{root_path}pools"
93
+ end
94
+
95
+ app.post "/pools/:pid" do
96
+ @pid = params[:pid]
97
+ @pool = CanvasSync::JobBatches::Pool.from_pid(@pid)
98
+
99
+ if params['delete']
100
+ @pool.cleanup_redis
101
+ end
102
+
103
+ redirect_with_query("#{root_path}pools")
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ if defined?(::Sidekiq::Web)
110
+ ::Sidekiq::Web.register CanvasSync::JobBatches::Sidekiq::Web
111
+ ::Sidekiq::Web.tabs["Batches"] = "batches"
112
+ ::Sidekiq::Web.tabs["Pools"] = "pools"
113
+ ::Sidekiq::Web.settings.locales << File.join(File.dirname(__FILE__), "locales")
114
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CanvasSync::JobBatches::Sidekiq
4
+ module Web
5
+ module Helpers
6
+ VIEW_PATH = File.expand_path("../web/views", __dir__)
7
+
8
+ module_function
9
+
10
+ def get_template(name)
11
+ File.open(File.join(VIEW_PATH, "#{name}.erb")).read
12
+ end
13
+
14
+ def drain_zset(key)
15
+ items, _ = Sidekiq.redis do |r|
16
+ r.multi do
17
+ r.zrange(key, 0, -1)
18
+ r.zremrangebyrank(key, 0, -1)
19
+ end
20
+ end
21
+ yield items
22
+ end
23
+
24
+ def safe_relative_time(time)
25
+ time = parse_time(time)
26
+ relative_time(time)
27
+ end
28
+
29
+ def parse_time(time)
30
+ case time
31
+ when Time
32
+ time
33
+ when Integer, Float
34
+ Time.at(time)
35
+ else
36
+ Time.parse(time.to_s)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,42 @@
1
+ <table class="table table-striped table-bordered table-hover">
2
+ <thead>
3
+ <tr>
4
+ <th rowspan="2"><%= t('Started') %></th>
5
+ <th rowspan="2"><%= t('BID') %></th>
6
+ <th rowspan="2"><%= t('Description') %></th>
7
+
8
+ <th colspan="4"><%= t('Jobs') %></th>
9
+ <th colspan="4"><%= t('Sub-Batches') %></th>
10
+ </tr>
11
+ <tr>
12
+ <th><%= t('Pending') %></th>
13
+ <th><%= t('Failed') %></th>
14
+ <th><%= t('Complete') %></th>
15
+ <th><%= t('Total') %></th>
16
+
17
+ <th><%= t('Pending') %></th>
18
+ <th><%= t('Failed') %></th>
19
+ <th><%= t('Success') %></th>
20
+ <th><%= t('Total') %></th>
21
+ </tr>
22
+ </thead>
23
+
24
+ <% batches.each do |batch| %>
25
+ <% status = CanvasSync::JobBatches::Batch::Status.new(batch) %>
26
+ <tr>
27
+ <td><%= safe_relative_time(batch.created_at.to_f) %></th>
28
+ <td><a href="<%= root_path %>batches/<%= batch.bid %>"><%= batch.bid %></a></td>
29
+ <td><%= batch.description %></th>
30
+
31
+ <td><%= status.pending %></th>
32
+ <td><%= status.failures %></th>
33
+ <td><%= status.completed_count %></th>
34
+ <td><%= status.job_count %></th>
35
+
36
+ <td><%= status.child_count - status.successful_children_count %></th>
37
+ <td><%= status.failed_children_count %></th>
38
+ <td><%= status.successful_children_count %></th>
39
+ <td><%= status.child_count %></th>
40
+ </tr>
41
+ <% end %>
42
+ </table>
@@ -0,0 +1,26 @@
1
+
2
+ <% if @total_size > @count %>
3
+ <ul class="pagination pull-right flip">
4
+ <% _page_key = defined?(page_key) ? page_key.to_s : 'page' %>
5
+
6
+ <li class="<%= 'disabled' if @current_page == 1 %>">
7
+ <a href="<%= url %>?<%= _page_key %>=1">&laquo;</a>
8
+ </li>
9
+ <% if @current_page > 1 %>
10
+ <li>
11
+ <a href="<%= url %>?<%= (qparams(page: @current_page - 1) || '').gsub('page', _page_key) %>"><%= @current_page - 1 %></a>
12
+ </li>
13
+ <% end %>
14
+ <li class="disabled">
15
+ <a href="<%= url %>?<%= (qparams(page: @current_page) || '').gsub('page', _page_key) %>"><%= @current_page %></a>
16
+ </li>
17
+ <% if @total_size > @current_page * @count %>
18
+ <li>
19
+ <a href="<%= url %>?<%= (qparams(page: @current_page + 1) || '').gsub('page', _page_key) %>"><%= @current_page + 1 %></a>
20
+ </li>
21
+ <% end %>
22
+ <li class="<%= 'disabled' if @total_size <= @current_page * @count %>">
23
+ <a href="<%= url %>?<%= (qparams(page: (@total_size.to_f / @count).ceil) || '').gsub('page', _page_key) %>">&raquo;</a>
24
+ </li>
25
+ </ul>
26
+ <% end %>
@@ -0,0 +1,138 @@
1
+ <h3><%= t('Batch') %></h3>
2
+ <% status = CanvasSync::JobBatches::Batch::Status.new(@batch) %>
3
+
4
+ <div class="table_container">
5
+ <table class="table table-striped table-bordered table-white table-hover">
6
+ <tbody>
7
+ <tr>
8
+ <th colspan="2" scope=row><%= t('Batch') %></td>
9
+ <td><%= @batch.bid %></td>
10
+ </tr>
11
+ <tr>
12
+ <th colspan="2" scope=row><%= t('Started') %></td>
13
+ <td><%= safe_relative_time(@batch.created_at.to_f) %></td>
14
+ </tr>
15
+ <tr>
16
+ <th colspan="2" scope=row><%= t('Description') %></td>
17
+ <td><%= @batch.description %></td>
18
+ </tr>
19
+ <tr>
20
+ <th colspan="2" scope=row><%= t('Added Context') %></td>
21
+ <td>
22
+ <code class="code-wrap">
23
+ <div class="args-extended"><%= @batch.context.own.to_json %></div>
24
+ </code>
25
+ </td>
26
+ </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
+ </tbody>
85
+ </table>
86
+ </div>
87
+
88
+ <header class="row">
89
+ <div class="col-sm-5">
90
+ <h3>
91
+ <%= t('Jobs') %>
92
+ </h3>
93
+ </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
+ </header>
104
+
105
+ <% if @jobs.any? %>
106
+ <div class="table_container">
107
+ <%= erb get_template(:_batches_table), locals: { batches: @jobs } %>
108
+ </div>
109
+ <% end %>
110
+
111
+ <header class="row">
112
+ <div class="col-sm-5">
113
+ <h3>
114
+ <%= t('Child Batches') %>
115
+ </h3>
116
+ </div>
117
+ <%
118
+ @current_page = @current_batches_page
119
+ @total_size = @total_batches_size
120
+ %>
121
+ <% if @sub_batches.any? && @total_size > @count.to_i %>
122
+ <div class="col-sm-4">
123
+ <%= erb get_template(:_pagination), locals: { url: "#{root_path}batches/#{@batch.bid}", page_key: :batch_page } %>
124
+ </div>
125
+ <% end %>
126
+ </header>
127
+
128
+ <% if @sub_batches.any? %>
129
+ <div class="table_container">
130
+ <%= erb get_template(:_batches_table), locals: { batches: @sub_batches } %>
131
+ </div>
132
+ <% 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>
@@ -0,0 +1,23 @@
1
+ <header class="row">
2
+ <div class="col-sm-5">
3
+ <h3>
4
+ <%= t('Batches') %>
5
+ </h3>
6
+ </div>
7
+ <% if @batches.any? && @total_size > @count.to_i %>
8
+ <div class="col-sm-4">
9
+ <%= erb get_template(:_pagination), locals: { url: "#{root_path}batches" } %>
10
+ </div>
11
+ <% end %>
12
+ </header>
13
+
14
+ <% if @batches.any? %>
15
+ <div class="table_container">
16
+ <%= erb get_template(:_batches_table), locals: { batches: @batches } %>
17
+ </div>
18
+ <% end %>
19
+
20
+ <form action="<%= root_path %>batches/all" method="post">
21
+ <%= csrf_tag %>
22
+ <input class="btn btn-danger btn-xs pull-right flip" type="submit" name="delete" value="<%= t('DeleteAll') %>" data-confirm="<%= t('AreYouSure') %>" />
23
+ </form>
@@ -0,0 +1,85 @@
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
+ </tbody>
35
+ </table>
36
+ </div>
37
+
38
+ <header class="row">
39
+ <div class="col-sm-5">
40
+ <h3>
41
+ <%= t('Tasks') %>
42
+ </h3>
43
+ </div>
44
+ <%
45
+ @current_page = @current_jobs_page
46
+ @total_size = @total_jobs_size
47
+ %>
48
+ <% if @jobs.any? && @total_size > @count.to_i %>
49
+ <div class="col-sm-4">
50
+ <%= erb get_template(:_pagination), locals: { url: "#{root_path}pools/#{@pool.pid}", page_key: :job_page } %>
51
+ </div>
52
+ <% end %>
53
+ </header>
54
+
55
+ <% if @jobs.any? %>
56
+ <div class="table_container">
57
+ <table class="table table-striped table-bordered table-hover">
58
+ <thead>
59
+ <tr>
60
+ <th><%= t('Job Class') %></th>
61
+ <th><%= t('Parameters') %></th>
62
+ <th><%= t('Wrapper Batch BID') %></th>
63
+ </tr>
64
+ </thead>
65
+
66
+ <% @jobs.each do |job_desc| %>
67
+ <tr>
68
+ <td><%= job_desc['job'] %></td>
69
+ <td>
70
+ <code class="code-wrap">
71
+ <div class="args-extended"><%= job_desc['parameters'].to_json %></div>
72
+ </code>
73
+ </td>
74
+ <td><a href="<%= root_path %>batches/<%= job_desc['pool_wrapper_batch'] %>"><%= job_desc['pool_wrapper_batch'] %></a></td>
75
+ </tr>
76
+ <% end %>
77
+ </table>
78
+ </div>
79
+ <% end %>
80
+
81
+ <form class="form-horizontal" action="<%= root_path %>pools/<%= @pool.pid %>" method="post">
82
+ <%= csrf_tag %>
83
+ <a class="btn btn-default" href="<%= root_path %>pools"><%= t('GoBack') %></a>
84
+ <input class="btn btn-danger" type="submit" name="delete" value="<%= t('Delete') %>" data-confirm="<%= t('AreYouSure') %>" />
85
+ </form>