I have been getting in to Cloud Foundry for a little while now and being a fan of using Resque to handle background tasks in Rails apps I was keen on getting this all working on my new favorite PaaS platform. So for the sake of the rest of the Cloud Foundry community and others trying to achieve the same, I thought it would be a good idea to get the process on paper.
As an example I have create a very simple Rails 3.2 application that has one model, Tweets. The purpose of this application is to archive the latest tweet from the Twitter timeline when the index page is requested. Instead of reading the Twitter timeline when the index page is loaded, a Resque job is created which performs exactly that task. The saved tweets are displayed in a table on the index page of the appication.
You can see the repository here
So, first step, create the a Rails application with a MySQL backend;
$ rails new resque_test -d mysql
Next, edit the Gemfile and add Resque and HTTParty (for getting the timeline)
1 2 | |
A quick “bundle install” and we’re good to start setting up Resque, obviously it’s good to get this working locally first, Resque is backed by Redis, if you don’t have that installed then head on over to http://redis.io/ and get it installed. If like me, you’re using Mac OS you can install it using homebrew;
$ brew install redis
Okay, now you have done all this we can actually have our Rails app start and mount Resque and give it is own route, this is easily achieved by modifying your routes.rb file so it looks like this;
1 2 3 4 5 6 7 8 9 | |
Note the include at the top of the file and the “mount” statement on line 5. Assuming that Redis is running on the local machine, you should be able to start the Rails application and view the Resque dashboard at http://localhost:3000/resque
Next, we create our model to store the archived tweets, not going to go too deep in to this but in the example the migration looks like this;
1 2 3 4 5 6 7 8 9 10 | |
And also a controller and view for displaying the archived tweets;
1 2 3 4 5 6 7 8 9 10 11 | |
Note the require to our Resque job class on line 1 that will actually read and archive the latest tweet. Also note how we enqueue a new instance of that job on line 9.
1 2 3 4 5 6 7 8 9 10 11 | |
So, next create the class that Resque will use to undertake the queued task, I always create these in the lib folder;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
I think this class is pretty self-explanatory, notice I have actually set a name for the job queue (twitter_reader), for a more detail on how to use Resque take a look at https://github.com/defunkt/resque. At this stage the application should run just fine, however we don’t currently have a Resque worker assigned to that “twitter_reader” queue to actually process the jobs. To do this we need to run one of the two Resque rake tasks, by default these are not included in the Rails project. You will need to include them in your Rakefile, mine looks like this;
1 2 3 4 5 6 7 | |
Notice I have included resque/tasks on line 6. Now we can launch a Resque job worker process, the Resque site advises us to do this like so;
$ QUEUE=twitter_reader rake resque:work
This works fine if the application is a simple rack based app but I found this doesn’t work with Rails and produces the following error “undefined method `require_dependency’”. However, launching the rake task as follows seems to work just fine!;
$ QUEUE=twitter_reader rake environment resque:work
Run the application, refresh the index page and you should start to see Resque process jobs and create record entries for the Tweet model. On to deployment to Cloud Foundy!
For this example app I am using an account on cloudfoundry.com, deploy the application as normal using vmc;
$ vmc push resque-test --runtime ruby19
Remember to create a new Redis service to bind to the application and to also save the configuration to manifest.yml. Once this is deployed you should have a working Rails app but we still need a worker process to service those requests. The best way to do this is re-deploy the application again using a different name and configuration much the same as is detailed (here)[http://blog.cloudfoundry.com/post/13481011636/running-resque-workers-on-cloud-foundry] for other rack-based apps.
Before doing this step make sure you have the latest version of vmc but re-installing the gem, the latest version has the option of deploying an application as a standalone app.
Move the manifest.yml out of the way so if we need to we can redploy the web server Rails app if needs be;
$ mv manifest.yml server-manifest.yml
Now redeploy the application using the same vmc command as last time with a different name but when asked if it is a Rails application, say no and then select “Standalone”, you will then be asked what command to execute to start the application, in this case it should be;
bundle exec rake environment VERBOSE=true QUEUE=twitter_reader resque:work
If this all deploys ok then the application should process all the queued jobs just fine! My demo application should still be running at http://resque-test.cloudfoundry.com/