ActionCable and Heroku Redis configuration - ruby-on-rails

Last week RedisToGo was terminated on Herokum, leaving me with no choice but to find an alternative. I got a new subscription from Heroku: Heroku Redis.
Everything seems to work fine (all tasks/jobs) except things related to ActionCable.
[ActionCable] [#######] Registered connection (#########)
2022-08-17T00:40:23.213184+00:00 app[web.1]: #<Thread:0x00007e######/app/vendor/bundle/ruby/2.6.0/gems/actioncable-5.1.7/lib/action_cable/subscription_adapter/redis.rb:144 run> terminated with exception (report_on_exception is true):
2022-08-17T00:40:23.213206+00:00 app[web.1]: /app/vendor/bundle/ruby/2.6.0/gems/redis-4.1.4/lib/redis/client.rb:268:in `rescue in io': Connection lost (ECONNRESET) (Redis::ConnectionError)
I spent the last few days trying all sort of trick, but nothing work.
My cable.yml file looks like:
production:
adapter: redis
url: <%= ENV['REDIS_URL'] %>
my redis.rb file looks like this:
uri = if Rails.env == 'production'
URI.parse(ENV["REDIS_URL"])
else
URI.parse("redis://localhost:6379")
end
Resque.redis = Redis.new(host: uri.host, port: uri.port, password: uri.password, ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE })
Am I missing certain parameters that results in the error ?

I use Heroku Redis and here's what my cable.yml looks like:
development:
adapter: redis
url: redis://localhost:6379/1
channel_prefix: myapp_development
test:
adapter: redis
url: redis://localhost:6379/1
channel_prefix: myapp_test
production:
adapter: redis
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
channel_prefix: myapp_production
ssl_params:
verify_mode: <%= OpenSSL::SSL::VERIFY_NONE %>
If your tasks and jobs don't use Redis (if ActionCable is the only thing trying to use Redis) then your Redis might not actually be set up properly. Here's the documentation.
Check to make sure Heroku actually set a REDIS_URL env variable:
$ heroku config | grep REDIS
> REDIS_URL: redis://h:asdfqwer1234asdf#ec2-111-1-1-1.compute-1.amazonaws.com:111
Make sure your instance has a normal configuration:
https://devcenter.heroku.com/articles/heroku-redis#configuring-your-instance
Two other helpful sources:
How to solve the SSL error for Redis 6 on Heroku
ActionCable Redis adapter crashes with Heroku Redis 6

Related

Redis redirects to localhost on Heroku (Rails 6)

I have an app hosted on Heroku, using Redis Cloud and ActionCable. Locally everything works but on Heroku the user is redirected to a localhost address after a form is submitted. I have tried most of the advice listed here (apart from resque settings since resque gem is not installed): Redis tries to connect to localhost on Heroku instead of REDIS_URL
Redis Cloud was added with
heroku addons:create rediscloud:30
This is in my cable.yml, I have commented out two other solutions that I tried that also did not work (in my actual code, redis url is set to the actual address rather than xxx999)
production:
adapter: redis
# url: <%= ENV.fetch('REDISCLOUD_URL') %>
# url: <%= ENV.fetch("REDISCLOUD_URL") { "redis://localhost:6379/1" } %>
url: <%= ENV.fetch("REDISCLOUD_URL") { "redis://default:xxx999#redis-13674.c77.eu-west-1-1.ec2.cloud.redislabs.com:13674" } %>
channel_prefix: art--collabs_production
In redis.rb:
if ENV["REDISCLOUD_URL"]
$redis = Redis.new(url: ENV["REDISCLOUD_URL"])
end
In production.rb I have the following (again, the commented out code has been tried and also failed)
config.action_cable.url = "ws://www.artcollabs.net/cable"
config.action_cable.allowed_request_origins = [ "http://www.artcollabs.net", "https://www.artcollabs.net" ]
# config.cache_store = :redis_cache_store, { url: ENV.fetch("REDISCLOUD_URL", "redis://localhost:6379/1") }
config.cache_store = :redis_cache_store, { url: ENV.fetch("REDISCLOUD_URL", "redis://default:xxx999#redis-13674.c77.eu-west-1-1.ec2.cloud.redislabs.com:13674") }
Any suggestions on how to solve this?

Actioncable broadcast not working from console in Rails

I used actioncable on rails 5 app. Below code work in controller but not in console.
ActionCable.server.broadcast "connector_app", content: "test message"
Response:
[ActionCable] Broadcasting to connector_app: {:content=>"test message"}
=> nil
cable.yml
development:
adapter: redis
url: redis://localhost:6379/1
test:
adapter: async
production:
adapter: redis
url: redis://localhost:6379/1
Contoller code( It works properly):
def sample_socket_message
ActionCable.server.broadcast "connector_app",
content: "test message",
head :ok
end
Problem Solved:
Forget to add below code in config/initializer/redis.rb
$redis = Redis.new(:host => 'localhost', :port => 6379)
The default behavior for ActionCable in development and test mode is to use the async adapter, which operates within the same process only. For inter-process broadcasting, you will need to switch to the redis adapter.
Since you are using redis adapter in development that's why it is working in controller and not working in console.
cable.yml
test:
adapter: redis
url: redis://localhost:6379/1

Getting Action Cable to broadcast in Sidekiq Job

I'm using Rails 5 in a docker environment and I can get Action Cable to broadcast on a Sidekiq worker perfectly fine, using worker.new.perform.
But for the life of me, I cannot get it to broadcast while using worker.perform_async.
Here is my cable.yml:
default: &default
adapter: redis
url: <%= ENV['REDIS_PROVIDER'] %>
development:
<<: *default
test:
<<: *default
production:
<<: *default
Here is my worker:
class AdminWorker
include Sidekiq::Worker
def perform
ActionCable.server.broadcast 'admin_channel', content: 'hello'
end
end
My Admin Channel:
class AdminChannel < ApplicationCable::Channel
def subscribed
stream_from "admin_channel"
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
end
As I mentioned earlier, this works just fine when calling AdminWorker.new.perform. As soon as I try to run AdminWorker.perform_async, the cable will not broadcast and nothing helpful regarding action cable in the logs. What am I missing here?
I had the same problem. Came across this answer: ActionCable.server.broadcast from the console - worked for me. Basically just changed cable.yml
development:
adapter: async
to
development:
adapter: redis
url: redis://localhost:6379/1
and I was able to broadcast from console, models, Sidekiq worker classes, etc.
For those who wants to dockerize rails and sidekiq, you should run action_cable server separately like
puma -p 28080 cable/config.ru
https://nickjanetakis.com/blog/dockerize-a-rails-5-postgres-redis-sidekiq-action-cable-app-with-docker-compose
https://github.com/kchrismucheke/dockersample/blob/da5923899fb17682fabed041bef5381ed3fd91ab/config/application.rb#L57-L62
In development environment
By default, ActionCable would run only on the rails server only. And it would not work in Sidekiq, console, cron jobs, etc.
Because in config/cable.yml development server adapter is set to async
Solution:
For ActionCable inter-process broadcasting, you have to set the adapter to Redis
In config/cable.yml
development:
adapter: redis
url: redis://localhost:6379/1
channel_prefix: project_name_development

Mongoid Production Issue: Failed to connect to a master node

I've switched away from Mongo_Mapper to Mongoid and am having trouble deploying to production, for some reason. I'm using NGINX, Rails 3.1, and Passenger. I keep getting this message, "Failed to connect to a master node at myusernamehere:27017 (Mongo::ConnectionFailure)".
defaults: &defaults
host: localhost
# slaves:
# - host: slave1.local
# port: 27018
# - host: slave2.local
# port: 27019
development:
<<: *defaults
database: s3uploadergen_development
test:
<<: *defaults
database: s3uploadergen_test
production:
host: localhost
port: 27017
database: mydbnamehere
username: myuserhere
password: mypasswordhere
I've triple-checked all settings and tried the ENV approach as well (adding the ENV variables to production.rb and calling them via the documented mongoid approach but had the same issue):
production:
host: <%= ENV['MONGOID_HOST'] %>
port: <%= ENV['MONGOID_PORT'] %>
username: <%= ENV['MONGOID_USERNAME'] %>
password: <%= ENV['MONGOID_PASSWORD'] %>
database: <%= ENV['MONGOID_DATABASE'] %>
Ideally, I want to just specify it either in production.rb or an initializer of some sort.
I'm assuming that by "documented mongoid approach" you mean setting the recommended "uri" param instead of all those different setttings. You might want to try it since it's the recommended way of doing it.
defaults: &defaults
persist_in_safe_mode: true
development:
<<: *defaults
host: localhost
database: app_development
test:
<<: *defaults
host: localhost
database: app_test
production:
<<: *defaults
uri: <%= ENV['MONGOHQ_URL'] %>
Note that I do use Heroku but I don't use the MongoHQ add on. I just use it directly, so I manually set my MONGOHQ_URL. Your uri would look something like:
mongodb://<user>:<password>#<the.db.host.com>:<port>/<database_name>
Looks to me like you can't connect to "localhost" based on the error (like maybe you need the full host name or IP or something?). Anything in your app logs?
Just make sure not to set "host" and "uri" on any of the ENV's because "host" will override the setting that is derived from the uri.

How to configure mongoid 1.9.2 on heroku?

I have a rails 2.3.8 app running on heroku, but am having trouble configuring mongoid 1.9.2 with MongoHQ. Has anyone made this work?
Thanks!
To connect to the database you must use the MONGODB_URL variable.
# set these environment variables on your prod server
production:
<<: *defaults
uri: <%= ENV['MONGOHQ_URL'] %>
Also, make sure the host property is not set in the defaults node.strong text
defaults: &defaults
# slaves:
# - host: slave1.local
# port: 27018
# - host: slave2.local
# port: 27019

Resources