From 619d0648448154c4f53e00dae4d15e5ec67d0187 Mon Sep 17 00:00:00 2001 From: Sylvester Chin <schin@gitlab.com> Date: Tue, 24 Oct 2023 08:32:02 +0000 Subject: [PATCH] Drop the use of namespace in Sidekiq and Mailroom delivery Changelog: other --- config/initializers/sidekiq.rb | 4 -- config/mail_room.yml | 1 - ...3045342_migrate_sidekiq_namespaced_jobs.rb | 59 ++++++++++++++++ db/schema_migrations/20231003045342 | 1 + lib/gitlab/patch/sidekiq_scheduled_enq.rb | 7 +- spec/lib/gitlab/mail_room/mail_room_spec.rb | 2 - .../patch/sidekiq_scheduled_enq_spec.rb | 26 ++----- ...42_migrate_sidekiq_namespaced_jobs_spec.rb | 67 +++++++++++++++++++ spec/support/redis.rb | 5 +- 9 files changed, 135 insertions(+), 37 deletions(-) create mode 100644 db/post_migrate/20231003045342_migrate_sidekiq_namespaced_jobs.rb create mode 100644 db/schema_migrations/20231003045342 create mode 100644 spec/migrations/20231003045342_migrate_sidekiq_namespaced_jobs_spec.rb diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index 57850e4e35c48..9b6a9b179359e 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -30,10 +30,6 @@ def enable_semi_reliable_fetch_mode? # Custom Queues configuration queues_config_hash = Gitlab::Redis::Queues.params -unless Gitlab::Utils.to_boolean(ENV['SIDEKIQ_ENQUEUE_NON_NAMESPACED']) - queues_config_hash[:namespace] = Gitlab::Redis::Queues::SIDEKIQ_NAMESPACE -end - enable_json_logs = Gitlab.config.sidekiq.log_format != 'text' Sidekiq.configure_server do |config| diff --git a/config/mail_room.yml b/config/mail_room.yml index b453ed8ce35c7..355df13fd6123 100644 --- a/config/mail_room.yml +++ b/config/mail_room.yml @@ -31,7 +31,6 @@ :delivery_options: :redis_url: <%= config[:redis_url].to_json %> :redis_db: <%= config[:redis_db] %> - :namespace: <%= Gitlab::Redis::Queues::SIDEKIQ_NAMESPACE %> :queue: <%= config[:queue] %> :worker: <%= config[:worker] %> <% if config[:sentinels] %> diff --git a/db/post_migrate/20231003045342_migrate_sidekiq_namespaced_jobs.rb b/db/post_migrate/20231003045342_migrate_sidekiq_namespaced_jobs.rb new file mode 100644 index 0000000000000..7d4d6876848be --- /dev/null +++ b/db/post_migrate/20231003045342_migrate_sidekiq_namespaced_jobs.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +class MigrateSidekiqNamespacedJobs < Gitlab::Database::Migration[2.1] + BATCH_SIZE = 1000 + SORTED_SET_NAMES = %w[schedule retry dead] + + def up + SORTED_SET_NAMES.each do |set_name| + sorted_set_migrate("resque:gitlab:#{set_name}", set_name) + end + + Sidekiq::Queue.all.each do |queue| + name = queue.name + sidekiq_queue_migrate("resque:gitlab:queue:#{name}", to: "queue:#{name}") + end + end + + def down + SORTED_SET_NAMES.each do |set_name| + sorted_set_migrate(set_name, "resque:gitlab:#{set_name}") + end + + Sidekiq::Queue.all.each do |queue| + name = queue.name + sidekiq_queue_migrate("queue:#{name}", to: "resque:gitlab:queue:#{name}") + end + end + + private + + def sidekiq_queue_migrate(queue_from, to:) + Gitlab::Redis::Queues.with do |conn| # rubocop:disable Cop/RedisQueueUsage + conn.rpoplpush(queue_from, to) while conn.llen(queue_from) > 0 + end + end + + def sorted_set_migrate(from, to) + cursor = '0' + + loop do + result = [] + + Gitlab::Redis::Queues.with do |redis| # rubocop:disable Cop/RedisQueueUsage + cursor, result = redis.zscan(from, cursor, count: BATCH_SIZE) + + next if result.empty? + + redis.multi do |multi| + multi.zadd(to, result.map { |k, v| [v, k] }) + multi.zrem(from, result.map { |k, _v| k }) + end + end + + sleep(0.01) + + break if cursor == '0' + end + end +end diff --git a/db/schema_migrations/20231003045342 b/db/schema_migrations/20231003045342 new file mode 100644 index 0000000000000..cf16a592ca62c --- /dev/null +++ b/db/schema_migrations/20231003045342 @@ -0,0 +1 @@ +a3a577992319a628fb7b1e8c492b1cb3ef1994d3e91e2af351c7b75a3900144d \ No newline at end of file diff --git a/lib/gitlab/patch/sidekiq_scheduled_enq.rb b/lib/gitlab/patch/sidekiq_scheduled_enq.rb index de0e8465f97a3..b5a40c199234d 100644 --- a/lib/gitlab/patch/sidekiq_scheduled_enq.rb +++ b/lib/gitlab/patch/sidekiq_scheduled_enq.rb @@ -15,10 +15,8 @@ def enqueue_jobs(sorted_sets = Sidekiq::Scheduled::SETS) # this portion swaps out Sidekiq.redis for Gitlab::Redis::Queues Gitlab::Redis::Queues.with do |conn| # rubocop:disable Cop/RedisQueueUsage sorted_sets.each do |sorted_set| - # adds namespace if `super` polls with a non-namespaced Sidekiq.redis - if Gitlab::Utils.to_boolean(ENV['SIDEKIQ_ENQUEUE_NON_NAMESPACED']) - sorted_set = "#{Gitlab::Redis::Queues::SIDEKIQ_NAMESPACE}:#{sorted_set}" # rubocop:disable Cop/RedisQueueUsage - end + # adds namespace since `super` polls with a non-namespaced Sidekiq.redis + sorted_set = "#{Gitlab::Redis::Queues::SIDEKIQ_NAMESPACE}:#{sorted_set}" # rubocop:disable Cop/RedisQueueUsage while !@done && (job = zpopbyscore(conn, keys: [sorted_set], argv: [Time.now.to_f.to_s])) # rubocop:disable Gitlab/ModuleWithInstanceVariables, Lint/AssignmentInCondition Sidekiq::Client.push(Sidekiq.load_json(job)) # rubocop:disable Cop/SidekiqApiUsage @@ -28,7 +26,6 @@ def enqueue_jobs(sorted_sets = Sidekiq::Scheduled::SETS) end end - # calls original enqueue_jobs which may or may not be namespaced depending on SIDEKIQ_ENQUEUE_NON_NAMESPACED super end end diff --git a/spec/lib/gitlab/mail_room/mail_room_spec.rb b/spec/lib/gitlab/mail_room/mail_room_spec.rb index 7259b5e2484cc..d3ddf034cd32a 100644 --- a/spec/lib/gitlab/mail_room/mail_room_spec.rb +++ b/spec/lib/gitlab/mail_room/mail_room_spec.rb @@ -245,7 +245,6 @@ delivery_options: { redis_url: "localhost", redis_db: 99, - namespace: "resque:gitlab", queue: "default", worker: "EmailReceiverWorker", sentinels: [{ host: "localhost", port: 1234 }] @@ -258,7 +257,6 @@ delivery_options: { redis_url: "localhost", redis_db: 99, - namespace: "resque:gitlab", queue: "default", worker: "ServiceDeskEmailReceiverWorker", sentinels: [{ host: "localhost", port: 1234 }] diff --git a/spec/lib/gitlab/patch/sidekiq_scheduled_enq_spec.rb b/spec/lib/gitlab/patch/sidekiq_scheduled_enq_spec.rb index f57257cd1c019..cd3718f5dccc3 100644 --- a/spec/lib/gitlab/patch/sidekiq_scheduled_enq_spec.rb +++ b/spec/lib/gitlab/patch/sidekiq_scheduled_enq_spec.rb @@ -10,7 +10,7 @@ allow(Sidekiq).to receive(:load_json).and_return(payload) # stub data in both namespaces - Sidekiq.redis { |c| c.zadd('schedule', 100, 'dummy') } + Gitlab::Redis::Queues.with { |c| c.zadd('resque:gitlab:schedule', 100, 'dummy') } Gitlab::Redis::Queues.with { |c| c.zadd('schedule', 100, 'dummy') } end @@ -26,7 +26,7 @@ end Gitlab::Redis::Queues.with do |conn| - expect(conn.zcard('schedule')).to eq(0) + expect(conn.zcard('resque:gitlab:schedule')).to eq(0) end end @@ -45,29 +45,13 @@ end Gitlab::Redis::Queues.with do |conn| - expect(conn.zcard('schedule')).to eq(1) + expect(conn.zcard('resque:gitlab:schedule')).to eq(1) end end end - context 'when both envvar are enabled' do - around do |example| - # runs the zadd to ensure it goes into namespaced set - Sidekiq.redis { |c| c.zadd('schedule', 100, 'dummy') } - - holder = Sidekiq.redis_pool - - # forcibly replace Sidekiq.redis since this is set in config/initializer/sidekiq.rb - Sidekiq.redis = Gitlab::Redis::Queues.pool - - example.run - - ensure - Sidekiq.redis = holder - end - + context 'when SIDEKIQ_ENABLE_DUAL_NAMESPACE_POLLING is enabled' do before do - stub_env('SIDEKIQ_ENQUEUE_NON_NAMESPACED', 'true') stub_env('SIDEKIQ_ENABLE_DUAL_NAMESPACE_POLLING', 'true') end @@ -81,7 +65,7 @@ end Gitlab::Redis::Queues.with do |conn| - expect(conn.zcard('schedule')).to eq(0) + expect(conn.zcard('resque:gitlab:schedule')).to eq(0) end end end diff --git a/spec/migrations/20231003045342_migrate_sidekiq_namespaced_jobs_spec.rb b/spec/migrations/20231003045342_migrate_sidekiq_namespaced_jobs_spec.rb new file mode 100644 index 0000000000000..9e170ff33a4ab --- /dev/null +++ b/spec/migrations/20231003045342_migrate_sidekiq_namespaced_jobs_spec.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe MigrateSidekiqNamespacedJobs, :migration, feature_category: :scalability do + before do + q1 = instance_double(Sidekiq::Queue, name: 'q1') + q2 = instance_double(Sidekiq::Queue, name: 'q2') + allow(Sidekiq::Queue).to receive(:all).and_return([q1, q2]) + + Gitlab::Redis::Queues.with do |redis| + (1..1000).each do |i| + redis.zadd('resque:gitlab:schedule', [i, i]) + redis.zadd('resque:gitlab:retry', [i, i]) + redis.zadd('resque:gitlab:dead', [i, i]) + end + + Sidekiq::Queue.all.each do |queue| + (1..1000).each do |i| + redis.lpush("resque:gitlab:queue:#{queue.name}", i) + end + end + end + end + + after do + Gitlab::Redis::Queues.with(&:flushdb) + end + + it "does not creates default organization if needed" do + reversible_migration do |migration| + migration.before -> { + Gitlab::Redis::Queues.with do |redis| + expect(redis.zcard('resque:gitlab:schedule')).to eq(1000) + expect(redis.zcard('resque:gitlab:retry')).to eq(1000) + expect(redis.zcard('resque:gitlab:dead')).to eq(1000) + expect(redis.zcard('schedule')).to eq(0) + expect(redis.zcard('retry')).to eq(0) + expect(redis.zcard('dead')).to eq(0) + + Sidekiq::Queue.all.each do |queue| + expect(redis.llen("resque:gitlab:queue:#{queue.name}")).to eq(1000) + expect(redis.llen("queue:#{queue.name}")).to eq(0) + end + end + } + + migration.after -> { + # no namespaced keys + Gitlab::Redis::Queues.with do |redis| + expect(redis.zcard('resque:gitlab:schedule')).to eq(0) + expect(redis.zcard('resque:gitlab:retry')).to eq(0) + expect(redis.zcard('resque:gitlab:dead')).to eq(0) + expect(redis.zcard('schedule')).to eq(1000) + expect(redis.zcard('retry')).to eq(1000) + expect(redis.zcard('dead')).to eq(1000) + + Sidekiq::Queue.all.each do |queue| + expect(redis.llen("resque:gitlab:queue:#{queue.name}")).to eq(0) + expect(redis.llen("queue:#{queue.name}")).to eq(1000) + end + end + } + end + end +end diff --git a/spec/support/redis.rb b/spec/support/redis.rb index ee6f00e4b63da..9cf5c44de98ad 100644 --- a/spec/support/redis.rb +++ b/spec/support/redis.rb @@ -3,10 +3,7 @@ RSpec.configure do |config| config.after(:each, :redis) do - Sidekiq.redis do |connection| - connection.redis.flushdb - end - + Sidekiq.redis(&:flushdb) redis_queues_metadata_cleanup! end -- GitLab