rails i18n redis ERR unknown command [] railscast 256 - ruby-on-rails

Following this RailsCast : http://railscasts.com/episodes/256-i18n-backends but using Rails 5.2, I raise this error :
Redis::CommandError in Pages#home<br>
ERR unknown command '[]'
In config/initializers/i18n_backend.rb
TRANSLATION_STORE = Redis.new seems causing this problem.
Whereas TRANSLATION_STORE = {} works like a charm.
But without Redis!
Any hint?

The problem is defined here:
https://github.com/ruby-i18n/i18n/blob/master/lib/i18n/backend/key_value.rb#L25-L30
I haven't investigated redis 4 but it seems that these methods has been removed.
The solution is to patch the Redis gem and add these methods to the redis.
# config/initializers/redis.rb
class RedisHash
def initialize(redis)
#redis = redis
end
def [](key)
#redis.get(key)
end
def []=(key, value)
#redis.set(key, value)
end
end
Redis.current = Redis.new(host: 127.0.0.1,
port: 6379,
db: 0,
thread_safe: true)
# config/initializers/i18n.rb
I18n::Backend::KeyValue.new(RedisHash.new(Redis.current))
This code above is sample initializer. It works with the newest version of redis 4.3.5
I've tested also redis-store/redis-i18n and it also works with the newest redis versions but in my opinion this implementation enforces huge overload on redis.
EDIT:
Due to the redis contributors [answer][1]
[1]: https://github.com/redis/redis-rb/issues/997#issuecomment-871302883 I've updated my solution

Not a full answer I know, but I had a similar problem after upgrading redis gem from 3.3.1 to 4.0.2
I set it back to 3.3.1 and it got fixed. Odd thing for me was that the problem only occurred in the production environment.
I am using a chained backend
I18n.backend= I18n::Backend::Chain.new(
I18n::Backend::KeyValue.new(Redis.current),
I18n.backend
)

Related

PG::UnableToSend: no connection to the server in Rails

I have a production server running ubuntu 14.04, Rails 4.2.0, postgresql 9.6.1 with gem pg 0.21.0/0.20.0. In last few days, there is constantly error with accessing to a table customer_input_datax_records in psql server.
D, [2017-07-20T18:08:39.166897 #1244] DEBUG -- : CustomerInputDatax::Record Load (0.1ms) SELECT "customer_input_datax_records".* FROM "customer_input_datax_records" WHERE ("customer_input_datax_records"."status" != $1) [["status", "email_sent"]]
E, [2017-07-20T18:08:39.166990 #1244] ERROR -- : PG::UnableToSend: no connection to the server
: SELECT "customer_input_datax_records".* FROM "customer_input_datax_records" WHERE ("customer_input_datax_records"."status" != $1)
The code which call to access the db server is with Rufus scheduler 3.4.2 loop:
s = Rufus::Scheduler.singleton
s.every '2m' do
new_signups = CustomerInputDatax::Record.where.not(:status => 'email_sent').all
.......
end
After restart the server, usually there is with first request (or a few). But after some time (ex, 1 or 2 hours), the issue starts to show up. But the app seems running fine (accessing records with read/write & creating new). There are some online posts about the error. However the problem seems not the one I am having. Before I re-install the psql server, I would like to get some ideas about what causes the no connection.
UPDATE: database.yml
production:
adapter: postgresql
encoding: unicode
host: localhost
database: wb_production
pool: 5
username: postgres
password: xxxxxxx
So, the error is "RAILS: PG::UnableToSend: no connection to the server".
That reminds me of Connection pool issue with ActiveRecord objects in rufus-scheduler
You could do
s = Rufus::Scheduler.singleton
s.every '2m' do
ActiveRecord::Base.connection_pool.with_connection do
new_signups = CustomerInputDatax::Record
.where.not(status: 'email_sent')
.all
# ...
end
end
digging
It would be great to know more about the problem.
I'd suggest trying this code:
s = Rufus::Scheduler.singleton
def s.on_error(job, error)
Rails.logger.error(
"err#{error.object_id} rufus-scheduler intercepted #{error.inspect}" +
" in job #{job.inspect}")
error.backtrace.each_with_index do |line, i|
Rails.logger.error(
"err#{error.object_id} #{i}: #{line}")
end
end
s.every '2m' do
new_signups = CustomerInputDatax::Record.where.not(:status => 'email_sent').all
# .......
end
As soon as the problem manifests itself, I'd look for the on_error full output in the Rails log.
This on_error comes from https://github.com/jmettraux/rufus-scheduler#rufusscheduleron_errorjob-error
As we discuss in the comments, the problem seems related to your rufus version.
I would suggest you to check out whenever gem and to invoke a rake task instead of calling directly the activerecord model.
It could be a good idea, however, to open an issue with the traceback of your error in the rufus-scheduler repo on github (just to let then know...)

Running API/gem on heroku gives Load error

I use the payment provider Mollie in my Ruby on Rails app. It works locally but not on heroku. When I call the API, it gives the error: 500: Load error: cannot load such file -- Mollie/Api/Client. Does someone know how to load the API on heroku? Update: I think that it has something to do with the location where heroku saves the gems. And that it can't find the location of the gem (??)
I installed the gem locally by running
$ gem install mollie-api-ruby
I also added the gem to my gemfile (but don't know if this is necessary).
gem 'mollie-api-ruby'
I am not experienced in Ruby on Rails and Heroku, but I hope that someone has a tip to get this working. Thanks!
I request this API in a controller by:
def create
#thrill = Thrill.find(params[:thrill_id])
if #thrill.reservations.length < #thrill.training.tr_max_attendants
#reservation = current_user.reservations.create(reservation_params)
if #reservation
require 'Mollie/API/Client'
mollie = Mollie::API::Client.new('test_gUejkz43UkdeCauC22J6UNq')
payment = mollie.payments.create(
amount: #reservation.thrill.training.tr_price,
description: #reservation.thrill.training.tr_name,
redirect_Url: 'http://8a3a73cb.ngrok.io/your_trips',
webhookUrl: 'http://8a3a73cb.ngrok.io/notify',
metadata: {
reservationid: #reservation.id
}
)
#reservation.update_attributes payid:payment.id
redirect_to payment.payment_url
else
redirect_to #thrill.training, notice: "Helaas, de training is vol"
end
end
end
Ok, found the answer. It had to be lowercase : require 'mollie/api/client'

Faraday::SSLError for Elasticsearch

Currently running into an issue where my background workers which are communicating with elasticsearch via elasticsearch-client are running into SSL errors inside Faraday.
The error is this:
SSL_connect returned=1 errno=0 state=SSLv3 read server hello A: sslv3 alert handshake failure
The configuration works fine some of the time (around ~50%) and it has never failed for me inside of a console sessions.
The trace of the command is this:
curl -X GET 'https://<host>/_alias/models_write?pretty
The client config is this
Thread.current[:chewy_client] ||= begin
client_configuration[:reload_on_failure] = true
client_configuration[:reload_connections] = 30
client_configuration[:sniffer_timeout] = 0.5
client_configuration[:transport_options] ||= {}
client_configuration[:transport_options][:ssl] = { :version => :TLSv1_2 }
client_configuration[:transport_options][:headers] = { content_type: 'application/json' }
client_configuration[:trace] = true
client_configuration[:logger] = Rails.logger
::Elasticsearch::Client.new(client_configuration) do |f|
f.request :aws_signers_v4,
credentials: AWS::Core::CredentialProviders::DefaultProvider.new,
service_name: 'es',
region: ENV['ES_REGION'] || 'us-west-2'
end
end
As you can see I explicitly set the ssl version to TSLv1_2, but still getting an SSLv3 error.
Thought maybe it was a race condition issue. So ran a script spawning about 10 processes with 50 threads each and calling the sidekiq perform method inside and still not able to reproduce.
I am using the managed AWS 2.3 Elasticsearch if that is at all relevant.
Any help or guidance in the right direction would be greatly appreciated, I would be happy to attach as much info as needed.
Figured it out. The problem was that the elasticsearch-ruby gem autoloads in an http adapter that it detects if one is not specified. The one used in my console was not the one getting auto loaded into sidekiq.
The sidekiq job was using the HTTPClient adapter which did not respect the SSL version option. Thus I was getting this error. After explicitly defining the faraday adapter it worked.

`<module:Rails>': superclass mismatch for class Server (TypeError)

I have seen this and several others question, but their problems are not similar to mine.
I have added the following code to the config/boot.rb , to run my server on port 8081
module Rails
class Server
def default_options
super.merge({Port: 8081})
end
end
end
Then I tried to run rails s, and i face with this erorr:
/usr/local/rvm/gems/ruby-2.2.1/gems/railties-4.2.4/lib/rails/commands/server.rb:7:in `<module:Rails>': superclass mismatch for class Server (TypeError)
from /usr/local/rvm/gems/ruby-2.2.1/gems/railties-4.2.4/lib/rails/commands/server.rb:6:in `<top (required)>'
A better way to do what you want:
require 'rails/commands/server'
module DefaultOptions
def default_options
super.merge!(Port: 8081)
end
end
Rails::Server.prepend(DefaultOptions)
The reason for the error message is because you are attempting to redefine the Rails::Server class and changing it's inheritance structure. Rails::Server inherits from ::Rack::Server, however your code is trying to say it no longer does. Therefore, you get your superclass mismatch error.
For Rails 5.1 the following line in config/boot.rb will do the trick:
ENV['PORT'] = '8081'
Link to the source.
In Rails 5.2
in config/puma.rb I added this code.
#port ENV.fetch("PORT") { 3000 }
bind 'tcp://0.0.0.0:3001'
And it works!

How to disable "Cannot Render Console from..." on Rails

I'm using Ubuntu/vagrant as my development environment.
I'm getting these messages on rails console:
Started GET "/assets/home-fcec5b5a277ac7c20cc9f45a209a3bcd.js?body=1" for 10.0.2.2 at 2015-04-02 15:48:31 +0000
Cannot render console from 10.0.2.2! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Is it possible to disable those "cannot render..." messages or allow them in any way?
You need to specifically allow the 10.0.2.2 network space in the Web Console config.
So you'll want something like this:
class Application < Rails::Application
config.web_console.permissions = '10.0.2.2'
end
Read here for more information.
As pointed out by pguardiario, this wants to go into config/environments/development.rb rather than config/application.rb so it is only applied in your development environment.
You can whitelist single IP's or whole networks.
Say you want to share your console with 192.168.0.100. You can do this:
class Application < Rails::Application
config.web_console.whitelisted_ips = '192.168.0.100'
end
If you want to whitelist the whole private network, you can do:
class Application < Rails::Application
config.web_console.whitelisted_ips = '192.168.0.0/16'
end
If you don't wanna see this message anymore, set this option to false:
class Application < Rails::Application
config.web_console.whiny_requests = false
end
Be careful what you wish for, 'cause you might just get it all
This is probably only for development purposes so you might prefer to place it under config/environments/development.rb instead of config/application.rb.
Hardcoding an IP into a configuration file isn't good. What about other devs? What if the ip changes?
Docker-related config should not leak into the rails app whenever possible. That's why you should use env vars in the config/environments/development.rb file:
class Application < Rails::Application
# Check if we use Docker to allow docker ip through web-console
if ENV['DOCKERIZED'] == 'true'
config.web_console.whitelisted_ips = ENV['DOCKER_HOST_IP']
end
end
You should set correct env vars in a .env file, not tracked into version control.
In docker-compose.yml you can inject env vars from this file with env_file:
app:
build: .
ports:
- "3000:3000"
volumes:
- .:/app
links:
- db
environment:
- DOCKERIZED=true
env_file:
- ".env"
Based on the feebdack received in comments, we can also build a solution without environment variables:
class Application < Rails::Application
# Check if we use Docker to allow docker ip through web-console
if File.file?('/.dockerenv') == true
host_ip = `/sbin/ip route|awk '/default/ { print $3 }'`.strip
config.web_console.whitelisted_ips << host_ip
end
end
I'll leave the solutions with env var for learning purposes.
Auto discovery within your config/development.rb
config.web_console.whitelisted_ips = Socket.ip_address_list.reduce([]) do |res, addrinfo|
addrinfo.ipv4? ? res << IPAddr.new(addrinfo.ip_address).mask(24) : res
end
Of course might need to add
require 'socket'
require 'ipaddr'
Within your file.
Anyone on any of my private networks is welcome.
I run in a docker container and I don't care which network it wants to use this week.
config/environments/development.rb add line
config.web_console.whitelisted_ips = ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16']
For development environment: Detect if it's docker, then determine the IP address and whitelist it
# config/environments/development.rb
require 'socket'
require 'ipaddr'
Rails.application.configure do
...
# When inside a docker container
if File.file?('/.dockerenv')
# Whitelist docker ip for web console
# Cannot render console from 172.27.0.1! Allowed networks: 127.0.0.1
Socket.ip_address_list.each do |addrinfo|
next unless addrinfo.ipv4?
next if addrinfo.ip_address == "127.0.0.1" # Already whitelisted
ip = IPAddr.new(addrinfo.ip_address).mask(24)
Logger.new(STDOUT).info "Adding #{ip.inspect} to config.web_console.whitelisted_ips"
config.web_console.whitelisted_ips << ip
end
end
end
For me this prints the following and the warning goes away 🎉
Adding 172.27.0.0 to config.web_console.whitelisted_ips
Adding 172.18.0.0 to config.web_console.whitelisted_ips
My solution was to combine
the answer from user2481743 ⭐️ https://stackoverflow.com/a/42142563/2037928
the comment from jottr ⭐️ How to disable "Cannot Render Console from..." on Rails
If you run your site locally (on the host) it generally works out, since 127.0.0.1 is always permitted. But if you're going to put your site into a container (not in production, locally), you might want to add this into config/environments/development.rb:
require 'socket'
require 'ipaddr'
Rails.application.configure do
...
config.web_console.permissions = Socket.getifaddrs
.select { |ifa| ifa.addr.ipv4_private? }
.map { |ifa| IPAddr.new(ifa.addr.ip_address + '/' + ifa.netmask.ip_address) }
...
end
P.S. Most of the time you want it to whine (don't want to do config.web_console.whiny_requests = false). Because it might mean you're running web-console in production (which you shouldn't do).
For me, whitelisted_ips didn't seem to work in a new project. The Readme states the corresponding configuration entry is supposed to be permissions now:
Rails.application.configure do
config.web_console.permissions = '192.168.0.0/16'
end
https://github.com/rails/web-console/blob/master/README.markdown
If you want to stop seeing this error message you can add this line in development.rb
config.web_console.whiny_requests = false
Note that only the last 'config.web_console.whitelisted_ips' will be used. So
config.web_console.whitelisted_ips = '10.0.2.2'
config.web_console.whitelisted_ips = '192.168.0.0/16'
will only whitelist 192.168.0.0/16, not 10.0.2.2.
Instead, use:
config.web_console.whitelisted_ips = ['10.0.2.2', '192.168.0.0/16']
class Application < Rails::Application
config.web_console.whitelisted_ips = %w( 0.0.0.0/0 ::/0 )
end
If you are using Docker most likely you don't want neither to introduce new ENV variables nor to hardcode your specific IP address.
Instead you may want to check that you are in Docker using /proc/1/cgroup, and to allow your host IP (both for web_console and better_errors). Add to your config/environments/development.rb
# https://stackoverflow.com/a/20012536/4862360
if File.read('/proc/1/cgroup').include?('docker')
# https://stackoverflow.com/a/24716645/4862360
host_ip = `/sbin/ip route|awk '/default/ { print $3 }'`.strip
BetterErrors::Middleware.allow_ip!(host_ip) if defined?(BetterErrors::Middleware)
config.web_console.whitelisted_ips << host_ip
end
I just want to add this because my own mistake caused me to get the same error.
I was missing this from the controller
load_and_authorize_resource except: [:payment_webhook]
Basically I was using cancancan to place authorization on that route, which was causing a 404 to be returned. I saw the message and assumed the two were related, when in fact they were not
Cannot render console from xxxxxx Allowed networks: xxxxx
So if you are getting an error message, it's possible that it has nothing to do with the Cannot render console from xxxxxx Allowed networks: xxxxx you see - look for other problems!

Resources