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