2
votes

How we should configure action cable in Rails to work in Google App Engine?

I have a Rails application which is using action cable for its messenger. On my local-host the action cable working well in development and production environments but its not working on Google App Engine.

  • I have created a Computer Engine instance and installed Redis on it.

  • Firewall allows all traffic to Redis VM.

  • Redis has bind 0.0.0.0

When I deploy the app on Google App Engine I get the error:

Firefox can’t establish a connection to the server at wss://mydomain.com/cable.

here is my current configuration:

config/environments/production.rb

config.action_cable.url = 'wss://[MYDOMAIN].com/cable'
config.action_cable.disable_request_forgery_protection = true
config.force_ssl = true
... 

config/cable.yml

production:
  adapter: redis
  url: redis://[IP_OF_REDIS_SERVER]:6379/

app.yaml

entrypoint: bundle exec rackup --port $PORT
env: flex
runtime: ruby
env_variables:
  REDIS_PROVIDER: REDIS_URL
  REDIS_URL: redis://[IP_OF_REDIS_SERVER]:6379/
  SECRET_KEY_BASE: [My_Secret_Key]

I couldn't find anything about actioncable setting in Google documentation of App Engine. I hope this question can help me and everyone with same issue.

1
Did you solve it? I'm running with the same trouble here. Whenever I run locally on production mode, I can connect with the redis instance. However when I check the production logs, I can see the error "(Redis::TimeoutError) (Redis::CannotConnectError)" I think it may be a error related with the firewall, I have a rule on the redis instance allowing to use the port 6379, but I have not this rule on my app instance. - Karl
i end up moving to compute engine , i created redis server there and production server. things are much more simpler if you do them on computer engine. in app engine you dont have access to anything and there is no docs. it took me just 1 hr to create redis server and 1 hr to create production server on computer engine. - Navid Farjad

1 Answers

1
votes

You must set create a VPC between your Redis instance and you App Engine instance. This is documented here:

https://cloud.google.com/appengine/docs/standard/python/connecting-vpc

Once you've done this, you'll have:

app.yaml

...
vpc_access_connector:
  name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR_NAME
...

Secondly, the Google managed Redis server does not allow you to set a client id. I tried forcing it to be nil, but the ActionCable subscription adapter will try to set one for you:

https://github.com/rails/rails/blob/6-0-stable/actioncable/lib/action_cable/subscription_adapter/redis.rb#L18

In order to get it working properly, I had to override this behavior.

I added the following file into my rails app:

config/initializers/decorators/redis.rb

require 'action_cable/subscription_adapter/redis'

ActionCable::SubscriptionAdapter::Redis.class_eval do
  cattr_accessor :redis_connector, default: ->(config) do
    ::Redis.new(config.except(:id, :adapter, :channel_prefix))
  end
end

Now everything is working fine. My only concern now is that the client id is somehow required and I'm going to end up with some nasty bug due to it.

Hope this works for you if you try it out!