Sidekiq looks for redis on localhost instead of remote - ruby-on-rails

I have this in my sidekiq initializer:
Sidekiq.configure_server do |config|
config.redis = { url: "redis://#{ENV['REDIS_PORT_6379_TCP_ADDR']}:#{ENV['REDIS_PORT_6379_TCP_PORT']}/0", namespace: 'Tyresearch' }
end
When i boot sidekiq it starts fine on the correct host and port:
INFO: Booting Sidekiq 3.2.4 with redis options {:url=>"redis://172.17.0.6:6379/0", :namespace=>"Tyresearch"}
However when I try to launch a worker or visit the sidekiq admin panel I get this error:
Redis::CannotConnectError at /sidekiq
Error connecting to Redis on 127.0.0.1:6379 (ECONNREFUSED)
So, for some reason it now tries to connect on 127.0.0.1 instead of 172.17.0.6
Here is my env (the app is made of linked docker containers managed by vagrant)
{"ADMIN_EMAIL"=>"user#example.com",
"ADMIN_NAME"=>"First User",
"ADMIN_PASSWORD"=>"changeme",
"BUNDLE_BIN_PATH"=>
"/opt/rubies/ruby-2.1.2/lib/ruby/gems/2.1.0/gems/bundler-1.7.4/bin/bundle",
"BUNDLE_GEMFILE"=>"/var/www/Gemfile",
"COLUMNS"=>"135",
"GEM_HOME"=>"/var/bundle/ruby/2.1.0",
"GEM_PATH"=>"",
"GMAIL_PASSWORD"=>"Your_Password",
"GMAIL_USERNAME"=>"Your_Username",
"HOME"=>"/home/web",
"HOSTNAME"=>"223b7ef7396f",
"LESSCLOSE"=>"/usr/bin/lesspipe %s %s",
"LESSOPEN"=>"| /usr/bin/lesspipe %s",
"LINES"=>"43",
"LS_COLORS"=>
"rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=
01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:
*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=0
1;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.
flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:
*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:",
"NODE_PATH"=>"/usr/lib/nodejs:/usr/lib/node_modules:/usr/share/javascript",
"PATH"=>
"/var/bundle/ruby/2.1.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/rubies/ruby-2.1.2/bin",
"POSTGRES_ENV_PASSWORD"=>"password",
"POSTGRES_ENV_USERNAME"=>"postgres",
"POSTGRES_ENV_VERSION"=>"9.3",
"POSTGRES_NAME"=>"/tyresearch/postgres",
"POSTGRES_PORT"=>"tcp://172.17.0.5:5432",
"POSTGRES_PORT_5432_TCP"=>"tcp://172.17.0.5:5432",
"POSTGRES_PORT_5432_TCP_ADDR"=>"172.17.0.5",
"POSTGRES_PORT_5432_TCP_PORT"=>"5432",
"POSTGRES_PORT_5432_TCP_PROTO"=>"tcp",
"PWD"=>"/var/www",
"REDIS_NAME"=>"/tyresearch/redis",
"REDIS_PORT"=>"tcp://172.17.0.6:6379",
"REDIS_PORT_6379_TCP"=>"tcp://172.17.0.6:6379",
"REDIS_PORT_6379_TCP_ADDR"=>"172.17.0.6",
"REDIS_PORT_6379_TCP_PORT"=>"6379",
"REDIS_PORT_6379_TCP_PROTO"=>"tcp",
"ROLES"=>"[\"admin\", \"user\", \"VIP\"]",
"RUBYLIB"=>
"/opt/rubies/ruby-2.1.2/lib/ruby/gems/2.1.0/gems/bundler-1.7.4/lib",
"RUBYOPT"=>"-rbundler/setup",
"SELENIUM_ENV_CHROME_DRIVER_VERSION"=>"2.12",
"SELENIUM_ENV_DEBCONF_NONINTERACTIVE_SEEN"=>"true",
"SELENIUM_ENV_DEBIAN_FRONTEND"=>"noninteractive",
"SELENIUM_ENV_DISPLAY"=>":20.0",
"SELENIUM_ENV_LANG"=>"en_US.UTF-8",
"SELENIUM_ENV_LANGUAGE"=>"en_US.UTF-8",
"SELENIUM_ENV_SCREEN_DEPTH"=>"24",
"SELENIUM_ENV_SCREEN_HEIGHT"=>"1020",
"SELENIUM_ENV_SCREEN_WIDTH"=>"1360",
"SELENIUM_ENV_SELENIUM_PORT"=>"4444",
"SELENIUM_ENV_TZ"=>"\"US/Pacific\"",
"SELENIUM_NAME"=>"/tyresearch/selenium",
"SELENIUM_PORT"=>"tcp://172.17.0.7:4444",
"SELENIUM_PORT_4444_TCP"=>"tcp://172.17.0.7:4444",
"SELENIUM_PORT_4444_TCP_ADDR"=>"172.17.0.7",
"SELENIUM_PORT_4444_TCP_PORT"=>"4444",
"SELENIUM_PORT_4444_TCP_PROTO"=>"tcp",
"SELENIUM_PORT_5900_TCP"=>"tcp://172.17.0.7:5900",
"SELENIUM_PORT_5900_TCP_ADDR"=>"172.17.0.7",
"SELENIUM_PORT_5900_TCP_PORT"=>"5900",
"SELENIUM_PORT_5900_TCP_PROTO"=>"tcp",
"SHLVL"=>"1",
"TERM"=>"xterm",
"_"=>"/opt/rubies/ruby-2.1.2/bin/bundle",
"_FIGARO_ADMIN_EMAIL"=>"user#example.com",
"_FIGARO_ADMIN_NAME"=>"First User",
"_FIGARO_ADMIN_PASSWORD"=>"changeme",
"_FIGARO_GMAIL_PASSWORD"=>"Your_Password",
"_FIGARO_GMAIL_PASSWORD"=>"Your_Password",
"_FIGARO_GMAIL_USERNAME"=>"Your_Username",
"_FIGARO_ROLES"=>"[\"admin\", \"user\", \"VIP\"]",
"_ORIGINAL_GEM_PATH"=>""}

Ok, I missed to read the documentation carefully and didn't configure sidekiq clientside:
Sidekiq.configure_server do |config|
config.redis = { url: "redis://#{ENV['REDIS_PORT_6379_TCP_ADDR']}:#{ENV['REDIS_PORT_6379_TCP_PORT']}/0", namespace: 'Tyresearch' }
end
Sidekiq.configure_client do |config|
config.redis = { url: "redis://#{ENV['REDIS_PORT_6379_TCP_ADDR']}:#{ENV['REDIS_PORT_6379_TCP_PORT']}/0", namespace: 'Tyresearch' }
end

Related

Can't connect to clustered Azure Redis Cache with redis-rb gem and public access

We've provisioned an Azure Redis Cache server using the Premium tier. The server is clustered, with 2 shards, and the server is configured to allow public access over the public internet through a firewall--allow-listing a set of known IPs.
Deploys of our Rails application two any of these known IPs fail with the error:
Redis::CannotConnectError: Redis client could not connect to any cluster nodes
Here is our Rails config:
# application.rb
if Rails.env.test?
config.cache_store = :redis_cache_store, {
url: config.nines[:redis_url],
expires_in: 90.minutes,
namespace: ENV['TEST_ENV_NUMBER'],
}
else
config.cache_store = :redis_store, {
namespace:ENV['TEST_ENV_NUMBER'],
cluster: [ Rails.application.config.nines[:redis_url] ],
replica: true, # allow reads from replicas
compress: true,
compress_threshold: 1024,
expires_in: 90.minutes
}
end
The config.nines[:redis_url] is set like this: rediss://:<pw>#<cache-name>.redis.cache.windows.net:6380/0
Then, we initialize the Redis connection in code like this:
if Rails.env.test?
::Redis.new :url => redis_url, :db => ENV['REDIS_DB']
else
::Redis.new(cluster: [ "#{redis_url}" ], db: ENV['REDIS_DB'])
end
We're using the redis-rb gem and redis-rails gem.
If anyone can point out what we're doing wrong, please do share!
Thank you User Peter Pan - Stack Overflow. Posting your suggestion as answer to help other community members.
You can try below code:
# Import the redis library for Ruby
require "redis"
# Create a redis client instance for connecting Azure Redis Cache
# At here, for enabling SSL, set the `:ssl` symbol with the
# symbol value `:true`, see https://github.com/redis/redis-rb#ssltls-support
redis = Redis.new(
:host => '<azure redis cache name>.redis.cache.windows.net',
:port => 6380,
:db => <the db index you selected like 10>,
:password => "<access key>",
:ssl => :true)
# Then, set key `foo` with value `bar` and return `OK`
status = redis.set('foo', 'bar')
puts status # => OK
# Get the value of key `foo`
foo = redis.get('foo')
puts foo # => bar
Reference: How to setup Azure Redis cache with Rails - Stack Overflow

Rails adding extra line in my redis cache

Im using redis-rails in my project to store a cache of users, and I don't know why a extra line is added at begining of cache.
This is my config:
config.cache_store = :redis_store, {
host: ENV['REDIS_SERVER'] || 'localhost',
port: 6379,
db: 0,
namespace: ENV['CUSTOMER']
}
This is my code:
namespace :update_employees_cache do
desc "Update employees cache"
task update: :environment do
employees = []
Employee.where(active: true).each do |item|
employees.push({ id: item.id, name: item.name })
end
Rails.cache.write "employees", employees.to_json
end
end
This is the result
At line 1, o: ActiveSupport::Cache::Entry:#valueI"�
What is this?
After open a issue in the project repo I discovered that is the default behavior of rails wrapping the cache with that data.
In my case I need to avoid it, then is needed set row as true in configs.
config.cache_store = :redis_store, {
host: ENV['REDIS_SERVER'] || 'localhost',
port: 6379,
db: 0,
namespace: ENV['CUSTOMER'],
raw: true
}

Rails 4.2.3 Test my applications REST response

I m building an app which reacts to http requests.
So far it was ok to check the log file and the tables. I used curl to send the request like:
curl -u test -X POST http://127.0.0.1:3000/api/information -d ''
But now i included some kind of response mechanism. My question now is what port do i have to use for my responses?
Is it port 80 (std http port) ? And are there some CLI tools available which allow to handle a session?
The port depends on your config and which arguments you use when starting the server. By default rails start on port 3000 - using port 80 will in most cases require the use of sudo. You can see the port in the output when starting the rails server.
$ rails server
=> Booting WEBrick
=> Rails 4.2.1 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
There are several browser extensions such as Postman which provide a GUI for sending REST requests - in the way that is much easier than trying to piece it all together in a monster cURL invocation.
This is useful for debugging - but manually testing your applications is very error-prone and known to be an incomplete and flawed approach*. Instead, you should consider using automated tests.
Example of an RSpec request spec:
# spec/requests/pets_api_spec.rb
require "rails_helper"
RSpec.describe "Pets API", type: :request do
subject { response }
let(:json) { JSON.parse(response.body, symbolize_keys: true) }
let(:pet) { Pet.create(name: 'Spot') }
describe "viewing a Pet" do
before { get pet_path(pet) }
it { should have_http_status :ok }
it "has the correct JSON response" do
expect(json[:type]).to eq 'Pet'
expect(json[:data][:name]).to eq 'Spot'
end
end
describe "creating a Pet" do
let(:valid_session) do
# setup session here.
end
before do
post "/pets", { type: 'Pet', data: { name: 'Doge' } }, valid_session
end
it { should have_http_status :created }
# ...
end
end

Using multiple sidekiq databases

Hey I am attempting to spawn a sidekiq worker that connects to a completely separate Redis database. I know with 3.0's connection pooling this is possible, and I have been able to successfully push a job onto the correct Redis DB, but the problem is the Sidekiq web UI is not showing these jobs in the queue (I have mounted a separate Rack app for this that points exclusively to the other Redis DB). The "Busy" tab in the admin interface also shows my sidekiq workers that I have pointed at this DB, with correct PIDs.
Here's my sidekiq.rb:
Sidekiq.configure_server do |config|
if ENV['REDIS_DB'] == "2"
config.redis = { :url => "redis://#{SIDEKIQ_HOST}:6379/2", :namespace => 'drip' }
else
config.redis = { :url => "redis://#{SIDEKIQ_HOST}:6379", :namespace => 'drip' }
end
end
Sidekiq.configure_client do |config|
if ENV['REDIS_DB'] == "2"
config.redis = { :url => "redis://#{SIDEKIQ_HOST}:6379/2", :namespace => 'drip' }
else
config.redis = { :url => "redis://#{SIDEKIQ_HOST}:6379", :namespace => 'drip' }
end
end
My use case is that I need to have fine grain control over the jobs that go into the second database, so I need the workers configured precisely so they are only using as many resources as I need them to. I only want the workers that are configured in this way to pick up these jobs.
The Web UI cannot be mounted multiple times to point to multiple Redises in a single process. You have to run multiple web processes with REDIS_DB set too.

configure multiple server to support sidekiq

I planned to migrate redis server to a new one with sidekiq running, but doesn't want to stop the current application running. And I don't want to use redis cluster which is still alpha version.
My thought is to ask sidekiq to write to new redis server, but pulls from both of them, so that once the workers in old redis are completed, the new one can totally take over all workers. I think this solution is feasible, but I have no idea how to make it happen.
This is my sidekiq.rb:
sidkiq_config = YAML.load(ERB.new(Rails.root.join('config/redis.yml').read).result)
Sidekiq.configure_server do |config|
config.logger.level = Logger::ERROR
config.redis = { :url => "redis://redis2.staging:6379", :namespace => "app_#{Rails.env}:sidekiq" }
config.redis = { :url => "redis://redis.staging:6379", :namespace => "app_#{Rails.env}:sidekiq" }
end
Sidekiq.configure_client do |config|
config.logger.level = Logger::ERROR
config.redis = { :url => "redis://redis2.staging:6379", :namespace => "app_#{Rails.env}:sidekiq" }
end
I believe the easiest solution is to run two instances of sidekiq - one that reads from the old cluster, and one that reads from the new cluster
sidkiq_config = YAML.load(ERB.new(Rails.root.join('config/redis.yml').read).result)
Sidekiq.configure_server do |config|
config.logger.level = Logger::ERROR
if ENV['read_from_new']
config.redis = { :url => "redis://redis2.staging:6379", :namespace => "app_#{Rails.env}:sidekiq" }
else
config.redis = { :url => "redis://redis.staging:6379", :namespace => "app_#{Rails.env}:sidekiq" }
end
end
Sidekiq.configure_client do |config|
config.logger.level = Logger::ERROR
config.redis = { :url => "redis://redis2.staging:6379", :namespace => "app_#{Rails.env}:sidekiq" }
end
You can update to a recent version of sidekiq and use Sharding.
REDIS_A = ConnectionPool.new { Redis.new(...) }
REDIS_B = ConnectionPool.new { Redis.new(...) }
# To create a new connection pool for a namespaced Sidekiq worker:
ConnectionPool.new do
client = Redis.new(:url => "Your Redis Url")
Redis::Namespace.new("Your Namespace", :redis => client)
end
# Create a job in the default redis instance
SomeWorker.perform_async
# Push a job to REDIS_A using the low-level Client API
client = Sidekiq::Client.new(REDIS_A)
client.push(...)
client.push_bulk(...)
Sidekiq::Client.via(REDIS_B) do
# All jobs defined within this block will go to B
SomeWorker.perform_async
end
To quite sidekiq, click the quite button in the UI

Resources