Redis Error after update

I keep getting this Redis Error when I try to migrate my db. This discourse docker install. Please help.

1 Like

Do you have a 2 container install or redis hosted elsewhere? Do you have redis 6.2?

2 Likes

This is my Redis version 6.2.6 and I only have one redis container in my docker and then a few discourse_dev containers too.

2 Likes

I have requested help on the sidekiq github too.

This is what comes up when I run in my docker container
d/bundle show redis

/Users/natashaselvidge/discourse/vendor/bundle/ruby/2.6.0/gems/redis-4.6.0

Here is my discourse_redis.rb file

#
#  A wrapper around redis that namespaces keys with the current site id
#

class DiscourseRedis
  def self.raw_connection(config = nil)
    config ||= self.config
    Redis.new(config)
  end

  def self.config
    GlobalSetting.redis_config
  end

  def initialize(config = nil, namespace: true)
    @config = config || DiscourseRedis.config
    @redis = DiscourseRedis.raw_connection(@config.dup)
    @namespace = namespace
  end

  def without_namespace
    # Only use this if you want to store and fetch data that's shared between sites
    @redis
  end

  def self.ignore_readonly
    yield
  rescue Redis::CommandError => ex
    if ex.message =~ /READONLY/
      Discourse.received_redis_readonly!
      nil
    else
      raise ex
    end
  end

  # prefix the key with the namespace
  def method_missing(meth, *args, **kwargs, &block)
    if @redis.respond_to?(meth)
      DiscourseRedis.ignore_readonly { @redis.public_send(meth, *args, **kwargs, &block) }
    else
      super
    end
  end

  # Proxy key methods through, but prefix the keys with the namespace
  [:append, :blpop, :brpop, :brpoplpush, :decr, :decrby, :expire, :expireat, :get, :getbit, :getrange, :getset,
   :hdel, :hexists, :hget, :hgetall, :hincrby, :hincrbyfloat, :hkeys, :hlen, :hmget, :hmset, :hset, :hsetnx, :hvals, :incr,
   :incrby, :incrbyfloat, :lindex, :linsert, :llen, :lpop, :lpush, :lpushx, :lrange, :lrem, :lset, :ltrim,
   :mapped_hmset, :mapped_hmget, :mapped_mget, :mapped_mset, :mapped_msetnx, :move, :mset,
   :msetnx, :persist, :pexpire, :pexpireat, :psetex, :pttl, :rename, :renamenx, :rpop, :rpoplpush, :rpush, :rpushx, :sadd, :scard,
   :sdiff, :set, :setbit, :setex, :setnx, :setrange, :sinter, :sismember, :smembers, :sort, :spop, :srandmember, :srem, :strlen,
   :sunion, :ttl, :type, :watch, :zadd, :zcard, :zcount, :zincrby, :zrange, :zrangebyscore, :zrank, :zrem, :zremrangebyrank,
   :zremrangebyscore, :zrevrange, :zrevrangebyscore, :zrevrank, :zrangebyscore,
   :dump, :restore].each do |m|
    define_method m do |*args, **kwargs|
      args[0] = "#{namespace}:#{args[0]}" if @namespace
      DiscourseRedis.ignore_readonly { @redis.public_send(m, *args, **kwargs) }
    end
  end

  def exists(*args)
    args.map! { |a| "#{namespace}:#{a}" } if @namespace
    DiscourseRedis.ignore_readonly { @redis.exists(*args) }
  end

  def exists?(*args)
    args.map! { |a| "#{namespace}:#{a}" } if @namespace
    DiscourseRedis.ignore_readonly { @redis.exists?(*args) }
  end

  def mget(*args)
    args.map! { |a| "#{namespace}:#{a}" }  if @namespace
    DiscourseRedis.ignore_readonly { @redis.mget(*args) }
  end

  def del(*keys)
    DiscourseRedis.ignore_readonly do
      keys = keys.flatten(1)
      keys.map! { |k| "#{namespace}:#{k}" } if @namespace
      @redis.del(*keys)
    end
  end

  def scan_each(options = {}, &block)
    DiscourseRedis.ignore_readonly do
      match = options[:match].presence || '*'

      options[:match] =
        if @namespace
          "#{namespace}:#{match}"
        else
          match
        end

      if block
        @redis.scan_each(**options) do |key|
          key = remove_namespace(key) if @namespace
          block.call(key)
        end
      else
        @redis.scan_each(**options).map do |key|
          key = remove_namespace(key) if @namespace
          key
        end
      end
    end
  end

  def keys(pattern = nil)
    DiscourseRedis.ignore_readonly do
      pattern = pattern || '*'
      pattern = "#{namespace}:#{pattern}" if @namespace
      keys = @redis.keys(pattern)

      if @namespace
        len = namespace.length + 1
        keys.map! { |k| k[len..-1] }
      end

      keys
    end
  end

  def delete_prefixed(prefix)
    DiscourseRedis.ignore_readonly do
      keys("#{prefix}*").each { |k| Discourse.redis.del(k) }
    end
  end

  def reconnect
    @redis._client.reconnect
  end

  def namespace_key(key)
    if @namespace
      "#{namespace}:#{key}"
    else
      key
    end
  end

  def namespace
    RailsMultisite::ConnectionManagement.current_db
  end

  def self.new_redis_store
    Cache.new
  end

  private

  def remove_namespace(key)
    key[(namespace.length + 1)..-1]
  end

  class EvalHelper
    def initialize(script)
      @script = script
      @sha1 = Digest::SHA1.hexdigest(script)
    end

    def eval(redis, *args, **kwargs)
      redis.evalsha @sha1, *args, **kwargs
    rescue ::Redis::CommandError => e
      if e.to_s =~ /^NOSCRIPT/
        redis.eval @script, *args, **kwargs
      else
        raise
      end
    end
  end
end
natashaselvidge@Natashas-MacBook-Pro discourse % d/rake db:migrate
Deprecation notice: enable_long_polling/long_polling_interval have switched from site settings to global settings. Remove the override from the Site Settings UI, and use a config file or environment variables to set the global settings. (removal in Discourse 2.9.0) 
At /usr/local/lib/ruby/gems/2.7.0/gems/bootsnap-1.10.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:48:in `load`
Pipelining commands on a Redis instance is deprecated and will be removed in Redis 5.0.0.

redis.multi do
  redis.get("key")
end

should be replaced by

redis.multi do |pipeline|
  pipeline.get("key")
end

(called from /src/lib/discourse_redis.rb:42:in `public_send'}
Pipelining commands on a Redis instance is deprecated and will be removed in Redis 5.0.0.

redis.multi do
  redis.get("key")
end

should be replaced by

redis.multi do |pipeline|
  pipeline.get("key")
end

(called from /src/lib/discourse_redis.rb:42:in `public_send'}
Pipelining commands on a Redis instance is deprecated and will be removed in Redis 5.0.0.

redis.multi do
  redis.get("key")
end

should be replaced by

redis.multi do |pipeline|
  pipeline.get("key")
end

(called from /src/lib/discourse_redis.rb:42:in `public_send'}
Pipelining commands on a Redis instance is deprecated and will be removed in Redis 5.0.0.

redis.multi do
  redis.get("key")
end

should be replaced by

redis.multi do |pipeline|
  pipeline.get("key")
end

(called from /src/lib/discourse_redis.rb:42:in `public_send'}
Pipelining commands on a Redis instance is deprecated and will be removed in Redis 5.0.0.

redis.multi do
  redis.get("key")
end

should be replaced by

redis.multi do |pipeline|
  pipeline.get("key")
end

(called from /src/lib/discourse_redis.rb:42:in `public_send'}
Pipelining commands on a Redis instance is deprecated and will be removed in Redis 5.0.0.

redis.multi do
  redis.get("key")
end

should be replaced by

redis.multi do |pipeline|
  pipeline.get("key")
end

(called from /src/lib/discourse_redis.rb:42:in `public_send'}
Pipelining commands on a Redis instance is deprecated and will be removed in Redis 5.0.0.

redis.multi do
  redis.get("key")
end

should be replaced by

redis.multi do |pipeline|
  pipeline.get("key")
end

(called from /src/lib/discourse_redis.rb:42:in `public_send'}
Pipelining commands on a Redis instance is deprecated and will be removed in Redis 5.0.0.

redis.multi do
  redis.get("key")
end

should be replaced by

redis.multi do |pipeline|
  pipeline.get("key")
end

(called from /src/lib/discourse_redis.rb:42:in `public_send'}
Pipelining commands on a Redis instance is deprecated and will be removed in Redis 5.0.0.

redis.multi do
  redis.get("key")
end

should be replaced by

redis.multi do |pipeline|
  pipeline.get("key")
end

(called from /src/lib/discourse_redis.rb:42:in `public_send'}
Pipelining commands on a Redis instance is deprecated and will be removed in Redis 5.0.0.

redis.multi do
  redis.get("key")
end

should be replaced by

redis.multi do |pipeline|
  pipeline.get("key")
end

(called from /src/lib/discourse_redis.rb:42:in `public_send'}
Ignoring /src/db/schema_cache.yml because it has expired. The current schema version is 20220124003259, but the one in the cache is 20211011123651.
Pipelining commands on a Redis instance is deprecated and will be removed in Redis 5.0.0.

redis.multi do
  redis.get("key")
end

should be replaced by

redis.multi do |pipeline|
  pipeline.get("key")
end

(called from /src/lib/discourse_redis.rb:42:in `public_send'}
Pipelining commands on a Redis instance is deprecated and will be removed in Redis 5.0.0.

redis.multi do
  redis.get("key")
end

should be replaced by

redis.multi do |pipeline|
  pipeline.get("key")
end

(called from /src/lib/discourse_redis.rb:42:in `public_send'}
rake aborted!
Redis::CommandError: ERR unknown command `synchronize`, with args beginning with:
/src/lib/distributed_mutex.rb:84:in `try_to_get_lock'
/src/lib/distributed_mutex.rb:61:in `get_lock'
/src/lib/distributed_mutex.rb:30:in `block in synchronize'
/src/lib/distributed_mutex.rb:29:in `synchronize'
/src/lib/distributed_mutex.rb:29:in `synchronize'
/src/lib/distributed_mutex.rb:14:in `synchronize'
/src/lib/tasks/db.rake:210:in `block in <main>'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
natashaselvidge@Natashas-MacBook-Pro discourse % 

Looks like you manually update the Redis gem on your dev environment from 4.5.1 to 4.6.0. Discourse doesn’t work with that gem version, so you need to revert back to the version we use on the Gemfile.lock file.

We are working on eventually moving to redis-rb 4.6.0, but that is a lot of work:

https://github.com/discourse/discourse/pull/15811

4 Likes

Ohhhh okay, thank you so much! I will try that :pray:t3:

1 Like

Update
For anyone who may need this in the future :hugs:
Thank you so much that fixed it! I updated my discourse, but the version wasn’t specified on the gem file. I added the version number to the end like this: gem ‘redis’, “~> 4.5.1”

We specify it at the Gemfile.lock:

1 Like

I think because I deleted my Gemfile lock and bundled. Then I was talking to the redis and sidekiq issues guys on Github and they were telling me I had to be on the updated version. Thanks again!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.