mirror of
https://github.com/mperham/sidekiq.git
synced 2022-11-09 13:52:34 -05:00
Migrate Sidekiq::Web to a pure Rack application
Migrate Sidekiq::Web a pure Rack application to avoid sinatra as dependency. rack-protection is still needed. The application is mounted on top of Rack::Builder, mantaining all of the previous http interface. Rack apps being used: - Rack::File to serve assets - Rack::Session::Cookie, the secret can be configured via Sidekiq::Web.session_secret - Rack::Protection, same as before when using sinatra - Sidekiq::WebApplication, described below. Sidekiq::WebApplication is a very simple rack application composed of a Sidekiq::WebRouter and a Sidekiq::WebAction dispatcher. This terminology was adopted to be able to mantain Sidekiq::Web as a Rack app. The Router is heavily inspired on Rack::Router[0] (and in many parts identical), however not being retrocompatible. The Action is a wrapper to provide convenience, DRY code and maintain the old interface. I tried to mantain most of the old application structures so that customizations and monkey-patches are easily adjustable or even further work be done to enforce retrocompatibility. Testing welcome! 0: https://github.com/pjb3/rack-router
This commit is contained in:
parent
c89ff2e034
commit
9ea167db16
21 changed files with 519 additions and 263 deletions
|
@ -1,26 +1,30 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
require 'erb'
|
require 'erb'
|
||||||
require 'yaml'
|
require 'yaml'
|
||||||
require 'sinatra/base'
|
|
||||||
|
|
||||||
require 'sidekiq'
|
require 'sidekiq'
|
||||||
require 'sidekiq/api'
|
require 'sidekiq/api'
|
||||||
require 'sidekiq/paginator'
|
require 'sidekiq/paginator'
|
||||||
require 'sidekiq/web_helpers'
|
|
||||||
|
require 'sidekiq/web/router'
|
||||||
|
require 'sidekiq/web/application'
|
||||||
|
|
||||||
|
require 'rack/protection'
|
||||||
|
|
||||||
|
require 'rack/builder'
|
||||||
|
require 'rack/static'
|
||||||
|
require 'rack/session/cookie'
|
||||||
|
|
||||||
module Sidekiq
|
module Sidekiq
|
||||||
class Web < Sinatra::Base
|
class Web
|
||||||
include Sidekiq::Paginator
|
REQUEST_METHOD = 'REQUEST_METHOD'.freeze
|
||||||
|
PATH_INFO = 'PATH_INFO'.freeze
|
||||||
|
|
||||||
enable :sessions
|
ROOT = File.expand_path(File.dirname(__FILE__) + "/../../web")
|
||||||
use ::Rack::Protection, :use => :authenticity_token unless ENV['RACK_ENV'] == 'test'
|
VIEWS = "#{ROOT}/views"
|
||||||
|
LOCALES = ["#{ROOT}/locales"]
|
||||||
set :root, File.expand_path(File.dirname(__FILE__) + "/../../web")
|
LAYOUT = "#{VIEWS}/layout.erb"
|
||||||
set :public_folder, proc { "#{root}/assets" }
|
ASSETS = "#{ROOT}/assets"
|
||||||
set :views, proc { "#{root}/views" }
|
|
||||||
set :locales, ["#{root}/locales"]
|
|
||||||
|
|
||||||
helpers WebHelpers
|
|
||||||
|
|
||||||
DEFAULT_TABS = {
|
DEFAULT_TABS = {
|
||||||
"Dashboard" => '',
|
"Dashboard" => '',
|
||||||
|
@ -41,226 +45,56 @@ module Sidekiq
|
||||||
end
|
end
|
||||||
alias_method :tabs, :custom_tabs
|
alias_method :tabs, :custom_tabs
|
||||||
|
|
||||||
attr_accessor :app_url
|
def locales
|
||||||
|
@locales ||= LOCALES
|
||||||
|
end
|
||||||
|
|
||||||
|
def session_secret=(secret)
|
||||||
|
@secret = secret
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_accessor :app_url, :session_secret
|
||||||
|
attr_writer :locales
|
||||||
end
|
end
|
||||||
|
|
||||||
get "/busy" do
|
def initialize
|
||||||
erb :busy
|
secret = Web.session_secret
|
||||||
end
|
|
||||||
|
|
||||||
post "/busy" do
|
if secret.nil?
|
||||||
if params['identity']
|
# explicitly generating a session secret eagerly to play nice with preforking
|
||||||
p = Sidekiq::Process.new('identity' => params['identity'])
|
begin
|
||||||
p.quiet! if params[:quiet]
|
require 'securerandom'
|
||||||
p.stop! if params[:stop]
|
secret = SecureRandom.hex(64)
|
||||||
else
|
rescue LoadError, NotImplementedError
|
||||||
processes.each do |pro|
|
# SecureRandom raises a NotImplementedError if no random device is available
|
||||||
pro.quiet! if params[:quiet]
|
secret = "%064x" % Kernel.rand(2**256-1)
|
||||||
pro.stop! if params[:stop]
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
redirect "#{root_path}busy"
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/queues" do
|
@app = Rack::Builder.new do
|
||||||
@queues = Sidekiq::Queue.all
|
%w(stylesheets javascripts images).each do |asset_dir|
|
||||||
erb :queues
|
map "/#{asset_dir}" do
|
||||||
end
|
run Rack::File.new("#{ASSETS}/#{asset_dir}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
get "/queues/:name" do
|
use Rack::Session::Cookie, secret: secret
|
||||||
halt 404 unless params[:name]
|
use ::Rack::Protection, use: :authenticity_token unless ENV['RACK_ENV'] == 'test'
|
||||||
@count = (params[:count] || 25).to_i
|
|
||||||
@name = params[:name]
|
|
||||||
@queue = Sidekiq::Queue.new(@name)
|
|
||||||
(@current_page, @total_size, @messages) = page("queue:#{@name}", params[:page], @count)
|
|
||||||
@messages = @messages.map { |msg| Sidekiq::Job.new(msg, @name) }
|
|
||||||
erb :queue
|
|
||||||
end
|
|
||||||
|
|
||||||
post "/queues/:name" do
|
run WebApplication.new
|
||||||
Sidekiq::Queue.new(params[:name]).clear
|
|
||||||
redirect "#{root_path}queues"
|
|
||||||
end
|
|
||||||
|
|
||||||
post "/queues/:name/delete" do
|
|
||||||
Sidekiq::Job.new(params[:key_val], params[:name]).delete
|
|
||||||
redirect_with_query("#{root_path}queues/#{params[:name]}")
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/morgue' do
|
|
||||||
@count = (params[:count] || 25).to_i
|
|
||||||
(@current_page, @total_size, @dead) = page("dead", params[:page], @count, reverse: true)
|
|
||||||
@dead = @dead.map { |msg, score| Sidekiq::SortedEntry.new(nil, score, msg) }
|
|
||||||
erb :morgue
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/morgue/:key" do
|
|
||||||
halt 404 unless params['key']
|
|
||||||
@dead = Sidekiq::DeadSet.new.fetch(*parse_params(params['key'])).first
|
|
||||||
redirect "#{root_path}morgue" if @dead.nil?
|
|
||||||
erb :dead
|
|
||||||
end
|
|
||||||
|
|
||||||
post '/morgue' do
|
|
||||||
redirect request.path unless params['key']
|
|
||||||
|
|
||||||
params['key'].each do |key|
|
|
||||||
job = Sidekiq::DeadSet.new.fetch(*parse_params(key)).first
|
|
||||||
retry_or_delete_or_kill job, params if job
|
|
||||||
end
|
|
||||||
redirect_with_query("#{root_path}morgue")
|
|
||||||
end
|
|
||||||
|
|
||||||
post "/morgue/all/delete" do
|
|
||||||
Sidekiq::DeadSet.new.clear
|
|
||||||
redirect "#{root_path}morgue"
|
|
||||||
end
|
|
||||||
|
|
||||||
post "/morgue/all/retry" do
|
|
||||||
Sidekiq::DeadSet.new.retry_all
|
|
||||||
redirect "#{root_path}morgue"
|
|
||||||
end
|
|
||||||
|
|
||||||
post "/morgue/:key" do
|
|
||||||
halt 404 unless params['key']
|
|
||||||
job = Sidekiq::DeadSet.new.fetch(*parse_params(params['key'])).first
|
|
||||||
retry_or_delete_or_kill job, params if job
|
|
||||||
redirect_with_query("#{root_path}morgue")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
get '/retries' do
|
|
||||||
@count = (params[:count] || 25).to_i
|
|
||||||
(@current_page, @total_size, @retries) = page("retry", params[:page], @count)
|
|
||||||
@retries = @retries.map { |msg, score| Sidekiq::SortedEntry.new(nil, score, msg) }
|
|
||||||
erb :retries
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/retries/:key" do
|
|
||||||
@retry = Sidekiq::RetrySet.new.fetch(*parse_params(params['key'])).first
|
|
||||||
redirect "#{root_path}retries" if @retry.nil?
|
|
||||||
erb :retry
|
|
||||||
end
|
|
||||||
|
|
||||||
post '/retries' do
|
|
||||||
redirect request.path unless params['key']
|
|
||||||
|
|
||||||
params['key'].each do |key|
|
|
||||||
job = Sidekiq::RetrySet.new.fetch(*parse_params(key)).first
|
|
||||||
retry_or_delete_or_kill job, params if job
|
|
||||||
end
|
|
||||||
redirect_with_query("#{root_path}retries")
|
|
||||||
end
|
|
||||||
|
|
||||||
post "/retries/all/delete" do
|
|
||||||
Sidekiq::RetrySet.new.clear
|
|
||||||
redirect "#{root_path}retries"
|
|
||||||
end
|
|
||||||
|
|
||||||
post "/retries/all/retry" do
|
|
||||||
Sidekiq::RetrySet.new.retry_all
|
|
||||||
redirect "#{root_path}retries"
|
|
||||||
end
|
|
||||||
|
|
||||||
post "/retries/:key" do
|
|
||||||
job = Sidekiq::RetrySet.new.fetch(*parse_params(params['key'])).first
|
|
||||||
retry_or_delete_or_kill job, params if job
|
|
||||||
redirect_with_query("#{root_path}retries")
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/scheduled' do
|
|
||||||
@count = (params[:count] || 25).to_i
|
|
||||||
(@current_page, @total_size, @scheduled) = page("schedule", params[:page], @count)
|
|
||||||
@scheduled = @scheduled.map { |msg, score| Sidekiq::SortedEntry.new(nil, score, msg) }
|
|
||||||
erb :scheduled
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/scheduled/:key" do
|
|
||||||
@job = Sidekiq::ScheduledSet.new.fetch(*parse_params(params['key'])).first
|
|
||||||
redirect "#{root_path}scheduled" if @job.nil?
|
|
||||||
erb :scheduled_job_info
|
|
||||||
end
|
|
||||||
|
|
||||||
post '/scheduled' do
|
|
||||||
redirect request.path unless params['key']
|
|
||||||
|
|
||||||
params['key'].each do |key|
|
|
||||||
job = Sidekiq::ScheduledSet.new.fetch(*parse_params(key)).first
|
|
||||||
delete_or_add_queue job, params if job
|
|
||||||
end
|
|
||||||
redirect_with_query("#{root_path}scheduled")
|
|
||||||
end
|
|
||||||
|
|
||||||
post "/scheduled/:key" do
|
|
||||||
halt 404 unless params['key']
|
|
||||||
job = Sidekiq::ScheduledSet.new.fetch(*parse_params(params['key'])).first
|
|
||||||
delete_or_add_queue job, params if job
|
|
||||||
redirect_with_query("#{root_path}scheduled")
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/' do
|
|
||||||
@redis_info = redis_info.select{ |k, v| REDIS_KEYS.include? k }
|
|
||||||
stats_history = Sidekiq::Stats::History.new((params[:days] || 30).to_i)
|
|
||||||
@processed_history = stats_history.processed
|
|
||||||
@failed_history = stats_history.failed
|
|
||||||
erb :dashboard
|
|
||||||
end
|
|
||||||
|
|
||||||
REDIS_KEYS = %w(redis_version uptime_in_days connected_clients used_memory_human used_memory_peak_human)
|
|
||||||
|
|
||||||
get '/dashboard/stats' do
|
|
||||||
redirect "#{root_path}stats"
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/stats' do
|
|
||||||
sidekiq_stats = Sidekiq::Stats.new
|
|
||||||
redis_stats = redis_info.select { |k, v| REDIS_KEYS.include? k }
|
|
||||||
|
|
||||||
content_type :json
|
|
||||||
Sidekiq.dump_json(
|
|
||||||
sidekiq: {
|
|
||||||
processed: sidekiq_stats.processed,
|
|
||||||
failed: sidekiq_stats.failed,
|
|
||||||
busy: sidekiq_stats.workers_size,
|
|
||||||
processes: sidekiq_stats.processes_size,
|
|
||||||
enqueued: sidekiq_stats.enqueued,
|
|
||||||
scheduled: sidekiq_stats.scheduled_size,
|
|
||||||
retries: sidekiq_stats.retry_size,
|
|
||||||
dead: sidekiq_stats.dead_size,
|
|
||||||
default_latency: sidekiq_stats.default_queue_latency
|
|
||||||
},
|
|
||||||
redis: redis_stats
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/stats/queues' do
|
|
||||||
queue_stats = Sidekiq::Stats::Queues.new
|
|
||||||
|
|
||||||
content_type :json
|
|
||||||
Sidekiq.dump_json(
|
|
||||||
queue_stats.lengths
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def retry_or_delete_or_kill job, params
|
|
||||||
if params['retry']
|
|
||||||
job.retry
|
|
||||||
elsif params['delete']
|
|
||||||
job.delete
|
|
||||||
elsif params['kill']
|
|
||||||
job.kill
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_or_add_queue job, params
|
def call(env)
|
||||||
if params['delete']
|
@app.call(env)
|
||||||
job.delete
|
|
||||||
elsif params['add_to_queue']
|
|
||||||
job.add_to_queue
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.call(env)
|
||||||
|
@app ||= new
|
||||||
|
@app.call(env)
|
||||||
|
end
|
||||||
|
|
||||||
|
ERB.new(File.read LAYOUT).def_method(WebAction, '_render')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
245
lib/sidekiq/web/application.rb
Normal file
245
lib/sidekiq/web/application.rb
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
module Sidekiq
|
||||||
|
class WebApplication
|
||||||
|
extend WebRouter
|
||||||
|
|
||||||
|
REDIS_KEYS = %w(redis_version uptime_in_days connected_clients used_memory_human used_memory_peak_human)
|
||||||
|
|
||||||
|
get "/" do
|
||||||
|
@redis_info = redis_info.select{ |k, v| REDIS_KEYS.include? k }
|
||||||
|
stats_history = Sidekiq::Stats::History.new((params['days'] || 30).to_i)
|
||||||
|
@processed_history = stats_history.processed
|
||||||
|
@failed_history = stats_history.failed
|
||||||
|
|
||||||
|
render(:dashboard)
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/busy" do
|
||||||
|
render(:busy)
|
||||||
|
end
|
||||||
|
|
||||||
|
post "/busy" do
|
||||||
|
if params['identity']
|
||||||
|
p = Sidekiq::Process.new('identity' => params['identity'])
|
||||||
|
p.quiet! if params['quiet']
|
||||||
|
p.stop! if params['stop']
|
||||||
|
else
|
||||||
|
processes.each do |pro|
|
||||||
|
pro.quiet! if params['quiet']
|
||||||
|
pro.stop! if params['stop']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
redirect "busy"
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/queues" do
|
||||||
|
@queues = Sidekiq::Queue.all
|
||||||
|
|
||||||
|
render(:queues)
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/queues/:name" do
|
||||||
|
@name = route_params[:name]
|
||||||
|
|
||||||
|
next(not_found(env)) unless @name
|
||||||
|
|
||||||
|
@count = (params['count'] || 25).to_i
|
||||||
|
@queue = Sidekiq::Queue.new(@name)
|
||||||
|
(@current_page, @total_size, @messages) = page("queue:#{@name}", params['page'], @count)
|
||||||
|
@messages = @messages.map { |msg| Sidekiq::Job.new(msg, @name) }
|
||||||
|
|
||||||
|
render(:queue)
|
||||||
|
end
|
||||||
|
|
||||||
|
post "/queues/:name" do
|
||||||
|
Sidekiq::Queue.new(route_params[:name]).clear
|
||||||
|
|
||||||
|
redirect "queues"
|
||||||
|
end
|
||||||
|
|
||||||
|
post "/queues/:name/delete" do
|
||||||
|
name = route_params[:name]
|
||||||
|
Sidekiq::Job.new(params['key_val'], name).delete
|
||||||
|
|
||||||
|
redirect_with_query("queues/#{name}")
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/morgue' do
|
||||||
|
@count = (params['count'] || 25).to_i
|
||||||
|
(@current_page, @total_size, @dead) = page("dead", params['page'], @count, reverse: true)
|
||||||
|
@dead = @dead.map { |msg, score| Sidekiq::SortedEntry.new(nil, score, msg) }
|
||||||
|
|
||||||
|
render(:morgue)
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/morgue/:key" do
|
||||||
|
next not_found(env) unless key = route_params[:key]
|
||||||
|
|
||||||
|
@dead = Sidekiq::DeadSet.new.fetch(*parse_params(key)).first
|
||||||
|
|
||||||
|
if @dead.nil?
|
||||||
|
redirect "morgue"
|
||||||
|
else
|
||||||
|
render(:dead)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
post '/morgue' do
|
||||||
|
next redirect(request.path) unless params['key']
|
||||||
|
|
||||||
|
params['key'].each do |key|
|
||||||
|
job = Sidekiq::DeadSet.new.fetch(*parse_params(key)).first
|
||||||
|
retry_or_delete_or_kill job, params if job
|
||||||
|
end
|
||||||
|
|
||||||
|
redirect_with_query("morgue")
|
||||||
|
end
|
||||||
|
|
||||||
|
post "/morgue/all/delete" do
|
||||||
|
Sidekiq::DeadSet.new.clear
|
||||||
|
|
||||||
|
redirect "morgue"
|
||||||
|
end
|
||||||
|
|
||||||
|
post "/morgue/all/retry" do
|
||||||
|
Sidekiq::DeadSet.new.retry_all
|
||||||
|
|
||||||
|
redirect "morgue"
|
||||||
|
end
|
||||||
|
|
||||||
|
post "/morgue/:key" do
|
||||||
|
next not_found(env) unless key = route_params[:key]
|
||||||
|
|
||||||
|
job = Sidekiq::DeadSet.new.fetch(*parse_params(key)).first
|
||||||
|
retry_or_delete_or_kill job, params if job
|
||||||
|
|
||||||
|
redirect_with_query("morgue")
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/retries' do
|
||||||
|
@count = (params['count'] || 25).to_i
|
||||||
|
(@current_page, @total_size, @retries) = page("retry", params['page'], @count)
|
||||||
|
@retries = @retries.map { |msg, score| Sidekiq::SortedEntry.new(nil, score, msg) }
|
||||||
|
|
||||||
|
render(:retries)
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/retries/:key" do
|
||||||
|
@retry = Sidekiq::RetrySet.new.fetch(*parse_params(route_params[:key])).first
|
||||||
|
|
||||||
|
if @retry.nil?
|
||||||
|
redirect "retries"
|
||||||
|
else
|
||||||
|
render(:retry)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
post '/retries' do
|
||||||
|
next redirect(request.path) unless params['key']
|
||||||
|
|
||||||
|
params['key'].each do |key|
|
||||||
|
job = Sidekiq::RetrySet.new.fetch(*parse_params(key)).first
|
||||||
|
retry_or_delete_or_kill job, params if job
|
||||||
|
end
|
||||||
|
|
||||||
|
redirect_with_query("retries")
|
||||||
|
end
|
||||||
|
|
||||||
|
post "/retries/all/delete" do
|
||||||
|
Sidekiq::RetrySet.new.clear
|
||||||
|
|
||||||
|
redirect "retries"
|
||||||
|
end
|
||||||
|
|
||||||
|
post "/retries/all/retry" do
|
||||||
|
Sidekiq::RetrySet.new.retry_all
|
||||||
|
|
||||||
|
redirect "retries"
|
||||||
|
end
|
||||||
|
|
||||||
|
post "/retries/:key" do
|
||||||
|
job = Sidekiq::RetrySet.new.fetch(*parse_params(route_params[:key])).first
|
||||||
|
|
||||||
|
retry_or_delete_or_kill job, params if job
|
||||||
|
|
||||||
|
redirect_with_query("retries")
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/scheduled' do
|
||||||
|
@count = (params['count'] || 25).to_i
|
||||||
|
(@current_page, @total_size, @scheduled) = page("schedule", params['page'], @count)
|
||||||
|
@scheduled = @scheduled.map { |msg, score| Sidekiq::SortedEntry.new(nil, score, msg) }
|
||||||
|
|
||||||
|
render(:scheduled)
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/scheduled/:key" do
|
||||||
|
@job = Sidekiq::ScheduledSet.new.fetch(*parse_params(route_params[:key])).first
|
||||||
|
|
||||||
|
if @job.nil?
|
||||||
|
redirect "scheduled"
|
||||||
|
else
|
||||||
|
render(:scheduled_job_info)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
post '/scheduled' do
|
||||||
|
next redirect(request.path) unless params['key']
|
||||||
|
|
||||||
|
params['key'].each do |key|
|
||||||
|
job = Sidekiq::ScheduledSet.new.fetch(*parse_params(key)).first
|
||||||
|
delete_or_add_queue job, params if job
|
||||||
|
end
|
||||||
|
|
||||||
|
redirect_with_query("scheduled")
|
||||||
|
end
|
||||||
|
|
||||||
|
post "/scheduled/:key" do
|
||||||
|
next not_found(env) unless key = route_params[:key]
|
||||||
|
|
||||||
|
job = Sidekiq::ScheduledSet.new.fetch(*parse_params(key)).first
|
||||||
|
delete_or_add_queue job, params if job
|
||||||
|
|
||||||
|
redirect_with_query("scheduled")
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/dashboard/stats' do
|
||||||
|
redirect "stats"
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/stats' do
|
||||||
|
sidekiq_stats = Sidekiq::Stats.new
|
||||||
|
redis_stats = redis_info.select { |k, v| REDIS_KEYS.include? k }
|
||||||
|
|
||||||
|
json(
|
||||||
|
sidekiq: {
|
||||||
|
processed: sidekiq_stats.processed,
|
||||||
|
failed: sidekiq_stats.failed,
|
||||||
|
busy: sidekiq_stats.workers_size,
|
||||||
|
processes: sidekiq_stats.processes_size,
|
||||||
|
enqueued: sidekiq_stats.enqueued,
|
||||||
|
scheduled: sidekiq_stats.scheduled_size,
|
||||||
|
retries: sidekiq_stats.retry_size,
|
||||||
|
dead: sidekiq_stats.dead_size,
|
||||||
|
default_latency: sidekiq_stats.default_queue_latency
|
||||||
|
},
|
||||||
|
redis: redis_stats
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/stats/queues' do
|
||||||
|
json Sidekiq::Stats::Queues.new.lengths
|
||||||
|
end
|
||||||
|
|
||||||
|
def not_found(env)
|
||||||
|
[404, {}, []]
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(env)
|
||||||
|
action = self.class.match(env) || WebAction.new(env, method(:not_found).to_proc)
|
||||||
|
|
||||||
|
action.instance_exec env, &action.app
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -9,7 +9,7 @@ module Sidekiq
|
||||||
@@strings[lang] ||= begin
|
@@strings[lang] ||= begin
|
||||||
# Allow sidekiq-web extensions to add locale paths
|
# Allow sidekiq-web extensions to add locale paths
|
||||||
# so extensions can be localized
|
# so extensions can be localized
|
||||||
settings.locales.each_with_object({}) do |path, global|
|
Web.locales.each_with_object({}) do |path, global|
|
||||||
find_locale_files(lang).each do |file|
|
find_locale_files(lang).each do |file|
|
||||||
strs = YAML.load(File.open(file))
|
strs = YAML.load(File.open(file))
|
||||||
global.deep_merge!(strs[lang])
|
global.deep_merge!(strs[lang])
|
||||||
|
@ -24,7 +24,7 @@ module Sidekiq
|
||||||
end
|
end
|
||||||
|
|
||||||
def locale_files
|
def locale_files
|
||||||
@@locale_files ||= settings.locales.flat_map do |path|
|
@@locale_files ||= Web.locales.flat_map do |path|
|
||||||
Dir["#{path}/*.yml"]
|
Dir["#{path}/*.yml"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -69,7 +69,7 @@ module Sidekiq
|
||||||
def locale
|
def locale
|
||||||
@locale ||= begin
|
@locale ||= begin
|
||||||
locale = 'en'.freeze
|
locale = 'en'.freeze
|
||||||
languages = request.env['HTTP_ACCEPT_LANGUAGE'.freeze] || 'en'.freeze
|
languages = env['HTTP_ACCEPT_LANGUAGE'.freeze] || 'en'.freeze
|
||||||
languages.downcase.split(','.freeze).each do |lang|
|
languages.downcase.split(','.freeze).each do |lang|
|
||||||
next if lang == '*'.freeze
|
next if lang == '*'.freeze
|
||||||
lang = lang.split(';'.freeze)[0]
|
lang = lang.split(';'.freeze)[0]
|
173
lib/sidekiq/web/router.rb
Normal file
173
lib/sidekiq/web/router.rb
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
require 'sidekiq/web/helpers'
|
||||||
|
|
||||||
|
module Sidekiq
|
||||||
|
module WebRouter
|
||||||
|
GET = 'GET'.freeze
|
||||||
|
POST = 'POST'.freeze
|
||||||
|
HEAD = 'HEAD'.freeze
|
||||||
|
|
||||||
|
ROUTE_PARAMS = 'rack.route_params'.freeze
|
||||||
|
REQUEST_METHOD = 'REQUEST_METHOD'.freeze
|
||||||
|
PATH_INFO = 'PATH_INFO'.freeze
|
||||||
|
|
||||||
|
def get(path, &block)
|
||||||
|
route(GET, path, &block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def post(path, &block)
|
||||||
|
route(POST, path, &block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def route(method, path, &block)
|
||||||
|
@routes ||= []
|
||||||
|
@routes << WebRoute.new(method, path, block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def match(env)
|
||||||
|
request_method = env[REQUEST_METHOD]
|
||||||
|
request_method = GET if request_method == HEAD
|
||||||
|
@routes.each do |route|
|
||||||
|
if params = route.match(request_method, env[PATH_INFO])
|
||||||
|
env[ROUTE_PARAMS] = params
|
||||||
|
return WebAction.new(env, route.app)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class WebAction
|
||||||
|
include WebHelpers
|
||||||
|
include Sidekiq::Paginator
|
||||||
|
|
||||||
|
RACK_SESSION = 'rack.session'.freeze
|
||||||
|
|
||||||
|
CONTENT_TYPE = "Content-Type".freeze
|
||||||
|
LOCATION = "Location".freeze
|
||||||
|
|
||||||
|
TEXT_HTML = "text/html".freeze
|
||||||
|
APPLICATION_JSON = "application/json".freeze
|
||||||
|
|
||||||
|
attr_accessor :env, :app
|
||||||
|
|
||||||
|
def request
|
||||||
|
@request ||= Rack::Request.new(env)
|
||||||
|
end
|
||||||
|
|
||||||
|
def params
|
||||||
|
request.params
|
||||||
|
end
|
||||||
|
|
||||||
|
def route_params
|
||||||
|
env[WebRouter::ROUTE_PARAMS]
|
||||||
|
end
|
||||||
|
|
||||||
|
def session
|
||||||
|
env[RACK_SESSION]
|
||||||
|
end
|
||||||
|
|
||||||
|
def render(file)
|
||||||
|
output = _render { ERB.new(File.read "#{Web::VIEWS}/#{file}.erb").result(binding) }
|
||||||
|
|
||||||
|
[200, { CONTENT_TYPE => TEXT_HTML }, [output]]
|
||||||
|
end
|
||||||
|
|
||||||
|
def redirect(location)
|
||||||
|
[302, { LOCATION => "#{request.base_url}#{root_path}#{location}" }, []]
|
||||||
|
end
|
||||||
|
|
||||||
|
def json(payload)
|
||||||
|
[200, { CONTENT_TYPE => APPLICATION_JSON }, [Sidekiq.dump_json(payload)]]
|
||||||
|
end
|
||||||
|
|
||||||
|
def partial(file, locals = {})
|
||||||
|
ERB.new(File.read "#{Web::VIEWS}/_#{file}.erb").result(binding)
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(env, app)
|
||||||
|
@env = env
|
||||||
|
@app = app
|
||||||
|
end
|
||||||
|
|
||||||
|
def retry_or_delete_or_kill(job, params)
|
||||||
|
if params['retry']
|
||||||
|
job.retry
|
||||||
|
elsif params['delete']
|
||||||
|
job.delete
|
||||||
|
elsif params['kill']
|
||||||
|
job.kill
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete_or_add_queue(job, params)
|
||||||
|
if params['delete']
|
||||||
|
job.delete
|
||||||
|
elsif params['add_to_queue']
|
||||||
|
job.add_to_queue
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class WebRoute
|
||||||
|
attr_accessor :request_method, :pattern, :app, :constraints, :name
|
||||||
|
|
||||||
|
NAMED_SEGMENTS_PATTERN = /\/([^\/]*):([^:$\/]+)/.freeze
|
||||||
|
|
||||||
|
def initialize(request_method, pattern, app)
|
||||||
|
@request_method = request_method
|
||||||
|
@pattern = pattern
|
||||||
|
@app = app
|
||||||
|
end
|
||||||
|
|
||||||
|
def regexp
|
||||||
|
@regexp ||= compile
|
||||||
|
end
|
||||||
|
|
||||||
|
def compile
|
||||||
|
p = if pattern.match(NAMED_SEGMENTS_PATTERN)
|
||||||
|
pattern.gsub(NAMED_SEGMENTS_PATTERN, '/\1(?<\2>[^$/]+)')
|
||||||
|
else
|
||||||
|
pattern
|
||||||
|
end
|
||||||
|
|
||||||
|
Regexp.new("\\A#{p}\\Z")
|
||||||
|
end
|
||||||
|
|
||||||
|
def match(request_method, path)
|
||||||
|
return nil unless request_method == self.request_method
|
||||||
|
|
||||||
|
if path_match = path.match(regexp)
|
||||||
|
params = Hash[path_match.names.map(&:to_sym).zip(path_match.captures)]
|
||||||
|
|
||||||
|
params if meets_constraints(params)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def meets_constraints(params)
|
||||||
|
if constraints
|
||||||
|
constraints.each do |param, constraint|
|
||||||
|
unless params[param].to_s.match(constraint)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def eql?(o)
|
||||||
|
o.is_a?(self.class) &&
|
||||||
|
o.request_method == request_method &&
|
||||||
|
o.pattern == pattern &&
|
||||||
|
o.app == app &&
|
||||||
|
o.constraints == constraints
|
||||||
|
end
|
||||||
|
alias == eql?
|
||||||
|
|
||||||
|
def hash
|
||||||
|
request_method.hash ^ pattern.hash ^ app.hash ^ constraints.hash
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -18,4 +18,4 @@ gem 'sidekiq', :path => '..'
|
||||||
#de gem 'pry-byebug'
|
#de gem 'pry-byebug'
|
||||||
|
|
||||||
# sidekiq-web dependencies
|
# sidekiq-web dependencies
|
||||||
gem 'sinatra'
|
gem 'rack-protection'
|
||||||
|
|
|
@ -18,7 +18,7 @@ Gem::Specification.new do |gem|
|
||||||
gem.add_dependency 'redis', '~> 3.2', '>= 3.2.1'
|
gem.add_dependency 'redis', '~> 3.2', '>= 3.2.1'
|
||||||
gem.add_dependency 'connection_pool', '~> 2.2', '>= 2.2.0'
|
gem.add_dependency 'connection_pool', '~> 2.2', '>= 2.2.0'
|
||||||
gem.add_dependency 'concurrent-ruby', '~> 1.0'
|
gem.add_dependency 'concurrent-ruby', '~> 1.0'
|
||||||
gem.add_dependency 'sinatra', '>= 1.4.7'
|
gem.add_dependency 'rack-protection', '~> 1.5'
|
||||||
gem.add_development_dependency 'redis-namespace', '~> 1.5', '>= 1.5.2'
|
gem.add_development_dependency 'redis-namespace', '~> 1.5', '>= 1.5.2'
|
||||||
gem.add_development_dependency 'minitest', '~> 5.7', '>= 5.7.0'
|
gem.add_development_dependency 'minitest', '~> 5.7', '>= 5.7.0'
|
||||||
gem.add_development_dependency 'rake', '~> 10.0'
|
gem.add_development_dependency 'rake', '~> 10.0'
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
require_relative 'helper'
|
require_relative 'helper'
|
||||||
require 'sidekiq/web'
|
require 'sidekiq/web'
|
||||||
require 'rack/test'
|
require 'rack/test'
|
||||||
require 'tilt/erubis'
|
#require 'tilt/erubis'
|
||||||
|
|
||||||
class TestWeb < Sidekiq::Test
|
class TestWeb < Sidekiq::Test
|
||||||
|
|
||||||
|
@ -341,7 +341,6 @@ class TestWeb < Sidekiq::Test
|
||||||
assert last_response.body.include?( "<a>hello</a>" )
|
assert last_response.body.include?( "<a>hello</a>" )
|
||||||
assert !last_response.body.include?( "<a>hello</a>" )
|
assert !last_response.body.include?( "<a>hello</a>" )
|
||||||
|
|
||||||
|
|
||||||
# on /queues page
|
# on /queues page
|
||||||
params = add_xss_retry # sorry, don't know how to easily make this show up on queues page otherwise.
|
params = add_xss_retry # sorry, don't know how to easily make this show up on queues page otherwise.
|
||||||
post "/retries/#{job_params(*params)}", 'retry' => 'Retry'
|
post "/retries/#{job_params(*params)}", 'retry' => 'Retry'
|
||||||
|
@ -372,21 +371,23 @@ class TestWeb < Sidekiq::Test
|
||||||
|
|
||||||
describe 'custom locales' do
|
describe 'custom locales' do
|
||||||
before do
|
before do
|
||||||
Sidekiq::Web.settings.locales << File.join(File.dirname(__FILE__), "fixtures")
|
Sidekiq::Web.locales << File.join(File.dirname(__FILE__), "fixtures")
|
||||||
Sidekiq::Web.tabs['Custom Tab'] = '/custom'
|
Sidekiq::Web.tabs['Custom Tab'] = '/custom'
|
||||||
Sidekiq::Web.get('/custom') do
|
Sidekiq::WebApplication.get('/custom') do
|
||||||
clear_caches # ugly hack since I can't figure out how to access WebHelpers outside of this context
|
clear_caches # ugly hack since I can't figure out how to access WebHelpers outside of this context
|
||||||
t('translated_text')
|
|
||||||
|
[200, { "Content-Type" => 'text/html' }, [ t('translated_text') ]]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
after do
|
after do
|
||||||
Sidekiq::Web.tabs.delete 'Custom Tab'
|
Sidekiq::Web.tabs.delete 'Custom Tab'
|
||||||
Sidekiq::Web.settings.locales.pop
|
Sidekiq::Web.locales.pop
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'can show user defined tab with custom locales' do
|
it 'can show user defined tab with custom locales' do
|
||||||
get '/custom'
|
get '/custom'
|
||||||
|
|
||||||
assert_match(/Changed text/, last_response.body)
|
assert_match(/Changed text/, last_response.body)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -564,6 +565,7 @@ class TestWeb < Sidekiq::Test
|
||||||
Sidekiq.redis do |conn|
|
Sidekiq.redis do |conn|
|
||||||
conn.zadd('retry', score, Sidekiq.dump_json(msg))
|
conn.zadd('retry', score, Sidekiq.dump_json(msg))
|
||||||
end
|
end
|
||||||
|
|
||||||
[msg, score]
|
[msg, score]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
<% job = locals[:job] %>
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
<h3><%= t('Job') %></h3>
|
<h3><%= t('Job') %></h3>
|
||||||
</header>
|
</header>
|
||||||
|
@ -50,7 +52,7 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if type == :retry %>
|
<% if locals[:type] == :retry %>
|
||||||
<% if job['retry_count'] && job['retry_count'] > 0 %>
|
<% if job['retry_count'] && job['retry_count'] > 0 %>
|
||||||
<tr>
|
<tr>
|
||||||
<th><%= t('RetryCount') %></th>
|
<th><%= t('RetryCount') %></th>
|
||||||
|
@ -71,13 +73,13 @@
|
||||||
<td><%= relative_time(job.at) %></td>
|
<td><%= relative_time(job.at) %></td>
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if type == :scheduled %>
|
<% if locals[:type] == :scheduled %>
|
||||||
<tr>
|
<tr>
|
||||||
<th><%= t('Scheduled') %></th>
|
<th><%= t('Scheduled') %></th>
|
||||||
<td><%= relative_time(job.at) %></td>
|
<td><%= relative_time(job.at) %></td>
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if type == :dead %>
|
<% if locals[:type] == :dead %>
|
||||||
<tr>
|
<tr>
|
||||||
<th><%= t('LastRetry') %></th>
|
<th><%= t('LastRetry') %></th>
|
||||||
<td><%= relative_time(job.at) %></td>
|
<td><%= relative_time(job.at) %></td>
|
||||||
|
|
|
@ -7,14 +7,14 @@
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="navbar-toggle collapsed navbar-livereload">
|
<div class="navbar-toggle collapsed navbar-livereload">
|
||||||
<%= erb :_poll_link %>
|
<%= partial :poll_link %>
|
||||||
<% if Sidekiq::Web.app_url %>
|
<% if Sidekiq::Web.app_url %>
|
||||||
<a class="btn btn-inverse" href="<%= Sidekiq::Web.app_url %>">Back to App</a>
|
<a class="btn btn-inverse" href="<%= Sidekiq::Web.app_url %>">Back to App</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<a class="navbar-brand" href="<%= root_path %>">
|
<a class="navbar-brand" href="<%= root_path %>">
|
||||||
<%= Sidekiq::NAME %>
|
<%= Sidekiq::NAME %>
|
||||||
<%= erb :_status %>
|
<%= partial :status %>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
<ul class="nav navbar-nav navbar-right navbar-livereload" data-navbar="static">
|
<ul class="nav navbar-nav navbar-right navbar-livereload" data-navbar="static">
|
||||||
<li>
|
<li>
|
||||||
<div class="poll-wrapper pull-right">
|
<div class="poll-wrapper pull-right">
|
||||||
<%= erb :_poll_link %>
|
<%= partial :poll_link %>
|
||||||
<% if Sidekiq::Web.app_url %>
|
<% if Sidekiq::Web.app_url %>
|
||||||
<a class="btn btn-inverse" href="<%= Sidekiq::Web.app_url %>"><%= t('BackToApp') %></a>
|
<a class="btn btn-inverse" href="<%= Sidekiq::Web.app_url %>"><%= t('BackToApp') %></a>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
<% if @total_size > @count %>
|
<% if @total_size > @count %>
|
||||||
<ul class="pagination pull-right">
|
<ul class="pagination pull-right">
|
||||||
<li class="<%= 'disabled' if @current_page == 1 %>">
|
<li class="<%= 'disabled' if @current_page == 1 %>">
|
||||||
<a href="<%= url %>?page=1">«</a>
|
<a href="<%= locals[:url] %>?page=1">«</a>
|
||||||
</li>
|
</li>
|
||||||
<% if @current_page > 1 %>
|
<% if @current_page > 1 %>
|
||||||
<li>
|
<li>
|
||||||
<a href="<%= url %>?<%= qparams(page: @current_page - 1) %>"><%= @current_page - 1 %></a>
|
<a href="<%= locals[:url] %>?<%= qparams(page: @current_page - 1) %>"><%= @current_page - 1 %></a>
|
||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
<li class="disabled">
|
<li class="disabled">
|
||||||
<a href="<%= url %>?<%= qparams(page: @current_page) %>"><%= @current_page %></a>
|
<a href="<%= locals[:url] %>?<%= qparams(page: @current_page) %>"><%= @current_page %></a>
|
||||||
</li>
|
</li>
|
||||||
<% if @total_size > @current_page * @count %>
|
<% if @total_size > @current_page * @count %>
|
||||||
<li>
|
<li>
|
||||||
<a href="<%= url %>?<%= qparams(page: @current_page + 1) %>"><%= @current_page + 1 %></a>
|
<a href="<%= locals[:url] %>?<%= qparams(page: @current_page + 1) %>"><%= @current_page + 1 %></a>
|
||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
<li class="<%= 'disabled' if @total_size <= @current_page * @count %>">
|
<li class="<%= 'disabled' if @total_size <= @current_page * @count %>">
|
||||||
<a href="<%= url %>?<%= qparams(page: (@total_size.to_f / @count).ceil) %>">»</a>
|
<a href="<%= locals[:url] %>?<%= qparams(page: (@total_size.to_f / @count).ceil) %>">»</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<% if current_path != '' && params[:poll] %>
|
<% if current_path != '' && params['poll'] %>
|
||||||
<script>
|
<script>
|
||||||
updatePage('<%= root_path + current_path %>')
|
updatePage('<%= root_path + current_path %>')
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<% if current_path != '' %>
|
<% if current_path != '' %>
|
||||||
<% if params[:poll] %>
|
<% if params['poll'] %>
|
||||||
<a id="live-poll" class="btn btn-primary active" href="<%= root_path + current_path %>"><%= t('StopPolling') %></a>
|
<a id="live-poll" class="btn btn-primary active" href="<%= root_path + current_path %>"><%= t('StopPolling') %></a>
|
||||||
<% else %>
|
<% else %>
|
||||||
<a id="live-poll" class="btn btn-primary" href="<%= root_path + current_path %>?<%= qparams(poll: true) %>"><%= t('LivePoll') %></a>
|
<a id="live-poll" class="btn btn-primary" href="<%= root_path + current_path %>?<%= qparams(poll: true) %>"><%= t('LivePoll') %></a>
|
||||||
|
|
|
@ -23,10 +23,10 @@
|
||||||
<div class="row chart">
|
<div class="row chart">
|
||||||
<h5>
|
<h5>
|
||||||
<span class="history-heading"><%= t('History') %></span>
|
<span class="history-heading"><%= t('History') %></span>
|
||||||
<a href="<%= root_path %>?days=7" class="history-graph <%= "active" if params[:days] == "7" %>"><%= t('OneWeek') %></a>
|
<a href="<%= root_path %>?days=7" class="history-graph <%= "active" if params['days'] == "7" %>"><%= t('OneWeek') %></a>
|
||||||
<a href="<%= root_path %>" class="history-graph <%= "active" if params[:days].nil? || params[:days] == "30" %>"><%= t('OneMonth') %></a>
|
<a href="<%= root_path %>" class="history-graph <%= "active" if params['days'].nil? || params['days'] == "30" %>"><%= t('OneMonth') %></a>
|
||||||
<a href="<%= root_path %>?days=90" class="history-graph <%= "active" if params[:days] == "90" %>"><%= t('ThreeMonths') %></a>
|
<a href="<%= root_path %>?days=90" class="history-graph <%= "active" if params['days'] == "90" %>"><%= t('ThreeMonths') %></a>
|
||||||
<a href="<%= root_path %>?days=180" class="history-graph <%= "active" if params[:days] == "180" %>"><%= t('SixMonths') %></a>
|
<a href="<%= root_path %>?days=180" class="history-graph <%= "active" if params['days'] == "180" %>"><%= t('SixMonths') %></a>
|
||||||
</h5>
|
</h5>
|
||||||
|
|
||||||
<div id="history" data-processed-label="<%= t('Processed') %>" data-failed-label="<%= t('Failed') %>" data-processed="<%= h Sidekiq.dump_json(@processed_history) %>" data-failed="<%= h Sidekiq.dump_json(@failed_history) %>" data-update-url="<%= root_path %>stats"></div>
|
<div id="history" data-processed-label="<%= t('Processed') %>" data-failed-label="<%= t('Failed') %>" data-processed="<%= h Sidekiq.dump_json(@processed_history) %>" data-failed="<%= h Sidekiq.dump_json(@failed_history) %>" data-update-url="<%= root_path %>stats"></div>
|
||||||
|
@ -58,14 +58,14 @@
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if @redis_info.fetch("used_memory_human", nil) %>
|
<% if @redis_info.fetch("used_memory_human", nil) %>
|
||||||
<div class="stat">
|
<div class="stat">
|
||||||
<h3 class="used_memory_human"><%= @redis_info.fetch("used_memory_human") %></h3>
|
<h3 class="used_memory_human"><%= @redis_info.fetch("used_memory_human") %></h3>
|
||||||
<p><%= t('MemoryUsage') %></p>
|
<p><%= t('MemoryUsage') %></p>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if @redis_info.fetch("used_memory_peak_human", nil) %>
|
<% if @redis_info.fetch("used_memory_peak_human", nil) %>
|
||||||
<div class="stat">
|
<div class="stat">
|
||||||
<h3 class="used_memory_peak_human"><%= @redis_info.fetch("used_memory_peak_human") %></h3>
|
<h3 class="used_memory_peak_human"><%= @redis_info.fetch("used_memory_peak_human") %></h3>
|
||||||
<p><%= t('PeakMemoryUsage') %></p>
|
<p><%= t('PeakMemoryUsage') %></p>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<%= erb :_job_info, :locals => {:job => @dead, :type => :dead} %>
|
<%= partial :job_info, job: @dead, type: :dead %>
|
||||||
|
|
||||||
<h3><%= t('Error') %></h3>
|
<h3><%= t('Error') %></h3>
|
||||||
<div class="table_container">
|
<div class="table_container">
|
||||||
|
|
|
@ -12,12 +12,12 @@
|
||||||
<%= display_custom_head %>
|
<%= display_custom_head %>
|
||||||
</head>
|
</head>
|
||||||
<body class="admin">
|
<body class="admin">
|
||||||
<%= erb :_nav %>
|
<%= partial :nav %>
|
||||||
<div id="page">
|
<div id="page">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12 summary_bar">
|
<div class="col-sm-12 summary_bar">
|
||||||
<%= erb :_summary %>
|
<%= partial :summary %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<%= erb :_footer %>
|
<%= partial :footer %>
|
||||||
<%= erb :_poll_js %>
|
<%= partial :poll_js %>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
</div>
|
</div>
|
||||||
<% if @dead.size > 0 && @total_size > @count %>
|
<% if @dead.size > 0 && @total_size > @count %>
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-4">
|
||||||
<%= erb :_paging, :locals => { :url => "#{root_path}morgue" } %>
|
<%= partial :paging, url: "#{root_path}morgue" %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= filtering('dead') %>
|
<%= filtering('dead') %>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4 pull-right">
|
<div class="col-sm-4 pull-right">
|
||||||
<%= erb :_paging, :locals => { :url => "#{root_path}queues/#{@name}" } %>
|
<%= partial :paging, url: "#{root_path}queues/#{@name}" %>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div class="table_container">
|
<div class="table_container">
|
||||||
|
@ -42,4 +42,4 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<%= erb :_paging, :locals => { :url => "#{root_path}queues/#{@name}" } %>
|
<%= partial :paging, url: "#{root_path}queues/#{@name}" %>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
</div>
|
</div>
|
||||||
<% if @retries.size > 0 && @total_size > @count %>
|
<% if @retries.size > 0 && @total_size > @count %>
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-4">
|
||||||
<%= erb :_paging, :locals => { :url => "#{root_path}retries" } %>
|
<%= partial :paging, url: "#{root_path}retries" %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= filtering('retries') %>
|
<%= filtering('retries') %>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<%= erb :_job_info, :locals => {:job => @retry, :type => :retry} %>
|
<%= partial :job_info, job: @retry, type: :retry %>
|
||||||
|
|
||||||
<h3><%= t('Error') %></h3>
|
<h3><%= t('Error') %></h3>
|
||||||
<div class="table_container">
|
<div class="table_container">
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
</div>
|
</div>
|
||||||
<% if @scheduled.size > 0 && @total_size > @count %>
|
<% if @scheduled.size > 0 && @total_size > @count %>
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-4">
|
||||||
<%= erb :_paging, :locals => { :url => "#{root_path}scheduled" } %>
|
<%= partial :paging, url: "#{root_path}scheduled" %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= filtering('scheduled') %>
|
<%= filtering('scheduled') %>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<%= erb :_job_info, :locals => {:job => @job, :type => :scheduled} %>
|
<%= partial :job_info, job: @job, type: :scheduled %>
|
||||||
|
|
||||||
<form class="form-horizontal" action="<%= root_path %>scheduled/<%= job_params(@job, @job.score) %>" method="post">
|
<form class="form-horizontal" action="<%= root_path %>scheduled/<%= job_params(@job, @job.score) %>" method="post">
|
||||||
<%= csrf_tag %>
|
<%= csrf_tag %>
|
||||||
|
|
Loading…
Add table
Reference in a new issue