The "sidekiq" executable file
The first line of code in this file is:
#!/usr/bin/env ruby
Shebang
This file is loaded into our $PATH
environment variable by our Ruby version manager, which is how we're able to execute it simply by typing sidekiq
in our terminal. But the reason we don't have to preface the sidekiq
command with the ruby
command is because of this shebang at the top of the file, which tells the computer what kind of code this file contains, and therefore how to execute it.
Reducing Nose When Running In Warning Mode
Next block of code:
# Quiet some warnings we see when running in warning mode:
# RUBYOPT=-w bundle exec sidekiq
$TESTING = false
The comment says that the purpose of the code $TESTING = false
is to "(q)uiet some warnings we see when running in warning mode". But what is "warning mode", and how do we enable it?
In this case, warning mode is enabled by running bundle exec sidekiq
with the RUBYOPT
variable set to include =-w
. The man ruby
page documents the RUBYOPT
variable:
RUBYOPT Additional Ruby options.
e.g.
RUBYOPT="-w -Ke"
Note that RUBYOPT can contain only -d, -E, -I, -K, -r, -T, -U, -v, -w, -W, --debug, --disable-FEATURE and --enable-FEATURE.
IMHO, this documentation isn't super-thorough: it just says "Additional Ruby options", which... great.
After Googling around a bit, I found this discussion forum, wherein a user named Justin Baker says:
RUBYOPT is an environment variable that you can set to cause every invocation of `ruby` to be started with those options.
This would be handy if you wanted to make sure some of Ruby's options were always passed by default, without having to pass them manually every time.
Here we're concerned with the -w
option, since that's what's mentioned in the commented-out line of code. If we re-run man ruby
and search for -w
, we see this flag does the following:
-w Enables verbose mode without printing version message at the beginning.
It sets the $VERBOSE variable to true.
Experiment- running Ruby with and without verbose mode
What is verbose mode, and what kinds of information should we expect to see when running in verbose mode, which we would not see when running in non-verbose mode?
One type of info is warnings. For example, if we try to reference an instance variable which hasn't yet been defined, we'll get a warning, but only when we're in -w
mode. For example, let's say we have a script named "foo.rb" which looks like so:
# foo.rb
@undefined_variable
puts "Hello world"
If we then run ruby foo.rb
from our terminal, we see the following:
$ ruby foo.rb
Hello world
If, however, we pass the -w
flag, we see:
$ ruby -w foo.rb
foo.rb:2: warning: possibly useless use of a variable in void context
Hello world
So these are the kinds of "warnings" that the comments here told us we can prevent from showing up by setting $TESTING
equal to true
. But how does doing the former cause the latter to happen? Is this done automatically by Ruby, or is it in the code somewhere?
As it turns out, the answer is the latter. This block of code calls the warn
method, but only under certain conditions. One of those conditions is that $TESTING
should be false
:
if defined?(::Rails) && Rails.respond_to?(:env) && !Rails.env.test? && !$TESTING
warn("⛔️ WARNING: Sidekiq testing API enabled, but this is not the test environment. Your jobs will not go to Redis.", uplevel: 1)
end
If !$TESTING
(i.e. $TESTING
with a bang in front of it) is true
, then $TESTING
must be false
.
Why Disable Warnings?
For further context on why the above code was added, we can run git blame
on this file, look up the commit SHA, and search for that SHA in Github:
$ git blame bin/sidekiq
726b6cad7 (Mike Perham 2012-01-16 16:14:47 -0800 1) #!/usr/bin/env ruby
726b6cad7 (Mike Perham 2012-01-16 16:14:47 -0800 2)
bcbe9b258 (Mike Perham 2015-06-22 09:14:55 -0700 3) # Quiet some warnings we see when running in warning mode:
bcbe9b258 (Mike Perham 2015-06-22 09:14:55 -0700 4) # RUBYOPT=-w bundle exec sidekiq
bcbe9b258 (Mike Perham 2015-06-22 09:14:55 -0700 5) $TESTING = false
bcbe9b258 (Mike Perham 2015-06-22 09:14:55 -0700 6)
...
If we search Sidekiq's Github repo for the SHA bcbe9b258
, we find this link, with a description that says the PR was added to resolve this reported issue:
When I enable ruby warnings (aka verbose mode) I get the following warning:
/Users/iain/.gem/ruby/2.2.2/gems/sidekiq-3.0.0/lib/sidekiq/fetch.rb:85: warning: instance variable @done not initialized
It happens every second or so (looks like sidekiq is polling for new jobs). It looks like the code has a class variable called @done which is read but never initialized here.I'm happy to fix it, but I don't have any good suggestions about how to initialize it cleanly, and wanted to ask in case you have any ideas (before I do the work).
So the user who reported the issue was running Ruby in verbose mode, and seeing warnings because an instance variable named @done
was being referenced in one of Sidekiq's files (~/.gem/ruby/2.2.2/gems/sidekiq-3.0.0/lib/sidekiq/fetch.rb
) but hadn't been defined yet. This was unnoticeable in regular Ruby mode, but triggered a warning in verbose mode. The PR which introduced our current block of code prevents the warning from being triggered, by replacing the simple reference to @done
with the more syntactically-correct defined? @done
inside the self.done?
method body.
Wrapping Up
Let's now move on to the integrate_with_systemd
method, which is implemented in the next block of code and then invoked a bit later inside our current file.