Owning a Tesla in Brooklyn
where do I charge
- tags
- tesla
ActionCable is WebSockets on rails. This lets you create realtime, interactive systems, where you can push data from one client to another client without reloading or polling. But how do we deploy it on heroku?
ActionCable is composed to two main parts: a javascript client library, and a backend pub/sub system built upon Redis. We’re also going to use ActiveJob to offload the publishing tasks from the main user thread, so we’ll also be setting up sidekiq.
Let’s go through the steps of how to deploy things on heroku.
I’m going to use an app that dhh made as a walk through. What it does is
rooms_channel
I’ve transcribed it here to see what was added. The code is available to clone the code from github if you don’t have an app that you are working on already.
The app we generated was done using basic rails 5 commands, and it’s out of the box stuff. (Unlike most of the walkthroughs on this site which were done with seed. It’s setup to use puma (good), which will handle the WebSockets. It’s also setup with ActiveJob and ActionCable, both on which are in async local mode and won’t use redis in development. ActionCable will also need to know where it’s websocket is going to connect to. Lets walk through everything that needs to get done.
First we need to add some things to the Gemfile, specifically redis, postgres, and the sidekiq gems. Add the following to your Gemfile
|
|
Make sure you remove the sqlite3
on the top of the file, we only want it in development. We are installing sinatra
out of the master branch since the current release doesn’t play well with Rails 5. (If it tries to install Sinatra 1.0 you’ll get rake exception errors.) If you don’t want the web interface to sidekiq you can omit.
First we need to create a Procfile
that defines our dynos
|
|
I’m running sidekiq with a concurrency of 2 to limit the number of redis connections. You’ll probably want that a lot higher in real life if you are using Sidekiq for other things..
Now create config/initializers/active_job.rb
and tell ActiveJob to use sidekiq
|
|
And let’s add the sidekiq web interace to your config/routes.rb
:
|
|
If this was a real app, you’d limit who can get to that engine. If you installed devise, the way to do that is:
|
|
It’s always nice to change as little as we can, so when everything blows up in our face we can limit our investigations to a small change set. So lets first migrate our development environment to communicate over redis, so the ActiveJobs are run in a seperate process, and that ActionCable will be able to communicate from that process, back to the main web server, back to the client.
Edit config/cable.yml
to set the development environment use to use redis.
|
|
If you don’t have redis installed, use homebrew to do that now:
|
|
If you don’t have foreman installed, do that now:
|
|
Now lets run that app!
|
|
Using foreman will start both the web interace as well as the sidekiq worker.
Now you should be able to go to http://localhost:3000
in multiple windows and talk with yourself. I really like talking with myself, and I assume that you do as well.
And http://localhost:3000/admin
should load up the sidekiq admin console. Validate that everything is working, since now we are going to spin up everything on heroku!
Create a new app:
|
|
Then we create a redis instance
|
|
We now need to tell ActionCable where it’s redis server is. Lets find out the answer and put in into the production section of config/cable.yml
.
|
|
config/cable.yml
:
|
|
We need to tell rails where it’s expected to receive the websocket connection from. heroku info
will show us our external application. If you deploy on a custom url, you’ll need to add that as well.
|
|
Lets tell rails about it. Edit config/environments/production.rb
. Obviously update the urls for your application.
|
|
Note that wss
is WebSockets over over SSL. You should use that, for a number of reasons including but not limited to security. However, if you don’t use SSL, use ws
instead.
Now we need to tell the javascript where to connect. Lets open up app/views/layouts/application.html.erb
and add this into the <HEAD>
:
<%= action_cable_meta_tag %>
First we add the code to repo
|
|
Now we push to heroku itself:
|
|
If that goes well, lets create the database tables and spin up the worker process
|
|
And now, lets run the app and look at the logs:
|
|
We ran open twice, so you could see what was there in two windows. Does it work? Do 3 windows work?
Do you like talking to yourself as much as I do?
Right now you have 1 web dyno, running puma with 5 threads, and 1 worker dyno running sidekiq with 2 concurrent worker. This should be at least 5 redis connections, up to 2 more depending upon how many jobs have gone through sidekiq. Lets look at the redis info:
$ heroku redis:cli
ec2-54-243-230-243.compute-1.amazonaws.com:24949> info
....
# Clients
connected_clients:7
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:2
....
So we see that we have 7 active connections now. As you get more people listening to redis, those will go up. Adding more dynos will push the number of active connections up, so you need to be careful in sizing both your postgres install as well as your redis install.
Image credit Lee Roberts
Previously
Next