Error while connecting to a remote solr instance from Sunspot - ruby-on-rails

I am using Sunspot rails(1.1.0). Everything works when I run my Rails
application and the Solr server on the same machine. When I run Solr
server on a different machine, I get the following error:
Errno::ECONNREFUSED: Connection refused - Connection refused
from /opt/tibco/jruby-1.4.0RC1/lib/ruby/1.8/net/http.rb:560:in `initialize'
from /opt/tibco/jruby-1.4.0RC1/lib/ruby/1.8/net/http.rb:560:in `new'
from /opt/tibco/jruby-1.4.0RC1/lib/ruby/1.8/net/http.rb:560:in `open'
After debugging through Sunspot code, I realized that the Solr::Client is connecting to localhost rather than the remote host configured in sunspot.yml. My sunspot.yml file is as follows:
production:
solr:
hostname: kingkong
port: 8983
log_level: WARNING
The build_session method(sunspot_rails-1.1.0/lib/rails.rb:line 24) tries to establish a slave session. The slave_config method ignores the configuration provided in sunspot.yml file. Here is the slave_config method:
def slave_config(sunspot_rails_configuration)
config = Sunspot::Configuration.build
config.solr.url = URI::HTTP.build(
:host => configuration.hostname,
:port => configuration.port,
:path => configuration.path
).to_s
config
end
Is this the intended behavior? Also, has anybody successfully connected to Solr running remotely?
Note:
I was able to work around this issue by monkey patching the
Sunspot::Rails.slave_config method. I added file called sunspot.rb in
configurations/initializers directory.
module Sunspot::Rails
def slave_config(sunspot_rails_configuration)
config = Sunspot::Configuration.build
config.solr.url = URI::HTTP.build(
:host => sunspot_rails_configuration.hostname,
:port => sunspot_rails_configuration.port,
:path => sunspot_rails_configuration.path
).to_s
config
end
end
Sunspot.session = Sunspot::Rails.build_session
I am not sure if this is the correct approach. Please let me know if I am missing something basic.

Related

How to avoid a 500 Internal Server Error when using the Rails ActionMailer on Heroku

I am trying to send an email to a user upon sign up in my web app, which is built with Rails in the back end and React-Redux on the front end. I used a gem called letter_opener when testing on a local server, and everything seemed to work fine. When I tried it live on Heroku, I got back a 500 error, and I'm not sure what is wrong.
I tried reading the ActionMailer docs, but it didn't seem to mention any issue like this.
The method in the UserMailer:
def welcome_email(user)
#user = user
mail(to: #user.email, subject: "Welcome")
end
Relevant code in UsersController:
def create
# ...
email = UserMailer.welcome_email(#user)
email.deliver_now # This line throws the error
# ...
end
The error from the Heroku logs:
Errno::ECONNREFUSED (Connection refused - connect(2) for "localhost" port 25):
I expected to the email to be delivered, or at least to have a more informative error message. I am not sure why Rails is looking at localhost's port 25.
I am not sure why Rails is looking at localhost's port 25.
ActionMailer defaults to localhost:25, and you probably only changed your development configuration.
Errno::ECONNREFUSED (Connection refused - connect(2) for "localhost" port 25)
Heroku doesn't provide an SMTP server, and there certainly won't be one on localhost. Use an email addon or some other third-party mail service of your choice.
You'll probably have to modify config/environments/production.rb to use whatever mail service you choose.
Chris is right, Heroku doesn't provide an SMTP server and you've to use an Addon. I'll further add on how you can proceed with using sendgrid addon which is free upto much extent.
First, goto your Heroku app -> Enable sendgrid addon. Then you'll be given sendgrid credentials. Keep them safe.
In your config/environments/production.rb add:
config.action_mailer.delivery_method = :smtp
config.action_mailer.default_url_options = { host: "your-domain.com", protocol: 'https' }
Then in your config/environment.rb file add:
...
# Initialize the Rails application.
Rails.application.initialize!
# Add sendgrid support
if Rails.env.production?
ActionMailer::Base.smtp_settings = {
:user_name => "sendgrid_username",
:password => "sendgrid_password",
:domain => "your-domain.com",
:address => "sendgrid_hostname",
:port => 3000, # sendgrid_port
:authentication => :plain,
:enable_starttls_auto => true
}
end
Change the credentials above as required. Also consider using ENV variables for above credentials.

Setting up Redis To Go with Heroku and Rails 4.0.0

I am attempting to setup Redis To Go on my Rails 4 app. I want to be able to deploy it to Heroku as well.
So far, this is what I've done:
Through the dashboard.heroku site, I used the one click install for the Nano version of Redis To Go to install the addon to my app.
I added gem 'redis' to my gemfile.
In config/environments/development.rb I added this line:
ENV["REDISTOGO_URL"] = 'redis://redistogo:b9fc604b1c86a1f6c232ce1dd16cd989#albacore.redistogo.com:10280/'
Then, I created a config/initializers/redis.rb file which looks like this:
uri = URI.parse(ENV["redis://redistogo:b9fc604b1c86a1f6d872ce1dd16cd989#albacore.redistogo.com:10280/"] || "redis://localhost:6379/")
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
When running a Redis command in my console now, I get this error:
Redis::CannotConnectError: Error connecting to Redis on 127.0.0.1:6379 (ECONNREFUSED)
What am I doing wrong here, and what do I need to do to ensure that I can test in development and deploy to Heroku without any issues?
ENV["REDISTOGO_URL"] should be in the environment on Heroku. I'd remove it from config/environments/development.rb altogether and change the redis.rb initializer to:
uri = URI.parse(ENV.fetch("REDISTOGO_URL", "redis://localhost:6379/"))
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
As long as that ENV var isn't set in development, it'll fall back to the local redis installation.
To update brandonhilkert's answer for Rails 4:
uri = ENV["REDISTOGO_URL"] || "redis://localhost:6379/"
REDIS = Redis.new(:url => uri)
Also, you might want to use Redis.current instead of setting a REDIS variable (see here).
For Rails 4 I did the following
In the console:
heroku addons:create redistogo
heroku config:set REDIS_PROVIDER=REDISTOGO_URL
In my Procfile I added:
worker: bundle exec sidekiq
In my 'gemfile.rb' I added:
gem 'redis'
I added the following file, config/initializers/redis.rb:
uri = ENV["REDISTOGO_URL"] || "redis://localhost:6379/"
REDIS = Redis.new(:url => uri)

Is it possible to directly connect to a Heroku database from localhost?

If I have a DATABASE_URL, is it possible to connect to it from localhost? I'm using the following code:
db = URI.parse(database_url)
connection = ActiveRecord::Base.establish_connection(
:adapter => db.scheme == 'postgres' ? 'postgresql' : db.scheme,
:host => db.host,
:username => db.user,
:password => db.password,
:database => db.path[1..-1],
:encoding => 'utf8'
)
When running the code from my pc, I keep getting errors like:
could not connect to server: Connection timed out
Is the server running on host some_host.amazonaws.com and accepting
TCP/IP connections on port 5432?
I'm using the same code to share a database between two apps that are running on Heroku and it works. This leads me to believe that connecting to a Heroku database is restricted unless you perform it from a Heroku host. Is that true?
Indeed SSL is required for outside connections. The underlying postgres adapter can be forced to use SSL with the sslmode=require parameter. You can pass arbitrary parameters down from the ActiveRecord connection options, like so:
ActiveRecord::Base.establish_connection(
adapter: 'postgresql',
host: 'host',
username: 'user',
password: 'pass',
database: 'database_name',
encoding: 'utf-8',
port: '5432', # could be a non-standard port
sslmode: 'require' # force SSL
)
I've verified this locally, and here's a full session showing it work. Please make sure you're not mistyping anything:
heroku pg:credentials yellow -a my-app Connection info string:
"dbname=ddbolrs4g89dsi host=ec2-23-21-91-108.compute-1.amazonaws.com port=5432 user=itkdrxzjmwcjtw password=wU-4tT3YbF8AZ3U5kwu-2KYPEX ssl
mode=require"
$ irb
> require 'active_record'
=> true
> ActiveRecord::Base.establish_connection(adapter: 'postgresql', database: 'ddbolrs4g89dsi', host: 'ec2-23-21-91-108.compute-1.amazonaws.com', username: 'itkdrxzjmwcjtw', password: 'wU-4tT3YbF8AZ3U5kwu-2KYPEX', sslmodel: 'require')
=> #<ActiveRecord::ConnectionAdapters::ConnectionPool:0x007f7f9ba6f0f0 #mon_owner=nil, #mon_count=0, #mon_mutex=#<Mutex:0x007f7f9ba6f078>, #spec=#<ActiveRecord::Base::ConnectionSpecification:0x007f7f9ba64150 #config={:adapter=>"postgresql", :database=>"ddbolrs4g89dsi", :host=>"ec2-23-21-91-108.compute-1.amazonaws.com", :username=>"itkdrxzjmwcjtw", :password=>"wU-4tT3YbF8AZ3U5kwu-2KYPEX", :sslmodel=>"require"}, #adapter_method="postgresql_connection">, #reserved_connections={}, #queue=#<MonitorMixin::ConditionVariable:0x007f7f9ba6f000 #monitor=#<ActiveRecord::ConnectionAdapters::ConnectionPool:0x007f7f9ba6f0f0 ...>, #cond=#<ConditionVariable:0x007f7f9ba6efd8 #waiters=[], #waiters_mutex=#<Mutex:0x007f7f9ba6ef88>>>, #timeout=5, #size=5, #connections=[], #automatic_reconnect=true>
> ActiveRecord::Base.connection.execute("SELECT version()").first
=> {"version"=>"PostgreSQL 9.1.4 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3, 64-bit"}
> exit
$ # remove db, leaked creds ^
$ heroku addons:remove HEROKU_POSTGRESQL_YELLOW -a my-app --confirm my-app
Removing HEROKU_POSTGRESQL_YELLOW on my-app... done, v490 (free)
Outside connection to the postgresql server require SSL on Heroku. Have a look at the docs as well.

deploying redis to heroku unable to connect

ive been trying to get resque to work with heroku. i can successfully get it to work in development mode, however when i try pushing to heroku i get
Errno::ECONNREFUSED (Connection refused - Unable to connect to Redis on 127.0.0.1:6379):
i then read and followed http://blog.redistogo.com/2010/07/26/resque-with-redis-to-go/
i put the configurations listed in the site but got the following error
SocketError (getaddrinfo: nodename nor servname provided, or not known):
i put in my initializers/resque.rb
Resque.after_fork = Proc.new { ActiveRecord::Base.establish_connection }
ENV["redis://redistogo:11111111111111111#lab.redistogo.com:9254/"] ||= "redis://heroku_username:heroku_password#host:9254/"
uri = URI.parse(ENV["redis://redistogo:1111111111111111#lab.redistogo.com:9254/"])
Resque.redis = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
however it throws the error mentioned above. on my dev mode now, i get the error as well.
i tried using my heroku username (im using the add on from heroku), putting my password to heroku, and changing the port to 9254. however i keep getting the socket error now. what am i doing wrong?
help would be much appreciated. thank you
UPDATE.
#kevin
i tried
uri = URI.parse(ENV["my_url_string"] || "redis://localhost:9254/" )
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
in a initializer/redis.rb as well but i get the following error
Errno::ECONNREFUSED (Connection refused - Unable to connect to Redis on 127.0.0.1:6379):
are the numbers in the error, ie 127.0.0.1:6379 significant? ive checked my redis gui app and also from heroku config that my port number is 9254
REDISTOGO_URL => redis://redistogo:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx#lab.redistogo.com:9254/
did you have any other configuration settings? thanks for helping!
FINAL UPDATE.
i fixed it. i can't believe it! my complete solution is
uri = URI.parse(ENV["REDISTOGO_URL"])
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
Resque.redis = REDIS
verbatim. it works without explicitly setting the url because i guess heroku tries to set it up for me already
For my setup I have /config/initializers/redis.rb with these lines:
uri = URI.parse(ENV["REDISTOGO_URL"] || "redis://localhost:6379/" )
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
My REDISTOGO_URL is defined in my heroku configuration. You should be able to validate that by typing:
heroku config --app my_app
You'll see in the output the value for REDISTOGO_URL
You should copy your REDISTOGO_URL directly from Redis To Go. You find it in by going to the instance in heroku and clicking on Add Ons -> Redis To Go.
Here are a couple pointers:
Verify you have your REDIS_TO_GO URL in your heroku config from the command line like I've demonstrated above.
Verify the REDIS_TO_GO URL is identical to the one assigned to that instance in the Add Ons -> Redis To Go config.
i fixed it. i can't believe it! my complete solution is
uri = URI.parse(ENV["REDISTOGO_URL"])
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
Resque.redis = REDIS
verbatim. it works without explicitly setting the url because i guess heroku tries to set it up for me already
I got the same thing, so, basically Sidekiq was not grabbing the REDISCLOUD_URL from vars, it was grabbing REDIS_PROVIDER.
heroku config:set REDIS_PROVIDER=REDISCLOUD_URL
It worked like a charm.

Database.yml configuration options

I would like to know where I can read about valid configuration options for database.yml for ActiveRecord. I know the basic ones like adapter, database, username, password, etc., but I would like to have the full list for each adapter. Where would I find that?
I found a gist of database.yml examples using mysql, postgres, and sqlite3, and the Rails 3.2 source code for connection adapters provides good insight as well.
Looks to me that the following are the most widely used options:
adapter
encoding
database
pool
username
password
socket
host
port
timeout
The Rails 3.2 connection_specification.rb file looks like it simply merges any options you include, so I'd say what options you include are dependant on the database adapter you choose to use (lines 58-74):
def connection_url_to_hash(url) # :nodoc:
config = URI.parse url
adapter = config.scheme
adapter = "postgresql" if adapter == "postgres"
spec = { :adapter => adapter,
:username => config.user,
:password => config.password,
:port => config.port,
:database => config.path.sub(%r{^/},""),
:host => config.host }
spec.reject!{ |_,value| !value }
if config.query
options = Hash[config.query.split("&").map{ |pair| pair.split("=") }].symbolize_keys
spec.merge!(options)
end
spec
end

Resources