From 8b61dc8e90456bc7eb645b1af886afcaa4943e13 Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Mon, 5 Feb 2024 16:56:50 +0530 Subject: [PATCH 01/24] require irb --- lib/mission_control/jobs/engine.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/mission_control/jobs/engine.rb b/lib/mission_control/jobs/engine.rb index 3a2102be..49575abb 100644 --- a/lib/mission_control/jobs/engine.rb +++ b/lib/mission_control/jobs/engine.rb @@ -63,6 +63,7 @@ class Engine < ::Rails::Engine end console do + require "irb" require "irb/context" IRB::Context.prepend(MissionControl::Jobs::Console::Context) From 7f8edf73b09431f140abb43fb8240be30ec8d720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Wn=C4=99trzak?= Date: Wed, 31 Jan 2024 06:01:32 +0100 Subject: [PATCH 02/24] Remove unused mailer files --- app/mailers/mission_control/jobs/application_mailer.rb | 8 -------- test/dummy/app/mailers/application_mailer.rb | 4 ---- 2 files changed, 12 deletions(-) delete mode 100644 app/mailers/mission_control/jobs/application_mailer.rb delete mode 100644 test/dummy/app/mailers/application_mailer.rb diff --git a/app/mailers/mission_control/jobs/application_mailer.rb b/app/mailers/mission_control/jobs/application_mailer.rb deleted file mode 100644 index d665e286..00000000 --- a/app/mailers/mission_control/jobs/application_mailer.rb +++ /dev/null @@ -1,8 +0,0 @@ -module MissionControl - module Jobs - class ApplicationMailer < ActionMailer::Base - default from: "from@example.com" - layout "mailer" - end - end -end diff --git a/test/dummy/app/mailers/application_mailer.rb b/test/dummy/app/mailers/application_mailer.rb deleted file mode 100644 index 3c34c814..00000000 --- a/test/dummy/app/mailers/application_mailer.rb +++ /dev/null @@ -1,4 +0,0 @@ -class ApplicationMailer < ActionMailer::Base - default from: "from@example.com" - layout "mailer" -end From d8c0f9e3b0326deb3fcef8c2a7aa63ebacb7dd02 Mon Sep 17 00:00:00 2001 From: Gary Tou Date: Sat, 10 Feb 2024 12:22:01 -0800 Subject: [PATCH 03/24] Remove `$debug` variable --- test/active_job/queue_adapters/adapter_testing/discard_jobs.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/active_job/queue_adapters/adapter_testing/discard_jobs.rb b/test/active_job/queue_adapters/adapter_testing/discard_jobs.rb index 64e523f6..7b68fe34 100644 --- a/test/active_job/queue_adapters/adapter_testing/discard_jobs.rb +++ b/test/active_job/queue_adapters/adapter_testing/discard_jobs.rb @@ -60,7 +60,6 @@ module ActiveJob::QueueAdapters::AdapterTesting::DiscardJobs 5.times { FailingJob.perform_later } 10.times { FailingReloadedJob.perform_later } perform_enqueued_jobs -$debug = true ActiveJob.jobs.failed.where(queue_name: :queue_1).discard_all assert_empty ActiveJob.jobs.failed.where(job_class_name: "FailingJob") From 68f7e4d118a216108dc212a3daf83132e5cc2529 Mon Sep 17 00:00:00 2001 From: Gary Tou Date: Sat, 10 Feb 2024 12:12:12 -0800 Subject: [PATCH 04/24] Add `internal_query_count_limit` configuration It can be configured via ```ruby MissionControl::Jobs.internal_query_count_limit = 5_000 ``` or ```ruby config.mission_control.jobs.internal_query_count_limit = 5_000 ``` --- lib/active_job/queue_adapters/solid_queue_ext.rb | 7 +++---- lib/mission_control/jobs.rb | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/active_job/queue_adapters/solid_queue_ext.rb b/lib/active_job/queue_adapters/solid_queue_ext.rb index 837fbd92..a7e5b66e 100644 --- a/lib/active_job/queue_adapters/solid_queue_ext.rb +++ b/lib/active_job/queue_adapters/solid_queue_ext.rb @@ -224,11 +224,10 @@ def direct_count solid_queue_status.finished? ? finished_jobs.count : executions.count end - INTERNAL_COUNT_LIMIT = 500_000 # Hard limit to keep unlimited count queries fast enough - def internally_limited_count - limited_count = solid_queue_status.finished? ? finished_jobs.limit(INTERNAL_COUNT_LIMIT + 1).count : executions.limit(INTERNAL_COUNT_LIMIT + 1).count - (limited_count == INTERNAL_COUNT_LIMIT + 1) ? Float::INFINITY : limited_count + count_limit = MissionControl::Jobs.internal_query_count_limit + 1 + limited_count = solid_queue_status.finished? ? finished_jobs.limit(count_limit).count : executions.limit(count_limit).count + (limited_count == count_limit) ? Float::INFINITY : limited_count end def execution_class_by_status diff --git a/lib/mission_control/jobs.rb b/lib/mission_control/jobs.rb index dba59137..3ebbc7b5 100644 --- a/lib/mission_control/jobs.rb +++ b/lib/mission_control/jobs.rb @@ -15,5 +15,6 @@ module Jobs mattr_accessor :base_controller_class, default: "::ApplicationController" mattr_accessor :delay_between_bulk_operation_batches, default: 0 mattr_accessor :logger, default: ActiveSupport::Logger.new(nil) + mattr_accessor :internal_query_count_limit, default: 500_000 # Hard limit to keep unlimited count queries fast enough end end From 6eaaf56081ad1e9065168b4a24762422441e637b Mon Sep 17 00:00:00 2001 From: Gary Tou Date: Sat, 10 Feb 2024 12:34:32 -0800 Subject: [PATCH 05/24] Add tests for `internal_query_count_limit` It appears that only the Solid Queue adapter implements an internal query count limit. The Resque adapter doesn't have a similar functionality --- .../adapter_testing/count_jobs.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/active_job/queue_adapters/adapter_testing/count_jobs.rb b/test/active_job/queue_adapters/adapter_testing/count_jobs.rb index d940690c..353f8087 100644 --- a/test/active_job/queue_adapters/adapter_testing/count_jobs.rb +++ b/test/active_job/queue_adapters/adapter_testing/count_jobs.rb @@ -107,4 +107,22 @@ module ActiveJob::QueueAdapters::AdapterTesting::CountJobs assert_equal 2, ApplicationJob.jobs.failed.where(job_class_name: "FailingJob").offset(3).limit(2).count assert_equal 3, ApplicationJob.jobs.failed.where(job_class_name: "FailingJob").offset(7).limit(10).count end + + test "count jobs with internal query count limit configured" do + skip "Only Solid Queue supports internal query count limit" unless queue_adapter == :solid_queue + + begin + original_limit = MissionControl::Jobs.internal_query_count_limit + MissionControl::Jobs.internal_query_count_limit = 5 + assert_equal 0, ApplicationJob.jobs.pending.count + + 5.times { DummyJob.perform_later } + assert_equal 5, ApplicationJob.jobs.pending.count + + DummyJob.perform_later + assert_equal Float::INFINITY, ApplicationJob.jobs.pending.count + ensure + MissionControl::Jobs.internal_query_count_limit = original_limit + end + end end From 11f690d211c971a3ff3d48127a1dc1fd7387b739 Mon Sep 17 00:00:00 2001 From: Gary Tou Date: Sat, 10 Feb 2024 12:38:59 -0800 Subject: [PATCH 06/24] Add `internal_query_count_limit` to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 40b2c303..398aa4bc 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ Besides `base_controller_class`, you can also set the following for `MissionCont - `logger`: the logger you want Mission Control Jobs to use. Defaults to `ActiveSupport::Logger.new(nil)` (no logging). Notice that this is different from Active Job's logger or Active Job's backend's configured logger. - `delay_between_bulk_operation_batches`: how long to wait between batches when performing bulk operations, such as _discard all_ or _retry all_ jobs—defaults to `0` - `adapters`: a list of adapters that you want Mission Control to use and extend. By default this will be the adapter you have set for `active_job.queue_adapter`. +- `internal_query_count_limit`: the maximum number of jobs that Solid Queue adapters will query when performing a count. True counts above this number will be returned as `INFINITY`. This keeps count queries fast—defaults to `500,000` This library extends Active Job with a querying interface and the following setting: - `config.active_job.default_page_size`: the internal batch size that Active Job will use when sending queries to the underlying adapter and the batch size for the bulk operations defined above—defaults to `1000`. From b6ea7d06cfff6cdb98d5da2e90786b5a6b99b2d7 Mon Sep 17 00:00:00 2001 From: Gary Tou Date: Mon, 12 Feb 2024 14:36:14 -0800 Subject: [PATCH 07/24] README: Clarify that not all adapters need to use `internal_query_count_limit` Co-authored-by: Rosa Gutierrez --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 398aa4bc..a7b82d29 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Besides `base_controller_class`, you can also set the following for `MissionCont - `logger`: the logger you want Mission Control Jobs to use. Defaults to `ActiveSupport::Logger.new(nil)` (no logging). Notice that this is different from Active Job's logger or Active Job's backend's configured logger. - `delay_between_bulk_operation_batches`: how long to wait between batches when performing bulk operations, such as _discard all_ or _retry all_ jobs—defaults to `0` - `adapters`: a list of adapters that you want Mission Control to use and extend. By default this will be the adapter you have set for `active_job.queue_adapter`. -- `internal_query_count_limit`: the maximum number of jobs that Solid Queue adapters will query when performing a count. True counts above this number will be returned as `INFINITY`. This keeps count queries fast—defaults to `500,000` +- `internal_query_count_limit`: in count queries, the maximum number of records that will be counted if the adapter needs to limit these queries. True counts above this number will be returned as `INFINITY`. This keeps count queries fast—defaults to `500,000` This library extends Active Job with a querying interface and the following setting: - `config.active_job.default_page_size`: the internal batch size that Active Job will use when sending queries to the underlying adapter and the batch size for the bulk operations defined above—defaults to `1000`. From 56b0d46f52b49474a86e1de9113fd5983f2f938a Mon Sep 17 00:00:00 2001 From: Rosa Gutierrez Date: Thu, 1 Feb 2024 14:17:56 +0100 Subject: [PATCH 08/24] Don't seed the test DB as it takes very long And include more Ruby versions. --- .github/workflows/ruby.yml | 6 +++--- Gemfile.lock | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index a4af9e65..88b5c92f 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -28,7 +28,7 @@ jobs: - name: Setup Ruby and install gems uses: ruby/setup-ruby@v1 with: - ruby-version: 3.0 + ruby-version: 3.3 bundler-cache: true - name: Run rubocop run: | @@ -42,7 +42,7 @@ jobs: BUNDLE_GITHUB__COM: x-access-token:${{ secrets.GH_TOKEN }} strategy: matrix: - ruby-version: ['3.0'] + ruby-version: ['3.0', '3.1', '3.2', '3.3'] services: redis: image: redis:4.0-alpine @@ -56,7 +56,7 @@ jobs: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true # runs 'bundle install' and caches installed gems automatically - name: Prepare database - run: bin/rails db:setup + run: bin/rails db:create db:schema:load - name: Run tests run: bin/rails test - name: Run system tests diff --git a/Gemfile.lock b/Gemfile.lock index c4f61baa..8037b459 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -32,7 +32,7 @@ GIT PATH remote: . specs: - mission_control-jobs (0.1.0) + mission_control-jobs (0.1.1) importmap-rails rails (~> 7.1) stimulus-rails From 94f53ddd5f6eb48bf39706f0338ade11ed59f825 Mon Sep 17 00:00:00 2001 From: Rosa Gutierrez Date: Tue, 13 Feb 2024 19:59:17 +0100 Subject: [PATCH 09/24] Run tests on all pushes and PRs Paired with the need for approval for all outside collaborators. --- .github/workflows/ruby.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 88b5c92f..d6200211 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -5,13 +5,9 @@ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby -name: Ruby +name: Build -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] +on: [push, pull_request] permissions: contents: read From aa994a61164fedad823ebaf93b658f71f346d9f1 Mon Sep 17 00:00:00 2001 From: Rosa Gutierrez Date: Tue, 13 Feb 2024 21:17:54 +0100 Subject: [PATCH 10/24] Wrap filters and toolbar when the page width is too narrow --- app/views/mission_control/jobs/jobs/index.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/mission_control/jobs/jobs/index.html.erb b/app/views/mission_control/jobs/jobs/index.html.erb index 92c183e2..dfd303a7 100644 --- a/app/views/mission_control/jobs/jobs/index.html.erb +++ b/app/views/mission_control/jobs/jobs/index.html.erb @@ -3,7 +3,7 @@ <% if @jobs_page.empty? && !active_filters? %> <%= blank_status_notice "There are no #{jobs_status.dasherize} jobs #{blank_status_emoji(jobs_status)}" %> <% else %> -
+
<%= render "mission_control/jobs/jobs/filters", job_class_names: @job_class_names, queue_names: @queue_names %> <%= render "mission_control/jobs/jobs/toolbar", jobs_count: @jobs_count %>
From 8efca91c433d89250551d2c6d3c151eed470e254 Mon Sep 17 00:00:00 2001 From: Rosa Gutierrez Date: Tue, 13 Feb 2024 22:03:19 +0100 Subject: [PATCH 11/24] Remove Ruby 3.3.0 from the list of tested Rubies for now There's some strange behaviour with the Solid Queue worker hanging unless it sends some output over STDOUT. --- .github/workflows/ruby.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index d6200211..77f385c2 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -38,7 +38,7 @@ jobs: BUNDLE_GITHUB__COM: x-access-token:${{ secrets.GH_TOKEN }} strategy: matrix: - ruby-version: ['3.0', '3.1', '3.2', '3.3'] + ruby-version: ['3.0', '3.1', '3.2'] services: redis: image: redis:4.0-alpine From 4f7fb1d358ab92a97b0bf1ad7ed1a6cf61162342 Mon Sep 17 00:00:00 2001 From: Rosa Gutierrez Date: Tue, 13 Feb 2024 22:18:39 +0100 Subject: [PATCH 12/24] Update puma, sinatra and nokogiri --- Gemfile.lock | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 8037b459..2c995ce3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -156,6 +156,8 @@ GEM mocha (1.14.0) mono_logger (1.1.1) multi_json (1.15.0) + mustermann (3.0.0) + ruby2_keywords (~> 0.0.1) mutex_m (0.2.0) net-imap (0.2.3) digest @@ -171,10 +173,10 @@ GEM digest net-protocol timeout - nio4r (2.5.8) - nokogiri (1.16.0-arm64-darwin) + nio4r (2.7.0) + nokogiri (1.16.2-arm64-darwin) racc (~> 1.4) - nokogiri (1.16.0-x86_64-linux) + nokogiri (1.16.2-x86_64-linux) racc (~> 1.4) parallel (1.24.0) parser (3.3.0.4) @@ -183,10 +185,13 @@ GEM psych (5.1.2) stringio public_suffix (5.0.4) - puma (5.6.4) + puma (6.4.2) nio4r (~> 2.0) - racc (1.6.0) - rack (3.0.8) + racc (1.7.3) + rack (3.0.9) + rack-protection (4.0.0) + base64 (>= 0.1.0) + rack (>= 3.0.0, < 4) rack-session (2.0.0) rack (>= 3.0.0) rack-test (2.1.0) @@ -271,8 +276,12 @@ GEM rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) - sinatra (1.0) - rack (>= 1.0) + sinatra (4.0.0) + mustermann (~> 3.0) + rack (>= 3.0.0, < 4) + rack-protection (= 4.0.0) + rack-session (>= 2.0.0, < 3) + tilt (~> 2.0) sprockets (4.2.1) concurrent-ruby (~> 1.0) rack (>= 2.2.4, < 4) @@ -286,6 +295,7 @@ GEM stringio (3.1.0) strscan (3.0.4) thor (1.3.0) + tilt (2.3.0) timeout (0.4.1) turbo-rails (1.5.0) actionpack (>= 6.0.0) From bdebc66f0c8e9188dd8555d02afc1b7796e5955e Mon Sep 17 00:00:00 2001 From: Rosa Gutierrez Date: Wed, 14 Feb 2024 14:25:59 +0100 Subject: [PATCH 13/24] Regenerate db/schema with right bigint type for foreign keys --- test/dummy/db/schema.rb | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/dummy/db/schema.rb b/test/dummy/db/schema.rb index fe0fc9d7..7d70c3ee 100644 --- a/test/dummy/db/schema.rb +++ b/test/dummy/db/schema.rb @@ -11,15 +11,15 @@ # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema[7.1].define(version: 2023_09_14_113326) do - create_table "posts", force: :cascade do |t| + create_table "posts", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "title" t.text "body" t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "solid_queue_blocked_executions", force: :cascade do |t| - t.integer "job_id", null: false + create_table "solid_queue_blocked_executions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "job_id", null: false t.string "queue_name", null: false t.integer "priority", default: 0, null: false t.string "concurrency_key", null: false @@ -30,22 +30,22 @@ t.index ["job_id"], name: "index_solid_queue_blocked_executions_on_job_id", unique: true end - create_table "solid_queue_claimed_executions", force: :cascade do |t| - t.integer "job_id", null: false + create_table "solid_queue_claimed_executions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "job_id", null: false t.bigint "process_id" t.datetime "created_at", null: false t.index ["job_id"], name: "index_solid_queue_claimed_executions_on_job_id", unique: true t.index ["process_id", "job_id"], name: "index_solid_queue_claimed_executions_on_process_id_and_job_id" end - create_table "solid_queue_failed_executions", force: :cascade do |t| - t.integer "job_id", null: false + create_table "solid_queue_failed_executions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "job_id", null: false t.text "error" t.datetime "created_at", null: false t.index ["job_id"], name: "index_solid_queue_failed_executions_on_job_id", unique: true end - create_table "solid_queue_jobs", force: :cascade do |t| + create_table "solid_queue_jobs", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "queue_name", null: false t.string "class_name", null: false t.text "arguments" @@ -63,13 +63,13 @@ t.index ["scheduled_at", "finished_at"], name: "index_solid_queue_jobs_for_alerting" end - create_table "solid_queue_pauses", force: :cascade do |t| + create_table "solid_queue_pauses", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "queue_name", null: false t.datetime "created_at", null: false t.index ["queue_name"], name: "index_solid_queue_pauses_on_queue_name", unique: true end - create_table "solid_queue_processes", force: :cascade do |t| + create_table "solid_queue_processes", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "kind", null: false t.datetime "last_heartbeat_at", null: false t.bigint "supervisor_id" @@ -81,8 +81,8 @@ t.index ["supervisor_id"], name: "index_solid_queue_processes_on_supervisor_id" end - create_table "solid_queue_ready_executions", force: :cascade do |t| - t.integer "job_id", null: false + create_table "solid_queue_ready_executions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "job_id", null: false t.string "queue_name", null: false t.integer "priority", default: 0, null: false t.datetime "created_at", null: false @@ -91,8 +91,8 @@ t.index ["queue_name", "priority", "job_id"], name: "index_solid_queue_poll_by_queue" end - create_table "solid_queue_scheduled_executions", force: :cascade do |t| - t.integer "job_id", null: false + create_table "solid_queue_scheduled_executions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "job_id", null: false t.string "queue_name", null: false t.integer "priority", default: 0, null: false t.datetime "scheduled_at", null: false @@ -101,7 +101,7 @@ t.index ["scheduled_at", "priority", "job_id"], name: "index_solid_queue_dispatch_all" end - create_table "solid_queue_semaphores", force: :cascade do |t| + create_table "solid_queue_semaphores", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "key", null: false t.integer "value", default: 1, null: false t.datetime "expires_at", null: false From 44e0b400adf5cc284acedba2fcd386d73faad831 Mon Sep 17 00:00:00 2001 From: Rosa Gutierrez Date: Wed, 14 Feb 2024 14:27:43 +0100 Subject: [PATCH 14/24] Update resque and mono_logger for Ruby 3.3.0 fix See https://github.com/resque/resque/issues/1856 and https://github.com/steveklabnik/mono_logger/pull/12 --- Gemfile.lock | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 2c995ce3..7d89ff11 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -154,7 +154,7 @@ GEM mini_mime (1.1.2) minitest (5.16.2) mocha (1.14.0) - mono_logger (1.1.1) + mono_logger (1.1.2) multi_json (1.15.0) mustermann (3.0.0) ruby2_keywords (~> 0.0.1) @@ -233,8 +233,8 @@ GEM rdoc (6.6.2) psych (>= 4.0.0) redis (4.0.3) - redis-namespace (1.8.2) - redis (>= 3.0.4) + redis-namespace (1.11.0) + redis (>= 4) regexp_parser (2.5.0) reline (0.4.2) io-console (~> 0.5) @@ -315,6 +315,7 @@ GEM PLATFORMS arm64-darwin-21 + arm64-darwin-22 x86_64-linux DEPENDENCIES From 7bf24d9c25e06ecbf41119f921ecedba0847b2c9 Mon Sep 17 00:00:00 2001 From: Rosa Gutierrez Date: Wed, 14 Feb 2024 18:44:14 +0100 Subject: [PATCH 15/24] Run tests against Ruby 3.3.0 and use a polling interval bigger than 0 Sleeping for 0 seconds doesn't play very well with Ruby 3.3.0 and Active Record connections, although I haven't quite figured out why yet -_- --- .github/workflows/ruby.yml | 2 +- test/active_job/queue_adapters/solid_queue_test.rb | 2 +- test/dummy/db/seeds.rb | 2 +- test/test_helper.rb | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 77f385c2..d6200211 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -38,7 +38,7 @@ jobs: BUNDLE_GITHUB__COM: x-access-token:${{ secrets.GH_TOKEN }} strategy: matrix: - ruby-version: ['3.0', '3.1', '3.2'] + ruby-version: ['3.0', '3.1', '3.2', '3.3'] services: redis: image: redis:4.0-alpine diff --git a/test/active_job/queue_adapters/solid_queue_test.rb b/test/active_job/queue_adapters/solid_queue_test.rb index c083edf8..ff62a28b 100644 --- a/test/active_job/queue_adapters/solid_queue_test.rb +++ b/test/active_job/queue_adapters/solid_queue_test.rb @@ -13,7 +13,7 @@ def queue_adapter end def perform_enqueued_jobs - worker = SolidQueue::Worker.new(queues: "*", threads: 1, polling_interval: 0) + worker = SolidQueue::Worker.new(queues: "*", threads: 1, polling_interval: 0.01) worker.mode = :inline worker.start end diff --git a/test/dummy/db/seeds.rb b/test/dummy/db/seeds.rb index 13d0337b..d642f200 100644 --- a/test/dummy/db/seeds.rb +++ b/test/dummy/db/seeds.rb @@ -40,7 +40,7 @@ def dispatch_jobs worker = Resque::Worker.new("*") worker.work(0.0) when :solid_queue - worker = SolidQueue::Worker.new(queues: "*", threads: 1, polling_interval: 0) + worker = SolidQueue::Worker.new(queues: "*", threads: 1, polling_interval: 0.01) worker.mode = :inline worker.start else diff --git a/test/test_helper.rb b/test/test_helper.rb index 447b4f48..9bdd33d7 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -78,7 +78,7 @@ class ActionDispatch::IntegrationTest @application = MissionControl::Jobs.applications["integration-tests"] @server = @application.servers[:solid_queue] - @worker = SolidQueue::Worker.new(queues: "*", threads: 2, polling_interval: 0) + @worker = SolidQueue::Worker.new(queues: "*", threads: 2, polling_interval: 0.01) end teardown do From 9e07a5d262cfc837624ff84f9944a41fa61c1bb0 Mon Sep 17 00:00:00 2001 From: Rosa Gutierrez Date: Wed, 14 Feb 2024 20:44:32 +0100 Subject: [PATCH 16/24] Set :async adapter if there's no adapter configured To be consistent with Active Job. Also, include `MissionControl::Jobs::Adapter` in the async adapter so it can fail with a proper IncompatibleAdapter error until support is added. --- lib/mission_control/jobs/adapter.rb | 35 +++++++++++-------- lib/mission_control/jobs/engine.rb | 6 ++-- .../jobs/server/serializable.rb | 2 +- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/lib/mission_control/jobs/adapter.rb b/lib/mission_control/jobs/adapter.rb index b5fd8a5d..7ab5ac2f 100644 --- a/lib/mission_control/jobs/adapter.rb +++ b/lib/mission_control/jobs/adapter.rb @@ -29,7 +29,7 @@ def exposes_workers? # with these attributes: # { # id: 123, - # name: "adapter-name", + # name: "worker-name", # hostname: "hey-default-101", # last_heartbeat_at: Fri, 26 Jan 2024 20:31:09.652174000 UTC +00:00, # configuration: { ... } @@ -37,7 +37,7 @@ def exposes_workers? # } def workers if exposes_workers? - raise MissionControl::Jobs::Errors::IncompatibleAdapter("Adapter must implement `workers`") + raise_incompatible_adapter_error_from :workers end end @@ -49,60 +49,65 @@ def workers # active: true # } def queues - raise MissionControl::Jobs::Errors::IncompatibleAdapter("Adapter must implement `queue_names`") + raise_incompatible_adapter_error_from :queue_names end def queue_size(queue_name) - raise MissionControl::Jobs::Errors::IncompatibleAdapter("Adapter must implement `queue_size`") + raise_incompatible_adapter_error_from :queue_size end def clear_queue(queue_name) - raise MissionControl::Jobs::Errors::IncompatibleAdapter("Adapter must implement `clear_queue`") + raise_incompatible_adapter_error_from :clear_queue end def pause_queue(queue_name) if supports_queue_pausing? - raise MissionControl::Jobs::Errors::IncompatibleAdapter("Adapter must implement `pause_queue`") + raise_incompatible_adapter_error_from :pause_queue end end def resume_queue(queue_name) if supports_queue_pausing? - raise MissionControl::Jobs::Errors::IncompatibleAdapter("Adapter must implement `resume_queue`") + raise_incompatible_adapter_error_from :resume_queue end end def queue_paused?(queue_name) if supports_queue_pausing? - raise MissionControl::Jobs::Errors::IncompatibleAdapter("Adapter must implement `queue_paused?`") + raise_incompatible_adapter_error_from :queue_paused? end end def jobs_count(jobs_relation) - raise MissionControl::Jobs::Errors::IncompatibleAdapter("Adapter must implement `jobs_count`") + raise_incompatible_adapter_error_from :jobs_count end def fetch_jobs(jobs_relation) - raise MissionControl::Jobs::Errors::IncompatibleAdapter("Adapter must implement `fetch_jobs`") + raise_incompatible_adapter_error_from :fetch_jobs end def retry_all_jobs(jobs_relation) - raise MissionControl::Jobs::Errors::IncompatibleAdapter("Adapter must implement `retry_all_jobs`") + raise_incompatible_adapter_error_from :retry_all_jobs end def retry_job(job, jobs_relation) - raise MissionControl::Jobs::Errors::IncompatibleAdapter("Adapter must implement `retry_job`") + raise_incompatible_adapter_error_from :retry_job end def discard_all_jobs(jobs_relation) - raise MissionControl::Jobs::Errors::IncompatibleAdapter("Adapter must implement `discard_all_jobs`") + raise_incompatible_adapter_error_from :discard_all_jobs end def discard_job(job, jobs_relation) - raise MissionControl::Jobs::Errors::IncompatibleAdapter("Adapter must implement `discard_job`") + raise_incompatible_adapter_error_from :discard_job end def find_job(job_id, *) - raise MissionControl::Jobs::Errors::IncompatibleAdapter("Adapter must implement `find_job`") + raise_incompatible_adapter_error_from :find_job end + + private + def raise_incompatible_adapter_error_from(method_name) + raise MissionControl::Jobs::Errors::IncompatibleAdapter, "Adapter #{ActiveJob.adapter_name(self)} must implement `#{method_name}`" + end end diff --git a/lib/mission_control/jobs/engine.rb b/lib/mission_control/jobs/engine.rb index 49575abb..c4407940 100644 --- a/lib/mission_control/jobs/engine.rb +++ b/lib/mission_control/jobs/engine.rb @@ -20,8 +20,8 @@ class Engine < ::Rails::Engine MissionControl::Jobs.public_send("#{key}=", value) end - if config.active_job.queue_adapter.present? && MissionControl::Jobs.adapters.empty? - MissionControl::Jobs.adapters << config.active_job.queue_adapter + if MissionControl::Jobs.adapters.empty? + MissionControl::Jobs.adapters << (config.active_job.queue_adapter || :async) end end @@ -43,6 +43,8 @@ class Engine < ::Rails::Engine if MissionControl::Jobs.adapters.include?(:solid_queue) ActiveJob::QueueAdapters::SolidQueueAdapter.prepend ActiveJob::QueueAdapters::SolidQueueExt end + + ActiveJob::QueueAdapters::AsyncAdapter.include MissionControl::Jobs::Adapter end config.after_initialize do |app| diff --git a/lib/mission_control/jobs/server/serializable.rb b/lib/mission_control/jobs/server/serializable.rb index 48b90ee2..2ca226d6 100644 --- a/lib/mission_control/jobs/server/serializable.rb +++ b/lib/mission_control/jobs/server/serializable.rb @@ -18,7 +18,7 @@ def from_global_id(global_id) end def to_global_id - suffix = ":#{id}" if application.servers.length > 1 + suffix = ":#{id}" if application.servers.many? "#{application&.id}#{suffix}" end end From c14ab260b493195cfa99863e8a939882605e8ed6 Mon Sep 17 00:00:00 2001 From: Juan Vasquez Date: Sun, 18 Feb 2024 00:35:25 -0600 Subject: [PATCH 17/24] Move tbody tag to the correct place in the jobs page --- .../jobs/jobs/_jobs_page.html.erb | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/app/views/mission_control/jobs/jobs/_jobs_page.html.erb b/app/views/mission_control/jobs/jobs/_jobs_page.html.erb index 806425fa..644a2036 100644 --- a/app/views/mission_control/jobs/jobs/_jobs_page.html.erb +++ b/app/views/mission_control/jobs/jobs/_jobs_page.html.erb @@ -1,15 +1,13 @@ - - - - <% attribute_names_for_job_status(jobs_status).each do |attribute| %> - - <% end %> - + + + <% attribute_names_for_job_status(jobs_status).each do |attribute| %> + + <% end %> + - - <%= render partial: "mission_control/jobs/jobs/job", collection: jobs_page.jobs %> - + + <%= render partial: "mission_control/jobs/jobs/job", collection: jobs_page.jobs %>
Job<%= attribute %>
Job<%= attribute %>
From 609c8959a44b19f846df5759094e6fa90e403fe8 Mon Sep 17 00:00:00 2001 From: Alexandre Chakroun Date: Sat, 17 Feb 2024 01:29:21 +0100 Subject: [PATCH 18/24] Avoid forcing applications to have a root ApplicationJob defined Also remove unused MissionControl::Jobs::ApplicationJob --- .../mission_control/jobs/failed_jobs_bulk_operations.rb | 2 +- .../mission_control/jobs/bulk_discards_controller.rb | 2 +- .../mission_control/jobs/discards_controller.rb | 2 +- app/controllers/mission_control/jobs/jobs_controller.rb | 6 +++--- app/controllers/mission_control/jobs/queues_controller.rb | 8 ++++---- .../mission_control/jobs/retries_controller.rb | 2 +- app/helpers/mission_control/jobs/navigation_helper.rb | 2 +- app/jobs/mission_control/jobs/application_job.rb | 6 ------ 8 files changed, 12 insertions(+), 18 deletions(-) delete mode 100644 app/jobs/mission_control/jobs/application_job.rb diff --git a/app/controllers/concerns/mission_control/jobs/failed_jobs_bulk_operations.rb b/app/controllers/concerns/mission_control/jobs/failed_jobs_bulk_operations.rb index 4ab944d3..99bdaaf1 100644 --- a/app/controllers/concerns/mission_control/jobs/failed_jobs_bulk_operations.rb +++ b/app/controllers/concerns/mission_control/jobs/failed_jobs_bulk_operations.rb @@ -12,6 +12,6 @@ module MissionControl::Jobs::FailedJobsBulkOperations # or causing replication lag in MySQL). This should be enough for most scenarios. For # cases where we need to retry a huge sets of jobs, we offer a runbook that uses the API. def bulk_limited_filtered_failed_jobs - ApplicationJob.jobs.failed.where(**@job_filters).limit(MAX_NUMBER_OF_JOBS_FOR_BULK_OPERATIONS) + ActiveJob::Base.jobs.failed.where(**@job_filters).limit(MAX_NUMBER_OF_JOBS_FOR_BULK_OPERATIONS) end end diff --git a/app/controllers/mission_control/jobs/bulk_discards_controller.rb b/app/controllers/mission_control/jobs/bulk_discards_controller.rb index 085cc404..1638af96 100644 --- a/app/controllers/mission_control/jobs/bulk_discards_controller.rb +++ b/app/controllers/mission_control/jobs/bulk_discards_controller.rb @@ -14,7 +14,7 @@ def jobs_to_discard bulk_limited_filtered_failed_jobs else # we don't want to apply any limit since "discarding all" without parameters can be optimized in the adapter as a much faster operation - ApplicationJob.jobs.failed + ActiveJob::Base.jobs.failed end end end diff --git a/app/controllers/mission_control/jobs/discards_controller.rb b/app/controllers/mission_control/jobs/discards_controller.rb index 5f0d356a..c3165b16 100644 --- a/app/controllers/mission_control/jobs/discards_controller.rb +++ b/app/controllers/mission_control/jobs/discards_controller.rb @@ -8,6 +8,6 @@ def create private def jobs_relation - ApplicationJob.jobs.failed + ActiveJob::Base.jobs.failed end end diff --git a/app/controllers/mission_control/jobs/jobs_controller.rb b/app/controllers/mission_control/jobs/jobs_controller.rb index f8b25139..8d03cc8c 100644 --- a/app/controllers/mission_control/jobs/jobs_controller.rb +++ b/app/controllers/mission_control/jobs/jobs_controller.rb @@ -5,7 +5,7 @@ class MissionControl::Jobs::JobsController < MissionControl::Jobs::ApplicationCo def index @job_class_names = jobs_with_status.job_class_names - @queue_names = ApplicationJob.queues.map(&:name) + @queue_names = ActiveJob::Base.queues.map(&:name) @jobs_page = MissionControl::Jobs::Page.new(filtered_jobs_with_status, page: params[:page].to_i) @jobs_count = @jobs_page.total_count @@ -24,11 +24,11 @@ def filtered_jobs_with_status end def jobs_with_status - ApplicationJob.jobs.with_status(jobs_status) + ActiveJob::Base.jobs.with_status(jobs_status) end def filtered_jobs - ApplicationJob.jobs.where(**@job_filters) + ActiveJob::Base.jobs.where(**@job_filters) end helper_method :jobs_status diff --git a/app/controllers/mission_control/jobs/queues_controller.rb b/app/controllers/mission_control/jobs/queues_controller.rb index 1be7a3fb..bb1740e7 100644 --- a/app/controllers/mission_control/jobs/queues_controller.rb +++ b/app/controllers/mission_control/jobs/queues_controller.rb @@ -11,14 +11,14 @@ def show private def set_queue - @queue = ApplicationJob.queues[params[:id]] + @queue = ActiveJob::Base.queues[params[:id]] end def filtered_queues - if prefix = ApplicationJob.queue_name_prefix - ApplicationJob.queues.select { |queue| queue.name.start_with?(prefix) } + if prefix = ActiveJob::Base.queue_name_prefix + ActiveJob::Base.queues.select { |queue| queue.name.start_with?(prefix) } else - ApplicationJob.queues + ActiveJob::Base.queues end end end diff --git a/app/controllers/mission_control/jobs/retries_controller.rb b/app/controllers/mission_control/jobs/retries_controller.rb index 74c81128..0190aba4 100644 --- a/app/controllers/mission_control/jobs/retries_controller.rb +++ b/app/controllers/mission_control/jobs/retries_controller.rb @@ -8,6 +8,6 @@ def create private def jobs_relation - ApplicationJob.jobs.failed + ActiveJob::Base.jobs.failed end end diff --git a/app/helpers/mission_control/jobs/navigation_helper.rb b/app/helpers/mission_control/jobs/navigation_helper.rb index e386766c..3b8fee69 100644 --- a/app/helpers/mission_control/jobs/navigation_helper.rb +++ b/app/helpers/mission_control/jobs/navigation_helper.rb @@ -45,7 +45,7 @@ def jobs_filter_param end def jobs_count_with_status(status) - count = ApplicationJob.jobs.with_status(status).count + count = ActiveJob::Base.jobs.with_status(status).count count.infinite? ? "..." : number_to_human(count) end end diff --git a/app/jobs/mission_control/jobs/application_job.rb b/app/jobs/mission_control/jobs/application_job.rb deleted file mode 100644 index 62555bd3..00000000 --- a/app/jobs/mission_control/jobs/application_job.rb +++ /dev/null @@ -1,6 +0,0 @@ -module MissionControl - module Jobs - class ApplicationJob < ActiveJob::Base - end - end -end From 66c408e1354dc6a816026af4f00b9630c93fbd41 Mon Sep 17 00:00:00 2001 From: Andy Barringer Date: Fri, 23 Feb 2024 12:28:58 -0500 Subject: [PATCH 19/24] Get most recent job by active_job_id --- lib/active_job/queue_adapters/solid_queue_ext.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/active_job/queue_adapters/solid_queue_ext.rb b/lib/active_job/queue_adapters/solid_queue_ext.rb index a7e5b66e..ff62faab 100644 --- a/lib/active_job/queue_adapters/solid_queue_ext.rb +++ b/lib/active_job/queue_adapters/solid_queue_ext.rb @@ -169,7 +169,7 @@ def count end def find_job(active_job_id) - if job = SolidQueue::Job.find_by(active_job_id: active_job_id) + if job = SolidQueue::Job.where(active_job_id: active_job_id).order(:id).last job if matches_relation_filters?(job) end end From 5bcab55a7d6f80ef79b774fded4351ac3fa3c1bc Mon Sep 17 00:00:00 2001 From: Rosa Gutierrez Date: Mon, 26 Feb 2024 16:16:40 +0100 Subject: [PATCH 20/24] Add test for retries controller, for invalid and automatically retried jobs --- test/controllers/jobs_controller_test.rb | 3 +- test/controllers/retries_controller_test.rb | 31 +++++++++++++++++++++ test/test_helper.rb | 4 +++ 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 test/controllers/retries_controller_test.rb diff --git a/test/controllers/jobs_controller_test.rb b/test/controllers/jobs_controller_test.rb index ac9871cf..1baf8bde 100644 --- a/test/controllers/jobs_controller_test.rb +++ b/test/controllers/jobs_controller_test.rb @@ -25,10 +25,9 @@ class MissionControl::Jobs::JobsControllerTest < ActionDispatch::IntegrationTest test "get jobs and job details when there are multiple instances of the same job due to automatic retries" do job = AutoRetryingJob.perform_later - perform_enqueued_jobs_async # Wait until the job has been executed and retried - sleep(1) + perform_enqueued_jobs_async { sleep(1) } get mission_control_jobs.application_jobs_url(@application, :finished) assert_response :ok diff --git a/test/controllers/retries_controller_test.rb b/test/controllers/retries_controller_test.rb new file mode 100644 index 00000000..f6fc94fc --- /dev/null +++ b/test/controllers/retries_controller_test.rb @@ -0,0 +1,31 @@ +require "test_helper" + +class MissionControl::Jobs::JobsControllerTest < ActionDispatch::IntegrationTest + test "retry job with invalid ID" do + post mission_control_jobs.application_job_retry_url(@application, "unknown_id") + assert_redirected_to mission_control_jobs.application_jobs_url(@application, :failed) + follow_redirect! + + assert_select "article.is-danger", /Job with id 'unknown_id' not found/ + end + + test "retry jobs when there are multiple instances of the same job due to automatic retries" do + job = AutoRetryingJob.perform_later + + # Wait until the job has been executed and retried + perform_enqueued_jobs_async { sleep(1) } + + get mission_control_jobs.application_jobs_url(@application, :failed) + assert_response :ok + + assert_select "tr.job", 1 + assert_select "tr.job", /AutoRetryingJob\s+Enqueued less than a minute ago\s+AutoRetryingJob::RandomError/ + + post mission_control_jobs.application_job_retry_url(@application, job.job_id) + assert_redirected_to mission_control_jobs.application_jobs_url(@application, :failed) + follow_redirect! + + assert_select "article.is-danger", text: /Job with id '#{job.job_id}' not found/, count: 0 + assert_select "tr.job", 0 + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 9bdd33d7..a503d2b7 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -92,5 +92,9 @@ def queue_adapter_for_test def perform_enqueued_jobs_async @worker.start + if block_given? + yield + @worker.stop + end end end From d4eb8b0df18d43e355503fe5b484e4149c19a7a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20V=C3=A1squez?= Date: Tue, 27 Feb 2024 14:28:07 -0600 Subject: [PATCH 21/24] Add Discard action to scheduled jobs (#73) * Add Discard action to scheduled jobs This is adding the ability to discard a scheduled job. This is useful when a job is no longer needed and you want to remove it from the queue. Closes https://github.com/basecamp/mission_control-jobs/issues/58 --- app/helpers/mission_control/jobs/jobs_helper.rb | 2 +- .../mission_control/jobs/jobs/scheduled/_actions.html.erb | 4 ++++ app/views/mission_control/jobs/jobs/scheduled/_job.html.erb | 3 +++ test/controllers/jobs_controller_test.rb | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 app/views/mission_control/jobs/jobs/scheduled/_actions.html.erb diff --git a/app/helpers/mission_control/jobs/jobs_helper.rb b/app/helpers/mission_control/jobs/jobs_helper.rb index 9c5a61af..8736866b 100644 --- a/app/helpers/mission_control/jobs/jobs_helper.rb +++ b/app/helpers/mission_control/jobs/jobs_helper.rb @@ -20,7 +20,7 @@ def attribute_names_for_job_status(status) when "failed" then [ "Error", "" ] when "blocked" then [ "Queue", "Blocked by", "Block expiry" ] when "finished" then [ "Queue", "Finished" ] - when "scheduled" then [ "Queue", "Scheduled" ] + when "scheduled" then [ "Queue", "Scheduled", "" ] when "in_progress" then [ "Queue", "Run by", "Running for" ] else [] end diff --git a/app/views/mission_control/jobs/jobs/scheduled/_actions.html.erb b/app/views/mission_control/jobs/jobs/scheduled/_actions.html.erb new file mode 100644 index 00000000..e5108e62 --- /dev/null +++ b/app/views/mission_control/jobs/jobs/scheduled/_actions.html.erb @@ -0,0 +1,4 @@ +
+ <%= button_to "Discard", application_job_discard_path(@application, job.job_id), class: "button is-danger is-light mr-0", + form: { data: { turbo_confirm: "This will delete the job and can't be undone. Are you sure?" } } %> +
diff --git a/app/views/mission_control/jobs/jobs/scheduled/_job.html.erb b/app/views/mission_control/jobs/jobs/scheduled/_job.html.erb index 144c10ad..c3f9e499 100644 --- a/app/views/mission_control/jobs/jobs/scheduled/_job.html.erb +++ b/app/views/mission_control/jobs/jobs/scheduled/_job.html.erb @@ -5,3 +5,6 @@
delayed
<% end %> + + <%= render "mission_control/jobs/jobs/scheduled/actions", job: job %> + diff --git a/test/controllers/jobs_controller_test.rb b/test/controllers/jobs_controller_test.rb index 1baf8bde..c99245d3 100644 --- a/test/controllers/jobs_controller_test.rb +++ b/test/controllers/jobs_controller_test.rb @@ -62,5 +62,6 @@ class MissionControl::Jobs::JobsControllerTest < ActionDispatch::IntegrationTest assert_select "tr.job", 2 assert_select "tr.job", /DummyJob\s+Enqueued 2 minutes ago\s+queue_1\s+in 1 minute/ assert_select "tr.job", /DummyJob\s+Enqueued 2 minutes ago\s+queue_1\s+(1 minute ago|less than a minute ago)/ + assert_select "tr.job", /Discard/ end end From 6d7315b159a33e8b2c4261f322841c4324d41729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20Mari=C3=A9?= Date: Thu, 22 Feb 2024 14:07:17 +0100 Subject: [PATCH 22/24] All-in-one upgrade / platform / bundler --- Gemfile.lock | 210 +++++++++++++++++++++++++++------------------------ 1 file changed, 113 insertions(+), 97 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 7d89ff11..38d2f7e6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: https://github.com/basecamp/house-style - revision: 635db5b3a9e5efca8dad0eba4bd708eefc19dec4 + revision: a9ca7e4ab80b72c1a10053c50efefe8cd275e3b8 specs: rubocop-37signals (1.0.0) rubocop @@ -10,14 +10,14 @@ GIT GIT remote: https://github.com/basecamp/solid_queue - revision: 5ad872727251c32c282a7eb44df1e24068a3fdaa + revision: d71aa8ad6dd435fc458fc07be5ecc3b0cf4e89de specs: - solid_queue (0.2.0) + solid_queue (0.2.1) rails (~> 7.1) GIT remote: https://github.com/teamcapybara/capybara.git - revision: 52eaecea6d154b7d664b0032cd1cbcad4788fe65 + revision: c0cbf4024c1abd48b0c22c2930e7b05af58ab284 specs: capybara (3.40.0) addressable @@ -41,35 +41,35 @@ PATH GEM remote: https://rubygems.org/ specs: - actioncable (7.1.3) - actionpack (= 7.1.3) - activesupport (= 7.1.3) + actioncable (7.1.3.2) + actionpack (= 7.1.3.2) + activesupport (= 7.1.3.2) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (7.1.3) - actionpack (= 7.1.3) - activejob (= 7.1.3) - activerecord (= 7.1.3) - activestorage (= 7.1.3) - activesupport (= 7.1.3) + actionmailbox (7.1.3.2) + actionpack (= 7.1.3.2) + activejob (= 7.1.3.2) + activerecord (= 7.1.3.2) + activestorage (= 7.1.3.2) + activesupport (= 7.1.3.2) mail (>= 2.7.1) net-imap net-pop net-smtp - actionmailer (7.1.3) - actionpack (= 7.1.3) - actionview (= 7.1.3) - activejob (= 7.1.3) - activesupport (= 7.1.3) + actionmailer (7.1.3.2) + actionpack (= 7.1.3.2) + actionview (= 7.1.3.2) + activejob (= 7.1.3.2) + activesupport (= 7.1.3.2) mail (~> 2.5, >= 2.5.4) net-imap net-pop net-smtp rails-dom-testing (~> 2.2) - actionpack (7.1.3) - actionview (= 7.1.3) - activesupport (= 7.1.3) + actionpack (7.1.3.2) + actionview (= 7.1.3.2) + activesupport (= 7.1.3.2) nokogiri (>= 1.8.5) racc rack (>= 2.2.4) @@ -77,35 +77,35 @@ GEM rack-test (>= 0.6.3) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - actiontext (7.1.3) - actionpack (= 7.1.3) - activerecord (= 7.1.3) - activestorage (= 7.1.3) - activesupport (= 7.1.3) + actiontext (7.1.3.2) + actionpack (= 7.1.3.2) + activerecord (= 7.1.3.2) + activestorage (= 7.1.3.2) + activesupport (= 7.1.3.2) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.1.3) - activesupport (= 7.1.3) + actionview (7.1.3.2) + activesupport (= 7.1.3.2) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - activejob (7.1.3) - activesupport (= 7.1.3) + activejob (7.1.3.2) + activesupport (= 7.1.3.2) globalid (>= 0.3.6) - activemodel (7.1.3) - activesupport (= 7.1.3) - activerecord (7.1.3) - activemodel (= 7.1.3) - activesupport (= 7.1.3) + activemodel (7.1.3.2) + activesupport (= 7.1.3.2) + activerecord (7.1.3.2) + activemodel (= 7.1.3.2) + activesupport (= 7.1.3.2) timeout (>= 0.4.0) - activestorage (7.1.3) - actionpack (= 7.1.3) - activejob (= 7.1.3) - activerecord (= 7.1.3) - activesupport (= 7.1.3) + activestorage (7.1.3.2) + actionpack (= 7.1.3.2) + activejob (= 7.1.3.2) + activerecord (= 7.1.3.2) + activesupport (= 7.1.3.2) marcel (~> 1.0) - activesupport (7.1.3) + activesupport (7.1.3.2) base64 bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) @@ -119,67 +119,74 @@ GEM public_suffix (>= 2.0.2, < 6.0) ast (2.4.2) base64 (0.2.0) - bigdecimal (3.1.5) + bigdecimal (3.1.6) builder (3.2.4) - concurrent-ruby (1.1.10) + concurrent-ruby (1.2.3) connection_pool (2.4.1) crass (1.0.6) + date (3.3.4) debug (1.9.1) irb (~> 1.10) reline (>= 0.3.8) - digest (3.1.0) drb (2.2.0) ruby2_keywords - erubi (1.11.0) + erubi (1.12.0) globalid (1.2.1) activesupport (>= 6.1) - i18n (1.12.0) + i18n (1.14.1) concurrent-ruby (~> 1.0) importmap-rails (2.0.1) actionpack (>= 6.0.0) activesupport (>= 6.0.0) railties (>= 6.0.0) - io-console (0.7.1) - irb (1.11.1) + io-console (0.7.2) + irb (1.11.2) rdoc reline (>= 0.4.2) json (2.7.1) loofah (2.22.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) - mail (2.7.1) + mail (2.8.1) mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp marcel (1.0.2) matrix (0.4.2) - mini_mime (1.1.2) - minitest (5.16.2) - mocha (1.14.0) + mini_mime (1.1.5) + minitest (5.22.2) + mocha (2.1.0) + ruby2_keywords (>= 0.0.5) mono_logger (1.1.2) multi_json (1.15.0) mustermann (3.0.0) ruby2_keywords (~> 0.0.1) mutex_m (0.2.0) - net-imap (0.2.3) - digest + net-imap (0.4.10) + date net-protocol - strscan - net-pop (0.1.1) - digest + net-pop (0.1.2) net-protocol + net-protocol (0.2.2) timeout - net-protocol (0.1.3) - timeout - net-smtp (0.3.1) - digest + net-smtp (0.4.0.1) net-protocol - timeout nio4r (2.7.0) + nokogiri (1.16.2-aarch64-linux) + racc (~> 1.4) + nokogiri (1.16.2-arm-linux) + racc (~> 1.4) nokogiri (1.16.2-arm64-darwin) racc (~> 1.4) + nokogiri (1.16.2-x86-linux) + racc (~> 1.4) + nokogiri (1.16.2-x86_64-darwin) + racc (~> 1.4) nokogiri (1.16.2-x86_64-linux) racc (~> 1.4) parallel (1.24.0) - parser (3.3.0.4) + parser (3.3.0.5) ast (~> 2.4.1) racc psych (5.1.2) @@ -188,7 +195,7 @@ GEM puma (6.4.2) nio4r (~> 2.0) racc (1.7.3) - rack (3.0.9) + rack (3.0.9.1) rack-protection (4.0.0) base64 (>= 0.1.0) rack (>= 3.0.0, < 4) @@ -199,20 +206,20 @@ GEM rackup (2.1.0) rack (>= 3) webrick (~> 1.8) - rails (7.1.3) - actioncable (= 7.1.3) - actionmailbox (= 7.1.3) - actionmailer (= 7.1.3) - actionpack (= 7.1.3) - actiontext (= 7.1.3) - actionview (= 7.1.3) - activejob (= 7.1.3) - activemodel (= 7.1.3) - activerecord (= 7.1.3) - activestorage (= 7.1.3) - activesupport (= 7.1.3) + rails (7.1.3.2) + actioncable (= 7.1.3.2) + actionmailbox (= 7.1.3.2) + actionmailer (= 7.1.3.2) + actionpack (= 7.1.3.2) + actiontext (= 7.1.3.2) + actionview (= 7.1.3.2) + activejob (= 7.1.3.2) + activemodel (= 7.1.3.2) + activerecord (= 7.1.3.2) + activestorage (= 7.1.3.2) + activesupport (= 7.1.3.2) bundler (>= 1.15.0) - railties (= 7.1.3) + railties (= 7.1.3.2) rails-dom-testing (2.2.0) activesupport (>= 5.0.0) minitest @@ -220,22 +227,22 @@ GEM rails-html-sanitizer (1.6.0) loofah (~> 2.21) nokogiri (~> 1.14) - railties (7.1.3) - actionpack (= 7.1.3) - activesupport (= 7.1.3) + railties (7.1.3.2) + actionpack (= 7.1.3.2) + activesupport (= 7.1.3.2) irb rackup (>= 1.0.0) rake (>= 12.2) thor (~> 1.0, >= 1.2.2) zeitwerk (~> 2.6) rainbow (3.1.1) - rake (13.0.6) + rake (13.1.0) rdoc (6.6.2) psych (>= 4.0.0) redis (4.0.3) redis-namespace (1.11.0) redis (>= 4) - regexp_parser (2.5.0) + regexp_parser (2.9.0) reline (0.4.2) io-console (~> 0.5) resque (2.6.0) @@ -246,7 +253,7 @@ GEM resque-pause (0.3.0) multi_json (~> 1.0) resque (>= 1.9.10) - rexml (3.2.5) + rexml (3.2.6) rubocop (1.52.1) json (~> 2.3) parallel (~> 1.10) @@ -259,19 +266,21 @@ GEM unicode-display_width (>= 2.4.0, < 3.0) rubocop-ast (1.30.0) parser (>= 3.2.1.0) - rubocop-minitest (0.27.0) - rubocop (>= 0.90, < 2.0) + rubocop-minitest (0.34.5) + rubocop (>= 1.39, < 2.0) + rubocop-ast (>= 1.30.0, < 2.0) rubocop-performance (1.20.2) rubocop (>= 1.48.1, < 2.0) rubocop-ast (>= 1.30.0, < 2.0) - rubocop-rails (2.22.1) + rubocop-rails (2.23.1) activesupport (>= 4.2.0) rack (>= 1.1) rubocop (>= 1.33.0, < 2.0) + rubocop-ast (>= 1.30.0, < 2.0) ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) rubyzip (2.3.2) - selenium-webdriver (4.17.0) + selenium-webdriver (4.18.1) base64 (~> 0.2) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) @@ -289,33 +298,40 @@ GEM actionpack (>= 5.2) activesupport (>= 5.2) sprockets (>= 3.0.0) - sqlite3 (1.4.4) + sqlite3 (1.7.2-aarch64-linux) + sqlite3 (1.7.2-arm-linux) + sqlite3 (1.7.2-arm64-darwin) + sqlite3 (1.7.2-x86-linux) + sqlite3 (1.7.2-x86_64-darwin) + sqlite3 (1.7.2-x86_64-linux) stimulus-rails (1.3.3) railties (>= 6.0.0) stringio (3.1.0) - strscan (3.0.4) thor (1.3.0) tilt (2.3.0) timeout (0.4.1) - turbo-rails (1.5.0) + turbo-rails (2.0.4) actionpack (>= 6.0.0) activejob (>= 6.0.0) railties (>= 6.0.0) - tzinfo (2.0.5) + tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (2.5.0) webrick (1.8.1) - websocket (1.2.9) - websocket-driver (0.7.5) + websocket (1.2.10) + websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.0) + zeitwerk (2.6.13) PLATFORMS - arm64-darwin-21 - arm64-darwin-22 + aarch64-linux + arm-linux + arm64-darwin + x86-linux + x86_64-darwin x86_64-linux DEPENDENCIES @@ -338,4 +354,4 @@ DEPENDENCIES sqlite3 BUNDLED WITH - 2.3.24 + 2.5.6 From 6cf8371c48397954c7ced7d768dd8ee7d76e0e10 Mon Sep 17 00:00:00 2001 From: Lex Cao Date: Sun, 18 Feb 2024 22:56:09 +0800 Subject: [PATCH 23/24] Support dispatching blocked jobs directly from the UI Introduce the dispatch action to blocked jobs Closes #37 Signed-off-by: Lex Cao --- Gemfile.lock | 4 ++++ .../jobs/dispatches_controller.rb | 13 +++++++++++++ .../mission_control/jobs/jobs_helper.rb | 2 +- .../mission_control/jobs/jobs/_title.html.erb | 3 +++ .../jobs/jobs/blocked/_actions.html.erb | 3 +++ .../jobs/jobs/blocked/_job.html.erb | 3 +++ config/routes.rb | 1 + lib/active_job/executing.rb | 9 +++------ lib/active_job/failed.rb | 4 ---- lib/active_job/job_proxy.rb | 6 ++++++ lib/active_job/jobs_relation.rb | 5 +++++ .../queue_adapters/solid_queue_ext.rb | 11 +++++++++++ lib/mission_control/jobs/adapter.rb | 4 ++++ .../adapter_testing/dispatch_jobs.rb | 19 +++++++++++++++++++ .../queue_adapters/solid_queue_test.rb | 1 + test/dummy/app/jobs/blocking_job.rb | 7 +++++++ test/dummy/db/seeds.rb | 17 +++++++++++++---- 17 files changed, 97 insertions(+), 15 deletions(-) create mode 100644 app/controllers/mission_control/jobs/dispatches_controller.rb create mode 100644 app/views/mission_control/jobs/jobs/blocked/_actions.html.erb create mode 100644 test/active_job/queue_adapters/adapter_testing/dispatch_jobs.rb create mode 100644 test/dummy/app/jobs/blocking_job.rb diff --git a/Gemfile.lock b/Gemfile.lock index 38d2f7e6..ffb2453e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -330,8 +330,12 @@ PLATFORMS aarch64-linux arm-linux arm64-darwin + arm64-darwin-21 + arm64-darwin-22 x86-linux x86_64-darwin + x86_64-darwin-22 + x86_64-darwin-23 x86_64-linux DEPENDENCIES diff --git a/app/controllers/mission_control/jobs/dispatches_controller.rb b/app/controllers/mission_control/jobs/dispatches_controller.rb new file mode 100644 index 00000000..8ca94669 --- /dev/null +++ b/app/controllers/mission_control/jobs/dispatches_controller.rb @@ -0,0 +1,13 @@ +class MissionControl::Jobs::DispatchesController < MissionControl::Jobs::ApplicationController + include MissionControl::Jobs::JobScoped + + def create + @job.dispatch + redirect_to application_jobs_url(@application, :blocked), notice: "Dispatched job with id #{@job.job_id}" + end + + private + def jobs_relation + ApplicationJob.jobs.blocked + end +end diff --git a/app/helpers/mission_control/jobs/jobs_helper.rb b/app/helpers/mission_control/jobs/jobs_helper.rb index 8736866b..68cec842 100644 --- a/app/helpers/mission_control/jobs/jobs_helper.rb +++ b/app/helpers/mission_control/jobs/jobs_helper.rb @@ -18,7 +18,7 @@ def failed_job_backtrace(job) def attribute_names_for_job_status(status) case status.to_s when "failed" then [ "Error", "" ] - when "blocked" then [ "Queue", "Blocked by", "Block expiry" ] + when "blocked" then [ "Queue", "Blocked by", "Block expiry", "" ] when "finished" then [ "Queue", "Finished" ] when "scheduled" then [ "Queue", "Scheduled", "" ] when "in_progress" then [ "Queue", "Run by", "Running for" ] diff --git a/app/views/mission_control/jobs/jobs/_title.html.erb b/app/views/mission_control/jobs/jobs/_title.html.erb index e2b8209f..ed974e47 100644 --- a/app/views/mission_control/jobs/jobs/_title.html.erb +++ b/app/views/mission_control/jobs/jobs/_title.html.erb @@ -8,6 +8,9 @@ <% if job.failed? %> <%= render "mission_control/jobs/jobs/failed/actions", job: job %> <% end %> + <% if job.blocked? %> + <%= render "mission_control/jobs/jobs/blocked/actions", job: job %> + <% end %>
diff --git a/app/views/mission_control/jobs/jobs/blocked/_actions.html.erb b/app/views/mission_control/jobs/jobs/blocked/_actions.html.erb new file mode 100644 index 00000000..9afb0f86 --- /dev/null +++ b/app/views/mission_control/jobs/jobs/blocked/_actions.html.erb @@ -0,0 +1,3 @@ +
+ <%= button_to "Dispatch", application_job_dispatch_path(@application, job.job_id), class: "button is-warning is-light mr-0" %> +
diff --git a/app/views/mission_control/jobs/jobs/blocked/_job.html.erb b/app/views/mission_control/jobs/jobs/blocked/_job.html.erb index c4c1088b..8135c73f 100644 --- a/app/views/mission_control/jobs/jobs/blocked/_job.html.erb +++ b/app/views/mission_control/jobs/jobs/blocked/_job.html.erb @@ -1,3 +1,6 @@ <%= link_to job.queue_name, application_queue_path(@application, job.queue) %>
<%= job.blocked_by %>
<%= bidirectional_time_distance_in_words_with_title(job.blocked_until) %> + + <%= render "mission_control/jobs/jobs/blocked/actions", job: job %> + diff --git a/config/routes.rb b/config/routes.rb index 0a04ba44..8b2057c3 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,6 +9,7 @@ resources :jobs, only: :show do resource :retry, only: :create resource :discard, only: :create + resource :dispatch, only: :create collection do resource :bulk_retries, only: :create diff --git a/lib/active_job/executing.rb b/lib/active_job/executing.rb index e27ab15f..d8f7e24f 100644 --- a/lib/active_job/executing.rb +++ b/lib/active_job/executing.rb @@ -4,9 +4,8 @@ module ActiveJob::Executing extend ActiveSupport::Concern included do - attr_accessor :raw_data, :position, :finished_at, :blocked_by, :blocked_until, :worker_id, :started_at + attr_accessor :raw_data, :position, :finished_at, :blocked_by, :blocked_until, :worker_id, :started_at, :status attr_reader :serialized_arguments - attr_writer :status thread_cattr_accessor :current_queue_adapter end @@ -25,10 +24,8 @@ def discard jobs_relation_for_discarding.discard_job(self) end - def status - return @status if @status.present? - - failed? ? :failed : :pending + def dispatch + ActiveJob.jobs.blocked.dispatch_job(self) end private diff --git a/lib/active_job/failed.rb b/lib/active_job/failed.rb index 80049977..b1817365 100644 --- a/lib/active_job/failed.rb +++ b/lib/active_job/failed.rb @@ -4,8 +4,4 @@ module ActiveJob::Failed included do attr_accessor :last_execution_error, :failed_at end - - def failed? - last_execution_error.present? - end end diff --git a/lib/active_job/job_proxy.rb b/lib/active_job/job_proxy.rb index 7441db32..623415fb 100644 --- a/lib/active_job/job_proxy.rb +++ b/lib/active_job/job_proxy.rb @@ -23,4 +23,10 @@ def serialize def perform_now raise UnsupportedError, "A JobProxy doesn't support immediate execution, only enqueuing." end + + ActiveJob::JobsRelation::STATUSES.each do |status| + define_method "#{status}?" do + self.status == status + end + end end diff --git a/lib/active_job/jobs_relation.rb b/lib/active_job/jobs_relation.rb index 09a78ffe..5764c479 100644 --- a/lib/active_job/jobs_relation.rb +++ b/lib/active_job/jobs_relation.rb @@ -147,6 +147,11 @@ def discard_job(job) queue_adapter.discard_job(job, self) end + # Dispatch the provided job. + def dispatch_job(job) + queue_adapter.dispatch_job(job, self) + end + # Find a job by id. # # Returns nil when not found. diff --git a/lib/active_job/queue_adapters/solid_queue_ext.rb b/lib/active_job/queue_adapters/solid_queue_ext.rb index ff62faab..4e2ef7b9 100644 --- a/lib/active_job/queue_adapters/solid_queue_ext.rb +++ b/lib/active_job/queue_adapters/solid_queue_ext.rb @@ -82,6 +82,10 @@ def discard_job(job, jobs_relation) find_solid_queue_job!(job.job_id, jobs_relation).discard end + def dispatch_job(job, jobs_relation) + dispatch_immediately find_solid_queue_job!(job.job_id, jobs_relation) + end + def find_job(job_id, *) if job = SolidQueue::Job.where(active_job_id: job_id).order(:id).last deserialize_and_proxy_solid_queue_job job @@ -146,6 +150,13 @@ def execution_error_from_solid_queue_job(solid_queue_job) end end + def dispatch_immediately(job) + SolidQueue::Job.transaction do + job.dispatch_bypassing_concurrency_limits + job.blocked_execution.destroy! + end + end + class RelationAdapter STATUS_MAP = { pending: :ready, diff --git a/lib/mission_control/jobs/adapter.rb b/lib/mission_control/jobs/adapter.rb index 7ab5ac2f..278b5c94 100644 --- a/lib/mission_control/jobs/adapter.rb +++ b/lib/mission_control/jobs/adapter.rb @@ -102,6 +102,10 @@ def discard_job(job, jobs_relation) raise_incompatible_adapter_error_from :discard_job end + def dispatch_job(job, jobs_relation) + raise_incompatible_adapter_error_from :dispatch_job + end + def find_job(job_id, *) raise_incompatible_adapter_error_from :find_job end diff --git a/test/active_job/queue_adapters/adapter_testing/dispatch_jobs.rb b/test/active_job/queue_adapters/adapter_testing/dispatch_jobs.rb new file mode 100644 index 00000000..22c4b20b --- /dev/null +++ b/test/active_job/queue_adapters/adapter_testing/dispatch_jobs.rb @@ -0,0 +1,19 @@ +module ActiveJob::QueueAdapters::AdapterTesting::DispatchJobs + extend ActiveSupport::Testing::Declarative + + test "dispatch blocked job immediately" do + 10.times { |index| BlockingJob.perform_later(index * 0.1.seconds) } + + # Given, there is one pending and the others are blocked + pending_jobs = ActiveJob.jobs.pending + assert_equal 1, pending_jobs.size + blocked_jobs = ActiveJob.jobs.blocked + assert_equal 9, blocked_jobs.size + + blocked_jobs.each(&:dispatch) + + # Then, all blocked jobs are pending + assert_empty blocked_jobs.reload + assert_equal 10, pending_jobs.reload.size + end +end diff --git a/test/active_job/queue_adapters/solid_queue_test.rb b/test/active_job/queue_adapters/solid_queue_test.rb index ff62a28b..c5d1036e 100644 --- a/test/active_job/queue_adapters/solid_queue_test.rb +++ b/test/active_job/queue_adapters/solid_queue_test.rb @@ -2,6 +2,7 @@ class ActiveJob::QueueAdapters::SolidQueueTest < ActiveSupport::TestCase include ActiveJob::QueueAdapters::AdapterTesting + include DispatchJobs setup do SolidQueue.logger = ActiveSupport::Logger.new(nil) diff --git a/test/dummy/app/jobs/blocking_job.rb b/test/dummy/app/jobs/blocking_job.rb new file mode 100644 index 00000000..046be28e --- /dev/null +++ b/test/dummy/app/jobs/blocking_job.rb @@ -0,0 +1,7 @@ +class BlockingJob < ApplicationJob + limits_concurrency key: ->(*args) { "exclusive" } + + def perform(pause = nil) + sleep(pause) if pause + end +end diff --git a/test/dummy/db/seeds.rb b/test/dummy/db/seeds.rb index d642f200..36cae4a0 100644 --- a/test/dummy/db/seeds.rb +++ b/test/dummy/db/seeds.rb @@ -9,7 +9,7 @@ def clean_database end class JobsLoader - attr_reader :application, :server, :failed_jobs_count, :regular_jobs_count, :finished_jobs_count + attr_reader :application, :server, :failed_jobs_count, :regular_jobs_count, :finished_jobs_count, :blocked_jobs_count def initialize(application, server, failed_jobs_count: 100, regular_jobs_count: 50) @application = application @@ -17,6 +17,7 @@ def initialize(application, server, failed_jobs_count: 100, regular_jobs_count: @failed_jobs_count = randomize(failed_jobs_count) @regular_jobs_count = randomize(regular_jobs_count) @finished_jobs_count = randomize(regular_jobs_count) + @blocked_jobs_count = randomize(regular_jobs_count) end def load @@ -24,6 +25,7 @@ def load load_finished_jobs load_failed_jobs load_regular_jobs + load_blocked_jobs if server.queue_adapter.supported_statuses.include?(:blocked) end end @@ -31,10 +33,10 @@ def load def load_failed_jobs puts "Generating #{failed_jobs_count} failed jobs for #{application} - #{server}..." failed_jobs_count.times { |index| enqueue_one_of FailingJob => index, FailingReloadedJob => index, FailingPostJob => [ Post.last, 1.year.ago ] } - dispatch_jobs + perform_jobs end - def dispatch_jobs + def perform_jobs case server.queue_adapter_name when :resque worker = Resque::Worker.new("*") @@ -53,7 +55,7 @@ def load_finished_jobs regular_jobs_count.times do |index| enqueue_one_of DummyJob => index, DummyReloadedJob => index end - dispatch_jobs + perform_jobs end def load_regular_jobs @@ -63,6 +65,13 @@ def load_regular_jobs end end + def load_blocked_jobs + puts "Generating #{blocked_jobs_count} blocked jobs for #{application} - #{server}..." + blocked_jobs_count.times do |index| + enqueue_one_of BlockingJob => index + end + end + def with_random_queue(job_class) random_queue = [ "background", "reports", "default", "realtime" ].sample job_class.tap do From a82578acb793220e7dcd8c51c3893201ee460a66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20Mari=C3=A9?= Date: Thu, 22 Feb 2024 14:21:43 +0100 Subject: [PATCH 24/24] Add config.mission_control.jobs.show_console_help that defaults to true To display or hide the irb help message --- lib/mission_control/jobs.rb | 1 + lib/mission_control/jobs/engine.rb | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/mission_control/jobs.rb b/lib/mission_control/jobs.rb index 3ebbc7b5..f41052e5 100644 --- a/lib/mission_control/jobs.rb +++ b/lib/mission_control/jobs.rb @@ -16,5 +16,6 @@ module Jobs mattr_accessor :delay_between_bulk_operation_batches, default: 0 mattr_accessor :logger, default: ActiveSupport::Logger.new(nil) mattr_accessor :internal_query_count_limit, default: 500_000 # Hard limit to keep unlimited count queries fast enough + mattr_accessor :show_console_help, default: true end end diff --git a/lib/mission_control/jobs/engine.rb b/lib/mission_control/jobs/engine.rb index c4407940..6e3ad132 100644 --- a/lib/mission_control/jobs/engine.rb +++ b/lib/mission_control/jobs/engine.rb @@ -79,7 +79,9 @@ class Engine < ::Rails::Engine MissionControl::Jobs::Current.server = application.servers.first end - puts "\n\nType 'jobs_help' to see how to connect to the available job servers to manage jobs\n\n" + if MissionControl::Jobs.show_console_help + puts "\n\nType 'jobs_help' to see how to connect to the available job servers to manage jobs\n\n" + end end initializer "mission_control-jobs.assets" do |app|