File: sidekiq.rb

package info (click to toggle)
gitlab 17.6.5-19
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 629,368 kB
  • sloc: ruby: 1,915,304; javascript: 557,307; sql: 60,639; xml: 6,509; sh: 4,567; makefile: 1,239; python: 406
file content (142 lines) | stat: -rw-r--r-- 6,309 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# frozen_string_literal: true
module SidekiqLogArguments
  def self.enabled?
    Gitlab::Utils.to_boolean(ENV['SIDEKIQ_LOG_ARGUMENTS'], default: true)
  end
end

# initialise migrated_shards on start-up to catch any malformed SIDEKIQ_MIGRATED_SHARD lists.
Gitlab::SidekiqSharding::Router.migrated_shards

# Custom Queues configuration
#
# We omit :command_builder since Sidekiq::RedisConnection performs a deep clone using
# Marshal.load(Marshal.dump(options.slice(*keys))) on the Redis config and Gitlab::Redis::CommandBuilder
# can't be referred to.
#
# We do not need the custom command builder since Sidekiq will handle the typing of Redis arguments.
queues_config_hash = Gitlab::Redis::Queues.params.except(:command_builder)
queue_instance = ENV.fetch('SIDEKIQ_SHARD_NAME', Gitlab::Redis::Queues::SIDEKIQ_MAIN_SHARD_INSTANCE_NAME)
queues_config_hash = Gitlab::Redis::Queues.instances[queue_instance].params.except(:command_builder)

enable_json_logs = Gitlab.config.sidekiq.log_format != 'text'

# Sidekiq's `strict_args!` raises an exception by default in 7.0
# https://github.com/sidekiq/sidekiq/blob/31bceff64e10d501323bc06ac0552652a47c082e/docs/7.0-Upgrade.md?plain=1#L59
# We set :warn in development/test to pick out workers that try to serialise complex args
strict_args_mode = Gitlab.dev_or_test_env? ? :warn : false
Sidekiq.strict_args!(strict_args_mode)

# Perform version check before configuring server with the custome scheduled job enqueue class
unless Gem::Version.new(Sidekiq::VERSION) == Gem::Version.new('7.2.4')
  raise 'New version of Sidekiq detected, please either update the version for this check ' \
        'and update Gitlab::SidekiqSharding::ScheduledEnq is compatible.'
end

Sidekiq.configure_server do |config|
  config[:strict] = false
  config[:scheduled_enq] = Gitlab::SidekiqSharding::ScheduledEnq
  config[:queues] = Gitlab::SidekiqConfig.expand_queues(config[:queues])

  if enable_json_logs
    config.logger.formatter = Gitlab::SidekiqLogging::JSONFormatter.new
    config[:job_logger] = Gitlab::SidekiqLogging::StructuredLogger

    # Remove the default-provided handler. The exception is logged inside
    # Gitlab::SidekiqLogging::StructuredLogger
    config.error_handlers.delete(Sidekiq::Config::ERROR_HANDLER)
  end

  config.logger.level = ENV.fetch("GITLAB_LOG_LEVEL", ::Logger::INFO)

  Sidekiq.logger.info "Listening on queues #{config[:queues].uniq.sort}"

  # In Sidekiq 6.x, connection pools have a size of concurrency+5.
  # ref: https://github.com/sidekiq/sidekiq/blob/v6.5.10/lib/sidekiq/redis_connection.rb#L93
  #
  # In Sidekiq 7.x, capsule connection pools have a size equal to its concurrency. Internal
  # housekeeping pool has a size of 10.
  # ref: https://github.com/sidekiq/sidekiq/blob/v7.1.6/lib/sidekiq/capsule.rb#L94
  # ref: https://github.com/sidekiq/sidekiq/blob/v7.1.6/lib/sidekiq/config.rb#L133
  #
  # We restore the concurrency+5 in Sidekiq 7.x to ensure that we do not experience resource bottlenecks with Redis
  # connections. The connections are created lazily so slightly over-provisioning a connection pool is not an issue.
  # This also increases the internal redis pool from 10 to concurrency+5.
  config.redis = queues_config_hash.merge({ size: config.concurrency + 5 })

  config.server_middleware(&Gitlab::SidekiqMiddleware.server_configurator(
    metrics: Settings.monitoring.sidekiq_exporter,
    arguments_logger: SidekiqLogArguments.enabled? && !enable_json_logs,
    skip_jobs: Gitlab::Utils.to_boolean(ENV['SIDEKIQ_SKIP_JOBS'], default: true)
  ))

  config.client_middleware(&Gitlab::SidekiqMiddleware.client_configurator)

  config.death_handlers << Gitlab::SidekiqDeathHandler.method(:handler)

  config.on :startup do
    # Clear any connections that might have been obtained before starting
    # Sidekiq (e.g. in an initializer).
    ActiveRecord::Base.clear_all_connections! # rubocop:disable Database/MultipleDatabases

    # Start monitor to track running jobs. By default, cancel job is not enabled
    # To cancel job, it requires `SIDEKIQ_MONITOR_WORKER=1` to enable notification channel
    Gitlab::SidekiqDaemon::Monitor.instance.start

    first_sidekiq_worker = !ENV['SIDEKIQ_WORKER_ID'] || ENV['SIDEKIQ_WORKER_ID'] == '0'
    health_checks = Settings.monitoring.sidekiq_health_checks

    # Start health-check in-process server
    if first_sidekiq_worker && health_checks.enabled
      Gitlab::HealthChecks::Server.instance(
        address: health_checks.address,
        port: health_checks.port
      ).start
    end
  end

  config.on(:shutdown) do
    Gitlab::Cluster::LifecycleEvents.do_worker_stop
  end

  config[:semi_reliable_fetch] = true # Default value is false

  Sidekiq::ReliableFetch.setup_reliable_fetch!(config)

  Gitlab::SidekiqVersioning.install!

  config[:cron_poll_interval] = Gitlab.config.cron_jobs.poll_interval
  config[:cron_poll_interval] = 0 if queue_instance != Gitlab::Redis::Queues::SIDEKIQ_MAIN_SHARD_INSTANCE_NAME

  Gitlab::SidekiqConfig::CronJobInitializer.execute

  # Avoid autoload issue such as 'Mail::Parsers::AddressStruct'
  # https://github.com/mikel/mail/issues/912#issuecomment-214850355
  Mail.eager_autoload!

  # Ensure the whole process group is terminated if possible
  Gitlab::SidekiqSignals.install!(Sidekiq::CLI::SIGNAL_HANDLERS)
end

Sidekiq.configure_client do |config|
  config.redis = queues_config_hash
  # We only need to do this for other clients. If Sidekiq-server is the
  # client scheduling jobs, we have access to the regular sidekiq logger that
  # writes to STDOUT
  config.logger = Gitlab::SidekiqLogging::ClientLogger.build
  config.logger.formatter = Gitlab::SidekiqLogging::JSONFormatter.new if enable_json_logs

  config.client_middleware(&Gitlab::SidekiqMiddleware.client_configurator)
end

Gitlab::Application.configure do |config|
  config.middleware.use(Gitlab::Middleware::SidekiqShardAwarenessValidation)
end

Sidekiq::Scheduled::Poller.prepend Gitlab::Patch::SidekiqPoller
Sidekiq::Cron::Poller.prepend Gitlab::Patch::SidekiqPoller
Sidekiq::Cron::Poller.prepend Gitlab::Patch::SidekiqCronPoller

Sidekiq::Client.prepend Gitlab::SidekiqSharding::Validator::Client
Sidekiq::RedisClientAdapter::CompatMethods.prepend Gitlab::SidekiqSharding::Validator
Sidekiq::Job::Setter.prepend Gitlab::Patch::SidekiqJobSetter