Dynamic Queue Assignment for Resque Jobs

Resque is a Redis-backed library for creating background jobs, placing those jobs on multiple queues, and processing them later. Sounds great!

Let’s dive in directly:

class Archive
  @queue = :file_serve
 
  def self.perform(repo_id, branch = 'master')
    repo = Repository.find(repo_id)
    repo.create_archive(branch)
  end
end
 
Resque.enqueue(Archive, @repo.id)

This example was taken from the Resque README. It works great, but there’s a problem: you hard-code the queue to use. For an app I’m currently working on this is unwanted behaviour.
Read More »

Posted in ruby on rails | Tagged , , | Leave a comment

Setup a self-signed SSL site with Apache2

Some things need to be secure. Login and registration pages are often among them. This guide will show you how to quickly set-up a SSL site with a self-signed certificate and automatic HTTP-to-HTTPS redirect. This is ideal for setting up staging environments.

I’ll assume you have a standard Debian system with the apache2 package installed and ready.

The first step is to generate a key. You must choose a passphrase here. We’ll remove that later on for easier Apache2 restarts

openssl genrsa -des3 -out server.key 4096

Next, you need to generate a Certificate Sign Request or CSR. Some things to consider:

  • Enter the Fully Qualified Domain Name in the Common Name field. For this blog that’d be ‘blog.kabisa.nl’.
  • There’s no need to set a challenge password.
openssl req -new -key server.key -out server.csr

Next, sign the request with your key.

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Then, create an insecure version of your key. This will remove the pass phrase. If you don’t do this apache will ask for the pass phrase when it loads the key.

openssl rsa -in server.key -out server.key.insecure
mv server.key server.key.secure
mv server.key.insecure server.key

A good place to keep your key and certificate is /etc/apache2/ssl. Make sure you chmod 600 it for the root user.

Okay, setup your VirtualHosts. This example is for a Passenger-powered example app.

<VirtualHost *:80>
  ServerName example.com

  Redirect permanent / https://example.com/
</VirtualHost>

<VirtualHost *:443>
  ServerAdmin support@example.com
  ServerName example.com

  # SSL Engine Switch
  SSLEngine on

  # SSL Cipher Suite:
  SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL

  # Server Certificate
  SSLCertificateFile /etc/apache2/ssl/server.crt

  # Server Private Key
  SSLCertificateKeyFile /etc/apache2/ssl/server.key

  # Set header to indentify https requests for Mongrel
  RequestHeader set X-Forwarded-Proto "https"

  BrowserMatch ".*MSIE.*" \
  nokeepalive ssl-unclean-shutdown \
  downgrade-1.0 force-response-1.0

  DocumentRoot /var/rails/example/current/public
  <Directory "/var/rails/example/current/public">
    AllowOverride all
    Allow from all
    Options -MultiViews
  </Directory>
 </VirtualHost>

There is a file name /etc/apache2/ports.conf that configures which ports apache listen on. Make it look like this:

NameVirtualHost *:80
Listen 80

<IfModule mod_ssl.c>
    NameVirtualHost *:443
    Listen 443
</IfModule>

All set. Now restart apache2 and you should be good to go.

Posted in Random | Leave a comment

Running cucumber features with sunspot_rails

We wanted to integrate the sunspot_rails gem into our cucumber features. I found a ticket where mat adviced to call Sunspot::Rails::Server.start / stop in one of the available cucumber hooks.

Code found in features/support/env.rb is run when Cucumber begins and exits so this seemed the right place to start Solr:

Sunspot::Rails::Server.new.start
 
at_exit do
  Sunspot::Rails::Server.new.stop
end

Also, make sure you’ve added a cucumber environment to the config/sunspot.yml file; we copied the test-environment for that:

test: &amp;TEST
  solr:
    hostname: localhost
    port: 8981
    log_level: WARNING
 
cucumber:
  &lt;&lt;: *TEST

Running cucumber will let all scenarios fail unfortunately and we got a ‘Connection refused – connect(2) (RSolr::RequestError)‘ in our console.

The reason for this is simple (after I stepped into the sunspot_rails gem to be honest): the Sunspot::Rails::Server.new.start method will eventually launch a Java Servlet Container (Jetty) with the Solr WAR and uses the port defined in your sunspot.yml.
Now, starting up a server could take some time, so if cucumber’s features are run before the Solr server is up and running, the ‘Connection refused’ sounds trivial then.
First I added a sleep after starting up the server:

Sunspot::Rails::Server.new.start
sleep(5)

and this will work for most cases, but I thought it would be better to let cucumber wait just long enough until the server is up and running. When the server is up, you can open up your browser and enter http://localhost:8981/solr to administering Solr. This we can use to find out if we’ve waited long enough and start our features. I’ve put this into a seperate class named CukeSunspot and created this file in the features/support directory:

require "net/http"
 
class CukeSunspot
 
  def initialize
    @server = Sunspot::Rails::Server.new
  end
 
  def start
    @started = Time.now
    @server.start
    up
  end
 
  private
  def port
    @server.port
  end
 
  def uri
    "http://0.0.0.0:#{port}/solr/"
  end
 
  def up
    while starting
      puts "Sunspot server is starting..."
    end
    puts "Sunspot server took #{'%.2f' % (Time.now - @started)} sec. to get up and running. Let's cuke!"
  end
 
  def starting
    begin
      sleep(1)
      request = Net::HTTP.get_response(URI.parse(uri))
      false
    rescue Errno::ECONNREFUSED
      true
    end
  end
 
end

Now we can the alternative start method and remove the explicit sleep statement in our global before hook. features/support/env.rb:

CukeSunspot.new.start
 
at_exit do
  Sunspot::Rails::Server.new.stop
end

And voila, if you run cucumber, you scenario’s should run successfully. On my machine:

Sunspot server is starting...
Sunspot server is starting...
Sunspot server took 3.74 sec. to get up and running. Let's cuke!
Posted in ruby | 2 Comments

Using transactions with Ruby DataMapper

With DataMapper, it can be quite a challenge to perform tasks that seem so simple at first. DataMapper is an object-relational mapper (ORM) written in Ruby, with a lot of great features and innovative approaches to common ORM-tasks. But it lacks documentation for some of the less-used features and even the more popular search engines don’t have the answer to all questions.

Note: the following examples have been tested with DataMapper version 0.10.2.

One of the questions I had was how to perform multiple queries within a single (database) transaction, so that I can ’stage’ a number of database queries and commit (or rollback) them all in one go. Fortunately, after some investigation of the DataMapper source code, it turns out to be an extremely simple task:

User.transaction do
  User.first.update(:name =&gt; "John Smith")
  Address.first.update(:street =&gt; "") # Invalid: street must not be blank
end

With this code neither the address nor the user will be updated in the database if one of the updates fails. The syntax is actually the same as for the ActiveRecord ORM. However, triggering a rollback is done differently, as can be seen in the following example.

User.transaction do |t|
  User.first.update(:name =&gt; "John Smith")
  Address.first.update(:street =&gt; "Oak St. 400")
  t.rollback # Transaction will be rolled back even when updates are OK.
end

That’s it for now. I’m sure there are some additional features that I haven’t mentioned here, but this is all I had to know at this point.

Posted in ruby | 1 Comment

Presentation: Heroku & Jeweler + Gemcutter

A small presentation by Ariejan on two topics:

  • Heroku – What is Heroku and how does it compare to Amazon EC2 and Kabisa’s Hosting
  • Jeweler + Gemcutter – How to use Jeweler to manage your gem and push it to gemcutter

Read More »

Posted in Talks | Tagged , , , , , , | Leave a comment

Xen: How to fix “SIOCSIFADDR: No such device”

Yesterday I had to clone a VPS to run some CPU and memory intensive tests. With our current setup (Xen + LVM), cloning an image on the fly is easy.

After configuring a new IP address for the clone, I booted up the system. Nice, but I ran into a problem:

Configuring network interfaces...SIOCSIFADDR: No such device
eth0: ERROR while getting interface flags: No such device
SIOCSIFNETMASK: No such device
SIOCSIFBRDADDR: No such device
eth0: ERROR while getting interface flags: No such device
eth0: ERROR while getting interface flags: No such device
Failed to bring up eth0.

After some investigation I found that the MAC address for eth0 is stored on disk in /etc/udev/rules.d/z25_persistent-net.rules. That makes sense, because the whole file system was cloned. But, I swapped the virtual network card, and I’d expect is to work. It didn’t.

The solution is quite easy. Empty /etc/udev/rules.d/z25_persistent-net.rules. Then shutdown and start your VPS. You must do a full shutdown, a reboot won’t work.

For the lazy folk out there, here’s how to quickly empty the file:

echo "" > /etc/udev/rules.d/z25_persistent-net.rules

After you have started your VPS back up again, you should be able to ping out over the network. If you peek in /etc/udev/rules.d/z25_persistent-net.rules you should see a line that contains the MAC address for your virtual network device.

Posted in hosting | Tagged , , , , | 1 Comment

How to setup Ruby on Rails, Apache and Passenger on Debian Linux

For this article I’m going to install a single (virtual) server to run a standard Ruby on Rails application. I will be using Apache2 and passenger for the webserver stack and MySQL as a database server.

Let’s start by installing Ruby and all tools:


# apt-get install build-essential
# apt-get install ruby irb ri rdoc libopenssl-ruby ruby1.8-dev
# ruby -v
# cd /usr/local/src
# wget http://rubyforge.org/frs/download.php/60718/rubygems-1.3.5.tgz # replace with latest version of rubygems
# tar xfvz rubygems-1.3.5.tgz
# cd rubygems-1.3.5
# ruby setup.rb
# ln -s /usr/bin/gem1.8 /usr/bin/gem
# gem -v
# gem install gemcutter
# gem tumble
# apt-get install mysql-server # this will ask for a password during installation
# apt-get install libmysqlclient15-dev
# gem install mysql
# gem install rails
# apt-get install git-core
# apt-get install apache2
# gem install passenger
# passenger-install-apache2-module

Copy the following lines from the output and paste them at the end of the file /etc/apache2/apache2.conf. They should look something like this:


LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-2.2.7/ext/apache2/mod_passenger.so
PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.2.7
PassengerRuby /usr/bin/ruby1.8

Finally let’s restart apache2:

/etc/init.d/apache2 restart

Phew! That's it... We now have all the software we need on the server that's required to deploy your Ruby on Rails app on Debian Linux (Lenny)!

In a future article I'll cover the basics of deployment using Capistrano.

Posted in ruby | Tagged , , , , , | 1 Comment

Ruby and SSL Certificate Validation

If your ruby app is doing SSL, you have probably seen one of the following errors:

doc = Hpricot(open("https://www.cert.org/blogs/vuls/rss.xml")) # => /usr/lib/ruby/1.8/net/http.rb:590:in `connect': certificate verify failed (OpenSSL::SSL::SSLError)

or

warning: peer certificate won't be verified in this SSL session

The solution is to make sure ruby has access to the right set of root certificates.
Read More »

Posted in ruby | Tagged , , | 1 Comment

Giving Love To the Community

Earlier this month Kabisa attended the Ruby en Rails 2009 conference in Amsterdam. Ruby en Rails is the largest dedicated Ruby and Rails conference in the Netherlands.

For the first time in its history Ruby en Rails was a multiple day event. The first day, October 31, was packed with interesting presentations on various Ruby and Rails related topics, by great speakers including renowned community idols like Yehuda Katz, Jeremy Kemper, Jonathan Weiss and many more. The second day (the ‘geek-day’) focused on more practical sessions and lightning talks. On this day another event was held: The RubyEnRails Rumble (RERR), a competition where teams of two had to complete an assignment within a certain time.
Read More »

Posted in ruby | Tagged , , , , | Leave a comment