begin
require "sidekiq/web"
rescue LoadError
# client-only usage
end
require_relative "web/helpers"
module CanvasSync::JobBatches::Compat::Sidekiq
module Web
DEV_MODE = (defined?(Rails) && !Rails.env.production?) || !!ENV["SIDEKIQ_WEB_TESTING"]
Sidekiq::WebHelpers::SAFE_QPARAMS << 'all_batches'
Sidekiq::WebHelpers::SAFE_QPARAMS << 'count'
def self.registered(app) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
app.helpers do
include Web::Helpers
def dev_mode?
DEV_MODE
end
end
# =============== BATCHES =============== #
app.get "/batches" do
@count = (params['count'] || 25).to_i
source_key = params['all_batches'] ? "batches" : "BID-ROOT-bids"
@current_page, @total_size, @batches = page(source_key, params['page'], @count)
@batches = @batches.map {|b, score| CanvasSync::JobBatches::Batch.new(b) }
erb(get_template(:batches))
end
app.get "/batches/:bid" do
@bid = params[:bid]
@batch = CanvasSync::JobBatches::Batch.new(@bid)
@tree_data = tree_data(@bid)
@count = (params['count'] || 25).to_i
@current_batches_page, @total_batches_size, @sub_batches = page("BID-#{@batch.bid}-bids", params['batch_page'], @count)
@sub_batches = @sub_batches.map {|b, score| CanvasSync::JobBatches::Batch.new(b) }
@current_jobs_page, @total_jobs_size, @jobs = page("BID-#{@batch.bid}-jids", params['job_page'], @count)
@jobs = @jobs.map do |jid, score|
{ jid: jid, }
end
erb(get_template(:batch))
end
app.get "/batches/:bid/tree" do
@bid = params[:bid]
json(tree_data(@bid, slice: params[:slice]))
end
app.helpers do
def tree_data(root_bid, slice: nil)
tree_bids = CanvasSync::JobBatches::Batch.bid_hierarchy(root_bid, slice: slice)
CanvasSync::JobBatches::Batch.redis do |r|
layer_data = ->(layer, parent = nil) {
bid = layer[0]
batch = CanvasSync::JobBatches::Batch.new(bid)
jobs_total = r.hget("BID-#{bid}", "job_count").to_i
jobs_pending = r.hget("BID-#{bid}", 'pending').to_i
jobs_failed = r.scard("BID-#{bid}-failed").to_i
jobs_dead = r.scard("BID-#{bid}-dead").to_i
jobs_success = jobs_total - jobs_pending
batches_total = r.hget("BID-#{bid}", 'children').to_i
batches_success = r.scard("BID-#{bid}-batches-success").to_i
batches_pending = batches_total - batches_success
batches_failed = r.scard("BID-#{bid}-batches-failed").to_i
status = 'in_progress'
status = 'complete' if batches_pending == batches_failed && jobs_pending == jobs_failed
status = 'success' if batches_pending == 0 && jobs_pending == 0
status = 'deleted' if bid != root_bid && !batch.parent_bid
{
bid: bid,
created_at: r.hget("BID-#{bid}", 'created_at'),
status: status,
parent_bid: parent ? parent.bid : batch.parent_bid,
description: batch.description,
jobs: {
pending_count: jobs_pending,
successful_count: jobs_success,
failed_count: jobs_failed,
dead_count: jobs_dead,
total_count: jobs_total,
# items: batches.map{|b| layer_data[b] },
},
batches: {
pending_count: batches_pending,
successful_count: batches_success,
failed_count: batches_failed,
total_count: batches_total,
items: layer[1].map{|b| layer_data[b, batch] },
},
}
}
data = layer_data[tree_bids]
data[:batches][:slice] = slice if slice
data
end
end
def format_context(batch)
bits = []
own_keys = batch.context.own.keys
batch.context.flatten.each do |k,v|
added = own_keys.include? k
bits << " \"#{k}\": #{v.to_json},"
end
bits = [
"{ // Added / Inherited",
*bits,
'}'
]
bits.join("\n")
end
end
app.post "/batches/all" do
if params['delete']
index_key = CanvasSync::JobBatches::Batch::INDEX_ALL_BATCHES ? "batches" : "BID-ROOT-bids"
drain_zset(index_key) do |batches|
batches.each do |bid|
CanvasSync::JobBatches::Batch.cleanup_redis(bid)
end
end
end
redirect "#{root_path}batches"
end
app.post "/batches/:bid" do
@bid = params[:bid]
@batch = CanvasSync::JobBatches::Batch.new(@bid)
if params['delete']
CanvasSync::JobBatches::Batch.delete_prematurely!(@bid)
end
redirect_with_query("#{root_path}batches")
end
# =============== POOLS =============== #
app.get "/pools" do
@count = (params['count'] || 25).to_i
@current_page, @total_size, @pools = page('pools', params['page'], @count)
@pools = @pools.map {|b, score| CanvasSync::JobBatches::Pool.new(b) }
erb(get_template(:pools))
end
app.get "/pools/:pid" do
@pid = params[:pid]
@pool = CanvasSync::JobBatches::Pool.new(@pid)
@active_tasks = @pool.active_jobs
@count = (params['count'] || 25).to_i
@current_jobs_page, @total_jobs_size, @jobs = page("POOLID-#{@pool.pid}-jobs", params['job_page'], @count)
@jobs = @jobs.map {|desc, score=nil| JSON.parse(desc)[0] }
erb(get_template(:pool))
end
app.post "/pools/all" do
if params['delete']
drain_zset('pools') do |pools|
pools.each do |pid|
CanvasSync::JobBatches::Pool.from_pid(pid).cleanup_redis
end
end
end
redirect "#{root_path}pools"
end
app.post "/pools/:pid" do
@pid = params[:pid]
@pool = CanvasSync::JobBatches::Pool.from_pid(@pid)
if params['delete']
@pool.cleanup_redis
end
redirect_with_query("#{root_path}pools")
end
end
end
end
if defined?(::Sidekiq::Web)
rules = []
rules = [[:all, {"Cache-Control" => "public, max-age=86400"}]] unless CanvasSync::JobBatches::Compat::Sidekiq::Web::DEV_MODE
::Sidekiq::Web.use Rack::Static, urls: ["/batches_assets"],
root: File.expand_path("#{File.dirname(__FILE__)}/web"),
cascade: true,
header_rules: rules
::Sidekiq::Web.register CanvasSync::JobBatches::Compat::Sidekiq::Web
::Sidekiq::Web.tabs["Batches"] = "batches"
::Sidekiq::Web.tabs["Pools"] = "pools"
::Sidekiq::Web.settings.locales << File.join(File.dirname(__FILE__), "locales")
end