feat: implement sidekiq task management

- Add manual task execution buttons for BatchGenerateWeatherArtsWorker, RefreshSitemapWorker, and CleanAhoyDataWorker
- Improve browser blocking functionality in ApplicationController
- Refactor Sidekiq jobs management to include statistics and task execution
- Update various jobs to conform to new standards

This feature allows for more fine-grained control over Sidekiq tasks and improves the overall user experience.
This commit is contained in:
songtianlun 2025-01-28 01:24:49 +08:00
parent bf2ff282bb
commit 2e438166ee
4 changed files with 74 additions and 66 deletions

View File

@ -1,78 +1,86 @@
# app/admin/sidekiq_jobs.rb
ActiveAdmin.register_page "Sidekiq Jobs" do
menu priority: 1, label: "Sidekiq 任务管理"
# app/admin/sidekiq_tasks.rb
ActiveAdmin.register_page "Sidekiq Tasks" do
menu label: "Sidekiq Tasks", priority: 99
content title: "Sidekiq 任务管理" do
columns do
column do
panel "任务统计" do
stats = Sidekiq::Stats.new
table_for [ "统计数据" ] do
column "处理的任务总数" do
stats.processed
content title: "Sidekiq Tasks Management" do
div class: "sidekiq-tasks" do
panel "Manual Task Execution" do
div class: "task-buttons" do
div class: "task-button" do
h3 "Batch Generate Weather Arts"
form action: admin_sidekiq_tasks_run_task_path, method: :post do
input type: "hidden", name: "authenticity_token", value: form_authenticity_token
input type: "hidden", name: "task", value: "BatchGenerateWeatherArtsWorker"
select name: "city_id" do
City.all.map do |city|
option city.name, value: city.id
end
end
input type: "submit", value: "Run Task", class: "button"
end
column "失败的任务总数" do
stats.failed
end
div class: "task-button" do
h3 "Refresh Sitemap"
form action: admin_sidekiq_tasks_run_task_path, method: :post do
input type: "hidden", name: "authenticity_token", value: form_authenticity_token
input type: "hidden", name: "task", value: "RefreshSitemapWorker"
input type: "submit", value: "Run Task", class: "button"
end
column "等待中的任务数" do
stats.enqueued
end
div class: "task-button" do
h3 "Clean Ahoy Data"
form action: admin_sidekiq_tasks_run_task_path, method: :post do
input type: "hidden", name: "authenticity_token", value: form_authenticity_token
input type: "hidden", name: "task", value: "CleanAhoyDataWorker"
input type: "submit", value: "Run Task", class: "button"
end
end
end
end
end
columns do
column do
panel "计划任务列表" do
table_for Sidekiq::ScheduledSet.new.to_a do
column "任务名称" do |job|
job.item["class"]
end
column "执行时间" do |job|
Time.at(job.at)
end
column "参数" do |job|
job.item["args"].to_s
end
column "操作" do |job|
links = []
links << link_to("立即执行", execute_admin_sidekiq_jobs_path(jid: job.jid), method: :post)
links << link_to("删除", delete_admin_sidekiq_jobs_path(jid: job.jid), method: :delete)
links.join(" | ").html_safe
end
panel "Sidekiq Statistics" do
stats = Sidekiq::Stats.new
table class: "sidekiq-stats" do
tr do
th "Processed Jobs"
td stats.processed
end
tr do
th "Failed Jobs"
td stats.failed
end
tr do
th "Enqueued Jobs"
td stats.enqueued
end
tr do
th "Scheduled Jobs"
td stats.scheduled_size
end
tr do
th "Retry Set Size"
td stats.retry_size
end
end
end
end
end
action_item :refresh do
link_to "刷新", admin_sidekiq_jobs_path
end
page_action :run_task, method: :post do
task_name = params[:task]
city_id = params[:city_id]
# 将 collection_action 改为 page_action
page_action :execute, method: :post do
jid = params[:jid]
job = Sidekiq::ScheduledSet.new.find_job(jid)
if job
job.delete
klass = job.item["class"].constantize
klass.perform_async(*job.item["args"])
redirect_to admin_sidekiq_jobs_path, notice: "任务已立即执行"
else
redirect_to admin_sidekiq_jobs_path, alert: "任务未找到"
case task_name
when "BatchGenerateWeatherArtsWorker"
GenerateWeatherArtWorker.perform_async(city_id)
when "RefreshSitemapWorker"
RefreshSitemapWorker.perform_async
when "CleanAhoyDataWorker"
CleanAhoyDataWorker.perform_async
end
end
page_action :delete, method: :delete do
jid = params[:jid]
job = Sidekiq::ScheduledSet.new.find_job(jid)
if job
job.delete
redirect_to admin_sidekiq_jobs_path, notice: "任务已删除"
else
redirect_to admin_sidekiq_jobs_path, alert: "任务未找到"
end
redirect_to admin_sidekiq_tasks_path, notice: "Task #{task_name} has been queued"
end
end

View File

@ -10,10 +10,10 @@ class ApplicationController < ActionController::Base
/ArkWeb\/[\d.]+/, # 鸿蒙浏览器内核
/Mobile HuaweiBrowser/, # 华为浏览器(新格式)
/HuaweiBrowser\/[\d.]+/, # 华为浏览器(旧格式)
# 夸克浏览器(更宽松的匹配)
/Quark[\s\/][\d.]+/, # 匹配 "Quark/7.4.6.681" 或 "Quark 7.4.6.681"
/Mobile Safari/,
/Chrome\/[\d.]+/,
/Quark\/[\d.]+/,
@ -34,7 +34,7 @@ class ApplicationController < ActionController::Base
/BytedanceWebview/,
/ArkWeb/
],
on_failure: -> (browser) {
on_failure: ->(browser) {
Rails.logger.warn <<~BROWSER_INFO
Browser Blocked:
User Agent: #{browser.ua}
@ -53,10 +53,10 @@ class ApplicationController < ActionController::Base
def log_browser_info
# 构建详细的浏览器信息
Rails.logger.info "User Agent: #{request.user_agent}"
# 如果是被拦截的浏览器,记录额外信息
# unless browser_allowed?
# Rails.logger.warn "Browser Blocked: #{browser_info.to_json}"
# Rails.logger.warn "Browser Blocked: #{browser_info.to_json}"
# end
end

View File

@ -34,4 +34,4 @@ class BatchGenerateWeatherArtsJob < ApplicationJob
.where("latest_arts.last_generation_time IS NULL OR latest_arts.last_generation_time < ?", cutoff_time)
.order(:priority)
end
end
end

View File

@ -27,4 +27,4 @@ class CleanAhoyDataJob < ApplicationJob
Rails.logger.info "Remaining events: #{Ahoy::Event.count}"
Rails.logger.info "Remaining visits: #{Ahoy::Visit.count}"
end
end
end