diff --git a/CHANGELOG.md b/CHANGELOG.md index 536a37b..c7867e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Queue pause / resume — Pause and Resume buttons per row on the Queues page - Pagination for jobs and failed jobs lists via pagy (25 per page) - Jobs URL segment renamed from `/jobs/jobs` to `/jobs/list` - Job detail page showing status, queue, priority, arguments (pretty-printed JSON), and full error backtrace for failed jobs diff --git a/app/controllers/solid_queue_web/queues_controller.rb b/app/controllers/solid_queue_web/queues_controller.rb index 6f5496c..47393f8 100644 --- a/app/controllers/solid_queue_web/queues_controller.rb +++ b/app/controllers/solid_queue_web/queues_controller.rb @@ -3,5 +3,21 @@ class QueuesController < ApplicationController def index @queues = SolidQueue::Queue.all.sort_by(&:name) end + + def pause + queue = SolidQueue::Queue.find_by_name(params[:name]) + queue.pause + redirect_to queues_path, notice: "Queue \"#{queue.name}\" paused." + rescue => e + redirect_to queues_path, alert: "Could not pause queue: #{e.message}" + end + + def resume + queue = SolidQueue::Queue.find_by_name(params[:name]) + queue.resume + redirect_to queues_path, notice: "Queue \"#{queue.name}\" resumed." + rescue => e + redirect_to queues_path, alert: "Could not resume queue: #{e.message}" + end end end diff --git a/app/views/solid_queue_web/queues/index.html.erb b/app/views/solid_queue_web/queues/index.html.erb index 4a74a88..8878542 100644 --- a/app/views/solid_queue_web/queues/index.html.erb +++ b/app/views/solid_queue_web/queues/index.html.erb @@ -11,6 +11,7 @@ Size Latency Status + @@ -26,6 +27,16 @@ Running <% end %> + + <% if queue.paused? %> + <%= button_to "Resume", resume_queue_path(queue.name), method: :post, + class: "sqd-btn sqd-btn--primary sqd-btn--sm" %> + <% else %> + <%= button_to "Pause", pause_queue_path(queue.name), method: :post, + class: "sqd-btn sqd-btn--muted sqd-btn--sm", + data: { confirm: "Pause queue \"#{queue.name}\"?" } %> + <% end %> + <% end %> diff --git a/config/routes.rb b/config/routes.rb index 95df0f0..1ecd8c8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,7 +1,12 @@ SolidQueueWeb::Engine.routes.draw do root to: "dashboard#index" - resources :queues, only: [ :index ] + resources :queues, only: [ :index ], param: :name do + member do + post :pause + post :resume + end + end resources :jobs, path: "list", only: [ :index, :show, :destroy ] do collection do post :discard_all diff --git a/spec/requests/solid_queue_web/queues_spec.rb b/spec/requests/solid_queue_web/queues_spec.rb new file mode 100644 index 0000000..db619b0 --- /dev/null +++ b/spec/requests/solid_queue_web/queues_spec.rb @@ -0,0 +1,56 @@ +require "rails_helper" + +RSpec.describe "Queues", type: :request do + before do + SolidQueue::Job.create!( + queue_name: "default", + class_name: "TestJob", + arguments: {}, + active_job_id: SecureRandom.uuid + ) + end + + describe "GET /jobs/queues" do + it "returns HTTP success" do + get "/jobs/queues" + expect(response).to have_http_status(:ok) + end + + it "displays queue names" do + get "/jobs/queues" + expect(response.body).to include("default") + end + end + + describe "POST /jobs/queues/:name/pause" do + it "pauses the queue and redirects" do + post "/jobs/queues/default/pause" + expect(response).to redirect_to("/jobs/queues") + follow_redirect! + expect(response.body).to include("paused") + end + + it "creates a Pause record" do + expect { + post "/jobs/queues/default/pause" + }.to change(SolidQueue::Pause, :count).by(1) + end + end + + describe "POST /jobs/queues/:name/resume" do + before { SolidQueue::Pause.create!(queue_name: "default") } + + it "resumes the queue and redirects" do + post "/jobs/queues/default/resume" + expect(response).to redirect_to("/jobs/queues") + follow_redirect! + expect(response.body).to include("resumed") + end + + it "removes the Pause record" do + expect { + post "/jobs/queues/default/resume" + }.to change(SolidQueue::Pause, :count).by(-1) + end + end +end