def eval(keys: [], argv: [])
      keys = [keys] unless keys.is_a?(Array)
      argv = [argv] unless argv.is_a?(Array)
      argv = normalize(argv)

      @connection.evalsha(self.sha1, keys, argv)
    rescue Redis::CommandError => err
      raise unless ERROR_MESSAGE_PATTERN.match?(err.message)
      @connection.eval(@script, keys, argv)
    end
def eval(keys: [], argv: [])
      keys = [keys] unless keys.is_a?(Array)
      argv = [argv] unless argv.is_a?(Array)
      argv = normalize(argv)

      @connection.evalsha(self.sha1, keys, argv)
    rescue Redis::CommandError => err
      raise unless ERROR_MESSAGE_PATTERN.match?(err.message)
      @connection.eval(@script, keys, argv)
    end
Evaluates the script using the given keys and argv arrays, and returns the unparsed result. Caller is in charge
 of interpreting the result.
 NOTE: To minimize the number of redis commands, this always first assumes that the script was already loaded using
 its sha1 representation, and tells redis to execute the script cached by `sha1`. If it receives as error that the
 script does not exist, only then will it send the source to be executed. So in the worst case you get 2 redis
 commands, but in the average case you get 1, and it's much faster as redis does not have to reparse the script,
 and we don't need to send the lua source every time.
 @param [Array<String>] keys the KEYS array as described in the Redis doc for eval
 @param [Array<String>] argv the ARGV array as described in the Redis doc for eval
 @return [nil, Boolean, String, Numeric] returns whatever redis returns