Redis::TimeoutError in Rails application - ruby

I keep getting Redis::Timeout error in my application (both in UI and in background jobs). I am using AWS ElastiCache service for Redis.
This is how I create a Redis connection. In my config/application.rb , I have:
$redis = Redis.new(host: REDIS_HOST, port: REDIS_PORT, db: REDIS_DB)
How can I avoid getting timeout errors? I am using the default connection settings as follows:
> $redis.client.options[:reconnect_attempts]
=> 1
> $redis.client.options[:timeout]
=> 5.0
> $redis.client.options[:tcp_keepalive]
=> 0
> $redis.client.options[:inherit_socket]
=> false

You should pool your Redis connections with the help of the Connection Pool Gem and increase the timeout value if the problem persists:
ConnectionPool.new(size: 5, timeout: 3) {Redis.new({:host => 'localhost', :port => 6379, :db => 1, :timeout => 240})}
Redis Gem

Related

Ruby Datamapper connection with SSL to MariaDB on Amazon RDS

How do I establish a ruby Datamapper connection to MariaDB on Amazon RDS with SSL?
Here's what I did:
A non-SSL connection works when testing with:
uri = 'mysql://user:pass#host:port/db_name'
connection = DataObjects::Connection.new(uri)
=> #<DataObjects::Mysql::Connection:0x000056179a3a5921
connection.secure?
=> false
According to the MySQL datamapper wiki, an ssl connection requires the following options: :ssl_ca, :client_key, and :client_cert.
This would result in the following code:
uri = 'mysql://user:pass#host:port/db_name?'
ssl_opts = 'ssl[ssl_ca]=file&ssl[client_key]=file&ssl[client_cert]=file'
connection = DataObjects::Connection.new(uri + ssl_opts)
connection.secure?
=> false
However the only files get is the RDS combind CA bundle, refered from the RDS docs
I do not have a client_cert at all.
Connecting with the mysql client on cli works with SSL:
mysql --ssl -h host -u user -p pass db_name
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 1638
Server version: 10.1.26-MariaDB MariaDB Server
In doc
https://github.com/datamapper/do/wiki/MySQL
It also says
as tested only ca_cert was required to connect to RDS.
So try adding only ca_cert path and do a test
There's only one parameter required: :ssl => {:ca_cert => 'pem_file'}.
However it looks like using uri string for configuration does not work. The reason is a limitation in Addressable::Uri. It cannot handle query strings which aim to represent hashes with more than 1 level.
The good news is that it works using DataMapper.setup with a config Hash:
DataMapper.setup(:default,
:adapter => 'mysql',
:user => 'user',
:database => 'db_name',
:host => 'host',
:password => 'pass',
:ssl => {
:ca_cert => '/path/to/rds-combined-ca-bundle.pem'
}
)

Get Postgres-activerecord setup to work both locally and in Heroku

I'm automating DB creation (with a Rakefile in a Sinatra App).
I would like to be able to run the rakefile from my Linux user "pete" (eg pete#pete_laptop: /path $ rake db:create) AND from Heroku.
It comes down to the settings in my config/database.rb:
ActiveRecord::Base.establish_connection(
:adapter => db.scheme == 'postgres' ? 'postgresql' : db.scheme,
:host => db.host,
:port => db.port,
# pete#ubuntu_14.04_laptop--------
# :username => 'pete',
# :password => 'password',
# OR
# heroku -----------------
# :username => db.user,
# :password => db.password,
:database => DB_NAME,
:encoding => 'utf8'
)
If I use the pete#ubuntu_laptop settings, the database works in localhost but not in Heroku,
If I use the heroku settings, the database works in localhost but not in Heroku.
How can I setup this file/my ubuntu laptop so that the app works both on localhost & in Heroku?
Cheers,
Pete
You can use environment variables which can be accessed like ENV["PG_USER"] in Ruby. If you want to use it in a yml file you can put it in erb tags <%= ENV["PG_USER"] %> and render it with erb before passing it to your config.
You can set environment variables in your .bashrc or you can use something like the dotenv gem. On heroku you can set environment variables like heroku config:set PG_USER=postgres.
But check whether this is really necessary for heroku. In Rails, for instance, heroku provides a database configuration, so there is no need to configure it.
oK! With help got it working!
used:
ActiveRecord::Base.establish_connection(
:adapter => db.scheme == 'postgres' ? 'postgresql' : db.scheme,
:host => db.host,
:port => db.port,
:username => ENV['PG_USER'] || db.user,
:password => ENV['PG_PASSWORD'] || db.password,
:database => DB_NAME,
:encoding => 'utf8'
)
AND
added this to my shell-rc (in my case ~/.zshrc)
export PG_USER='pete'
export PG_PASSWORD='password'
now in my local environment the username & password pick up the ENV['PG...] variables from the terminal I launch the app in.
Note: 'export' is important - without it the variables don't get sent to the app's 'ENV'

Rabbitmq queuing system not being consumed using fanout

ive been trying to fanout those queues using a ruby consumer very simple it just subscribes to that exchange/queues and it receives the message. now the problem whenever a new message is published. they dont receive the message which means they are not consuming and no consumers are listed. once you rebind the queue with the exchange again and restart the ruby app it starts to consume again. then it goes back to lembo again! sometimes when you restart the ruby app for few times it works. any idea?
code used for the consumer below:
#!/usr/bin/env ruby
# encoding: utf-8
require "rubygems"
require "amqp"
EventMachine.run do
connection = AMQP.connect(:host => '127.0.0.1', :port => 5672, :user => "user",:pass => "pass",:vhost => "/",:ssl => false,:frame_max => 131072 )
puts "Connected to AMQP broker. Running #{AMQP::VERSION} version of the gem..."
channel = AMQP::Channel.new(connection)
exchange = channel.fanout("p_cmds.p1")
channel.queue("p1_queue").bind(exchange).subscribe do |payload|
puts "#{payload} => p1"
end
end

Redis session store on heroku

I am attempting to use redis store as my session store on heroku. It works fine in development but I am unable to get a redis connection on heroku. It is attempting to connect to a 127.0.0.1 instead of the correct redis server.
Error:
ActionView::Template::Error (Error connecting to Redis on 127.0.0.1:6379 (ECONNREFUSED)):
I have set the heroku redis config to the correct server (not really using for the session store but it is set)
REDISTOGO_URL: redis://redistogo:#################################carp.redistogo.com:9274/
session_store.rb
GrnAuth::Application.config.session_store :redis_store, :server => APP_CONFIG['redis_server'], key: '_grn_session'
environment.rb
# Load the rails application
require File.expand_path('../application', __FILE__)
require 'yaml'
APP_CONFIG = YAML.load_file("#{Rails.root}/config/config.yml")[Rails.env]
# Initialize the rails application
GrnAuth::Application.initialize!
config.yml
development:
redis_server: redis://localhost:6379/
test:
redis_server: redis://localhost:6379/
production:
redis_server: redis://redistogo:#################################carp.redistogo.com:9274/
When I console in to heroku I can check APP_CONFIG['redis_server'] and it is set to the redis server.
I have also set up a redis connection just to use that works.
redis.rb
uri = URI.parse(ENV["REDISTOGO_URL"] || "redis://localhost:6379/" )
$redis = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
When I console in to heroku I can do and get the following
irb(main):001:0> $redis
=> #<Redis client v3.0.1 for redis://carp.redistogo.com:9274/0>
Any help would be much appreciated. Thank you.
It looks like this:
GrnAuth::Application.config.session_store :redis_store, :server => APP_CONFIG['redis_server'], key: '_grn_session'
Should instead be this:
GrnAuth::Application.config.session_store :redis_store, :servers => APP_CONFIG['redis_server'], key: '_grn_session'

Is there any way to get resque-web to work with Redis To Go hosted redis instance?

Is there any way to get resque-web to work with a Redis To Go hosted redis instance?
UPDATE:
#Nemo157's suggestion was correct. Ended up creating a test-evn.rb containing:
uri = URI.parse(" redis://XXXX#catfish.redistogo.com:9122")
Resque.redis = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
Pass it the config file you're using to setup redis in the app, e.g.
resque-web ./environment.rb
where environment.rb contains something like:
Resque.redis = Redis.new(:host => "path.to.host", :port => 6379)
Note: I haven't tested this since all my redis instances have been on localhost, but that's my understanding of how it works.

Resources