Upgrade to 3.0.2: NameError: undefined method `call' for class `Redis::Client' (with a "fix")

Just tried upgrading from 3.0.1 to 3.0.2, and got this error during rake db:migrate stage:

rake aborted!
NameError: undefined method `call' for class `Redis::Client'
Did you mean?  caller
/var/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/mini_profiler/profiling_methods.rb:83:in `alias_method'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/mini_profiler/profiling_methods.rb:83:in `profile_method'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/mini_profiler/profiling_methods.rb:65:in `counter_method'
/var/discourse/config/initializers/006-mini_profiler.rb:90:in `<main>'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/railties-7.0.4.3/lib/rails/engine.rb:667:in `load'

Very long story short, I found that pegging redis at version 4.8.0 instead of leaving the redis version unspecified in the Gemfile did the trick. I.e., for the Gemfile:

-gem "redis"
+gem "redis", "4.8.0"

I don’t feel very comfortable mucking about with this, but it seems to me that this is an unintended side effect of redis being upgraded elsewhere since my last upgrade (to 3.0.1), and that a reinstall of Discourse 3.0.1 would now show the same problem.

Hope this helps someone, and please let me know if this leaves my system in a vulnerable state :slight_smile:

1 Like

We set gem versions on the Gemfile.lock file, and it’s already set to that same version

Quite! Strange, since I had never heard about either Gemfile or Gemfile.lock before. But having 20 other fora to repeat the install on (sigh), it turns out that the whole thing started with a different problem during install where the complaints ended with a recommendation to try deleting the Gemfile.lock:

Bundler found conflicting requirements for the Ruby version:
  In Gemfile:
    actionmailer (= 7.0.4.3) was resolved to 7.0.4.3, which depends on
      Ruby (>= 2.7.0)

    sassc-rails was resolved to 2.1.2, which depends on
      sprockets-rails was resolved to 3.4.2, which depends on
        Ruby (>= 2.5)

    json was resolved to 2.6.3, which depends on
      Ruby (>= 2.3)
:
:
:
    json_schemer was resolved to 0.2.23, which depends on
      ecma-re-validator (~> 0.3) was resolved to 0.4.0, which depends on
        Ruby (>= 2.6, < 4.0)

    rspec was resolved to 3.12.0, which depends on
      rspec-expectations (~> 3.12.0) was resolved to 3.12.2, which depends on
        diff-lcs (>= 1.2.0, < 2.0) was resolved to 1.5.0, which depends on
          Ruby (>= 1.8)

    web-push was resolved to 3.0.0, which depends on
      Ruby (>= 3.0)

  Current Ruby version:
    Ruby (= 2.7.6)

Bundler could not find compatible versions for gem "hkdf":
  In snapshot (Gemfile.lock):
    hkdf (= 1.0.0)

  In Gemfile:
    web-push was resolved to 1.0.0, which depends on
      hkdf (~> 0.2)

Deleting your Gemfile.lock file and running `bundle install` will rebuild your
snapshot from scratch, using only
the gems in your Gemfile, which may resolve the conflict.

So, I got past that initial error after removing the lock file as suggested, then ran into the NameError: undefined method ‘call’ described earlier. Fixed that by pegging the redis version. Then, everything worked.

So, my script was modified to a) remove Gemfile.lock (because of the error quoted above) and b) automatically change the Gemfile to peg redis at 4.8.0. Hunky dory… I thought. This worked on three out of the 20 “identical” machines! The rest gave this new error:

[discourse@in3020-discourse discourse]$ cd $INSTA; RAILS_ENV=production /usr/local/bin/bundle exec rake db:migrate # stuffing a lot of stuff into the database
rake aborted!
NoMethodError: undefined method `logger=' for Sidekiq:Module
Did you mean?  logger
/var/discourse/config/initializers/100-sidekiq.rb:58:in `<main>'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/railties-7.0.4.3/lib/rails/engine.rb:667:in `load'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/railties-7.0.4.3/lib/rails/engine.rb:667:in `block in load_config_initializer'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.4.3/lib/active_support/notifications.rb:208:in `instrument'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/railties-7.0.4.3/lib/rails/engine.rb:666:in `load_config_initializer'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/railties-7.0.4.3/lib/rails/engine.rb:620:in `block (2 levels) in <class:Engine>'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/railties-7.0.4.3/lib/rails/engine.rb:619:in `each'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/railties-7.0.4.3/lib/rails/engine.rb:619:in `block in <class:Engine>'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/railties-7.0.4.3/lib/rails/initializable.rb:32:in `instance_exec'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/railties-7.0.4.3/lib/rails/initializable.rb:32:in `run'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/railties-7.0.4.3/lib/rails/initializable.rb:61:in `block in run_initializers'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/railties-7.0.4.3/lib/rails/initializable.rb:50:in `each'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/railties-7.0.4.3/lib/rails/initializable.rb:50:in `tsort_each_child'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/railties-7.0.4.3/lib/rails/initializable.rb:60:in `run_initializers'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/railties-7.0.4.3/lib/rails/application.rb:372:in `initialize!'
/var/discourse/config/environment.rb:7:in `<main>'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.6.7/lib/zeitwerk/kernel.rb:38:in `require'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/railties-7.0.4.3/lib/rails/application.rb:348:in `require_environment!'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/railties-7.0.4.3/lib/rails/application.rb:511:in `block in run_tasks_blocks'
/var/discourse/vendor/bundle/ruby/2.7.0/gems/rake-13.0.6/exe/rake:27:in `<top (required)>'
/usr/local/share/gems/gems/bundler-2.3.26/lib/bundler/cli/exec.rb:58:in `load'
/usr/local/share/gems/gems/bundler-2.3.26/lib/bundler/cli/exec.rb:58:in `kernel_load'
/usr/local/share/gems/gems/bundler-2.3.26/lib/bundler/cli/exec.rb:23:in `run'
/usr/local/share/gems/gems/bundler-2.3.26/lib/bundler/cli.rb:486:in `exec'
/usr/local/share/gems/gems/bundler-2.3.26/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/usr/local/share/gems/gems/bundler-2.3.26/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
/usr/local/share/gems/gems/bundler-2.3.26/lib/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
/usr/local/share/gems/gems/bundler-2.3.26/lib/bundler/cli.rb:31:in `dispatch'
/usr/local/share/gems/gems/bundler-2.3.26/lib/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
/usr/local/share/gems/gems/bundler-2.3.26/lib/bundler/cli.rb:25:in `start'
/usr/local/share/gems/gems/bundler-2.3.26/exe/bundle:48:in `block in <top (required)>'
/usr/local/share/gems/gems/bundler-2.3.26/lib/bundler/friendly_errors.rb:120:in `with_friendly_errors'
/usr/local/share/gems/gems/bundler-2.3.26/exe/bundle:36:in `<top (required)>'
/usr/local/bin/bundle:23:in `load'
/usr/local/bin/bundle:23:in `<main>'
Tasks: TOP => db:migrate => db:load_config => environment
(See full trace by running task with --trace)

Which was really, really strange because the /var/discourse/config/initializers/100-sidekiq.rb files were identical on all machines, and certainly did not contain ‘logger=’, but a ‘logger = …’ statement.

I finally figured out that on the machines where it worked, /usr/local/bin/bundle was version 2.3.20, not 2.3.26 as on the machines where it failed. So in sum, adding this before the install command for discourse did the trick for me (it was not enough to do the bundler pegging at 2.3.20 commands after the bundler install of discourse, it had to be before):

rm Gemfile.lock
perl -pi.bak -e 's/gem "redis"/gem "redis","4.8.0"/;' Gemfile

/usr/bin/gem uninstall bundler -v 2.3.26
/usr/bin/gem install bundler -v 2.3.20
RAILS_ENV=production /usr/local/bin/bundle install
RAILS_ENV=production /usr/local/bin/bundle exec rake db:migrate
RAILS_ENV=production /usr/local/bin/bundle exec rake assets:precompile

Why on Earth some of those machines had bundler 2.3.26 and others had 2.3.20 I have no idea… but it’s probably not your fault :laughing:.

And this is why I use the stable version :laughing:

Ruby 2.7 is EOL and not supported by us anymore. You don’t get that version when installing Discourse following the standard install guide for a while, so I assume this is a custom install?

I recommend sticking to the supported official install guide even for people familiar with Discourse stack, and that is even more important for people unfamiliar with the technologies used.

Yes, doing it the official way would almost certainly have given me fewer headaches (most likely none). The problem is that I’m not allowed to use docker images that are not pre-approved by our IT security department - and yours is not.

So this is indeed a custom, native install on RHEL8 machines, which also needed some SELinux trickery to work.

Maybe there are others out there with the same problem - perhaps it would be useful to them if I post a topic with my installation procedure? Feel free to protest - I can see that this could be taken as an “encouragement” to install it this way even if not strictly necessary, which could lead to more questions for you.

As an aside, when googling for solutions to any SELinux problem, the most frequent advice you will find is “this is how you disable it”:laughing:. But this is not an option here.

Thanks for your help!

Thanks for the context. Just be aware that we do not offer free support for custom installs here.

This install is already using a version of Ruby that doesn’t work with any of the current versions of Discourse, does not respect any of the carefully managed gem versions, and doesn’t use all the manually managed OS level shared libraries we ship. Therefore, breakage is not a question of if but more of a question of when.

3 Likes

You might suggest to your security team that an image that is vetted and used by the developers is much, much safer than your attempting to apply security patches to things that you can’t possibly keep track of unless it’s your only job.

. . . . But, that’s likely not helpful.

Haha, yes (probably safer w/your images) and no (not helpful - but thanks for the comment anyway😊).

This is indeed not my day job, I’m just running these fora “because I’m the one who could do it” as a pilot program so we can convince our IT department to pick it up and run it for the entire University of Oslo.

Fortunately, that seems to have worked, so hopefully this is the last semester that I have to run the show. I bet the IT department will use the images… :wink:

And thanks, @Falco, for pointing out that there is a Ruby version mismatch, will have a look at it if/when I run into problems with future updates.

1 Like

Holy cow! Having been faculty at several universities in the US, I’m quite impressed.

1 Like

Oops, forgot to press the Reply button on this long ago…

@pfaffman Haha, yes. We’re not 100% out of the woods yet though, even if IT says ok: it has to be approved at the tippety-top (by the university board) as an official communication channel first. Fortunately, we got the Natural Sciences Department on board big time, and they’ve been pushing it through the hoops.

I’m quite proud to have been able to run these pilot instances - not many non-IT-department people would have been able to do so (within the necessary security policies, that is). The Natural Sciences people consistently refer to it as “Astro-Discourse” (I’m at the Institute of Theoretical Astrophysics) :laughing:.

But now… it seems I have to run this show one more semester, with the same non-standard setup. I’m wondering, which pgsql version(s) is the current Discourse release compatible with?