diff --git a/Gemfile b/Gemfile index 33d07c194..97c694e1b 100644 --- a/Gemfile +++ b/Gemfile @@ -21,7 +21,7 @@ gem 'flipper-active_record', '~> 1.3' gem 'flipper-ui', '~> 1.4' gem 'github_webhook', '~> 1.4' gem 'globalid' -gem 'good_job', '~> 4.3' +gem 'good_job', '~> 4.13' gem 'graphql' gem 'graphql-client' gem 'i18n' diff --git a/Gemfile.lock b/Gemfile.lock index 698d330ea..830536d90 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -171,7 +171,7 @@ GEM activemodel erb (6.0.2) erubi (1.13.1) - et-orbi (1.3.0) + et-orbi (1.4.0) tzinfo factory_bot (6.5.6) activesupport (>= 6.1.0) @@ -202,8 +202,8 @@ GEM rack-protection (>= 1.5.3, < 5.0.0) rack-session (>= 1.0.2, < 3.0.0) sanitize (< 8) - fugit (1.11.2) - et-orbi (~> 1, >= 1.2.11) + fugit (1.12.1) + et-orbi (~> 1.4) raabro (~> 1.4) github_webhook (1.4.2) activesupport (>= 4) @@ -211,7 +211,7 @@ GEM railties (>= 4) globalid (1.2.1) activesupport (>= 6.1) - good_job (4.11.2) + good_job (4.13.3) activejob (>= 6.1.0) activerecord (>= 6.1.0) concurrent-ruby (>= 1.3.1) @@ -557,7 +557,7 @@ GEM tilt (2.6.1) time (0.4.1) date - timeout (0.4.3) + timeout (0.6.1) tsort (0.2.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) @@ -616,7 +616,7 @@ DEPENDENCIES flipper-ui (~> 1.4) github_webhook (~> 1.4) globalid - good_job (~> 4.3) + good_job (~> 4.13) graphiql-rails graphql graphql-client diff --git a/db/migrate/20260319084430_add_index_good_jobs_concurrency_key_created_at.rb b/db/migrate/20260319084430_add_index_good_jobs_concurrency_key_created_at.rb new file mode 100644 index 000000000..470b205d1 --- /dev/null +++ b/db/migrate/20260319084430_add_index_good_jobs_concurrency_key_created_at.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class AddIndexGoodJobsConcurrencyKeyCreatedAt < ActiveRecord::Migration[7.2] + disable_ddl_transaction! + + def change + reversible do |dir| + dir.up do + # Ensure this incremental update migration is idempotent + # with monolithic install migration. + return if connection.index_exists? :good_jobs, [:concurrency_key, :created_at] + end + end + + add_index :good_jobs, [:concurrency_key, :created_at], algorithm: :concurrently + end +end diff --git a/db/migrate/20260319084431_add_index_good_jobs_job_class.rb b/db/migrate/20260319084431_add_index_good_jobs_job_class.rb new file mode 100644 index 000000000..4dbf50909 --- /dev/null +++ b/db/migrate/20260319084431_add_index_good_jobs_job_class.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class AddIndexGoodJobsJobClass < ActiveRecord::Migration[7.2] + disable_ddl_transaction! + + def change + reversible do |dir| + dir.up do + # Ensure this incremental update migration is idempotent + # with monolithic install migration. + return if connection.index_exists? :good_jobs, :job_class + end + end + + add_index :good_jobs, :job_class, algorithm: :concurrently + end +end \ No newline at end of file diff --git a/db/migrate/20260319084432_add_index_good_jobs_finished_at_for_cleanup.rb b/db/migrate/20260319084432_add_index_good_jobs_finished_at_for_cleanup.rb new file mode 100644 index 000000000..ee3c645bf --- /dev/null +++ b/db/migrate/20260319084432_add_index_good_jobs_finished_at_for_cleanup.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class AddIndexGoodJobsFinishedAtForCleanup < ActiveRecord::Migration[7.2] + disable_ddl_transaction! + + def change + reversible do |dir| + dir.up do + # Ensure this incremental update migration is idempotent + # with monolithic install migration. + return if connection.index_exists? :good_jobs, [:finished_at], name: :index_good_jobs_jobs_on_finished_at_only + end + end + + add_index :good_jobs, [:finished_at], where: "finished_at IS NOT NULL", name: :index_good_jobs_jobs_on_finished_at_only, algorithm: :concurrently + end +end diff --git a/db/migrate/20260319084433_remove_extraneous_finished_at_index.rb b/db/migrate/20260319084433_remove_extraneous_finished_at_index.rb new file mode 100644 index 000000000..afc269447 --- /dev/null +++ b/db/migrate/20260319084433_remove_extraneous_finished_at_index.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class RemoveExtraneousFinishedAtIndex < ActiveRecord::Migration[7.2] + disable_ddl_transaction! + + def change + reversible do |dir| + dir.up do + # Ensure this incremental update migration is idempotent + # with monolithic install migration. + return unless connection.index_exists? :good_jobs, [:finished_at], name: :index_good_jobs_jobs_on_finished_at + end + end + + remove_index :good_jobs, [:finished_at], where: "retried_good_job_id IS NULL AND finished_at IS NOT NULL", name: :index_good_jobs_jobs_on_finished_at, algorithm: :concurrently + end +end diff --git a/db/schema.rb b/db/schema.rb index 42455ef28..dc022dbea 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2026_03_10_161646) do +ActiveRecord::Schema[7.2].define(version: 2026_03_19_084433) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -178,10 +178,12 @@ t.index ["active_job_id", "created_at"], name: "index_good_jobs_on_active_job_id_and_created_at" t.index ["batch_callback_id"], name: "index_good_jobs_on_batch_callback_id", where: "(batch_callback_id IS NOT NULL)" t.index ["batch_id"], name: "index_good_jobs_on_batch_id", where: "(batch_id IS NOT NULL)" + t.index ["concurrency_key", "created_at"], name: "index_good_jobs_on_concurrency_key_and_created_at" t.index ["concurrency_key"], name: "index_good_jobs_on_concurrency_key_when_unfinished", where: "(finished_at IS NULL)" t.index ["cron_key", "created_at"], name: "index_good_jobs_on_cron_key_and_created_at_cond", where: "(cron_key IS NOT NULL)" t.index ["cron_key", "cron_at"], name: "index_good_jobs_on_cron_key_and_cron_at_cond", unique: true, where: "(cron_key IS NOT NULL)" - t.index ["finished_at"], name: "index_good_jobs_jobs_on_finished_at", where: "((retried_good_job_id IS NULL) AND (finished_at IS NOT NULL))" + t.index ["finished_at"], name: "index_good_jobs_jobs_on_finished_at_only", where: "(finished_at IS NOT NULL)" + t.index ["job_class"], name: "index_good_jobs_on_job_class" t.index ["labels"], name: "index_good_jobs_on_labels", where: "(labels IS NOT NULL)", using: :gin t.index ["locked_by_id"], name: "index_good_jobs_on_locked_by_id", where: "(locked_by_id IS NOT NULL)" t.index ["priority", "created_at"], name: "index_good_job_jobs_for_candidate_lookup", where: "(finished_at IS NULL)"