Freelancing Gods 2012

God
02 Mar 2012

Drop in at Inspire9

I was about to write a new post about something technical, but that can wait for another day. Right now, I want to highlight to the world Inspire9, a coworking space here in Melbourne.

Now, Inspire9 is also a web development business, run by the talented and generous Nathan Sampimon. When the word spread a few years ago that he had an office for himself but others could drop by, I started visiting – as did others. Slowly the numbers grew, and instead of being just “Nathan’s office”, there was a growing sense of community and shared ownership, and it had become a much-loved coworking space.

As part of that growth, we had clearly outgrown our existing space – a measly 77 square metres – and so plans were hatched for something much larger. Halfway through last year, we moved into our new residence at 41 Stewart St, Richmond (right beside Richmond Station), with 370 square metres to work and play in (and that’ll eventually double to 720).

IMG_2927

Our office is now a bustling hive of activity – there’s usually somewhere between 20 and 30 people in each day at any one point. Many of us have dedicated desks (it is something I happily pay for). That said, not everyone who works from Inspire9 are residents – anyone is welcome to drop by and use a desk, and it’s free.

IMG_5187.jpg

It’s occurred to me to write about Inspire9 now because of what’s happened in the last 24 hours. Last night, someone stole Kealey’s iPhone while she was making sure an event in the office was running smoothly. Kealey is not only our events manager, but also a key part of the heart and soul of Inspire9 – so we were all pretty upset, and doubly so because it happened in our midst, in our home.

Not content with this situation, this morning Ned got a pledgie running to help fund a new iPhone for Kealey. Within two hours we had the funds, and by the end of today Kealey had a shiny new iPhone in her hands. The full story has been covered on the Inspire9 blog, and I particularly love the title, a very appropriate ‘Restoring Balance’.

While Inspire9 is a fantastic place to work, it’s the community that makes it stand out. I consider myself very lucky to be a part of it.

So, if you find yourself in Melbourne, please do visit. You’re welcome to pull up a chair and get some work done, or perhaps challenge someone to a game of pool. We also now host the Melbourne Ruby and Python meets every month (as well as plenty of other events), and we’re a friendly bunch – don’t be afraid to say hello!

18 Feb 2012

The Ballad of Roger and Grace

One of my favourite times to be in Melbourne is April, because that’s when the Comedy Festival happens in this fine city. And Comedy Festivals are especially fantastic when Daniel Kitson is in town performing – which he will be this year, with a new show.

Daniel Kitson, if you’ve not heard of him before, is not only a talented comedian. He’s also a brilliant storyteller, and often his performances are cleverly woven, heartwarming, and human.

As a rare treat (recordings of his full shows are extremely scarce), he’s put one of his older storytelling shows online – a collaboration between him and his good friend, musician Gavin Osborn, titled The Ballad of Roger and Grace. I actually have raved about it already, back when they performed it in 2008.

If any of this has caught your interest, then I recommend you go and spend the £2.50 (a bargain indeed), set aside an hour, and soak in the intertwined stories and songs.

And then perhaps you should consider buying a ticket to Daniel Kitson’s show at this year’s festival – they’ll soon be on sale, and will disappear quickly (I’m far from the only person in Melbourne who’s a fan).

22 Jan 2012

Backing up with Backup

I’ve found myself singing the praises of Michael van Rooijen’s backup gem twice in quick succession lately – and so, I just want to run through how I’m using it, and how useful I find it.

For those not familiar with it, Backup provides a neat DSL for creating backup scripts with archiving files and databases through to common data stores (S3, Rackspace, SFTP, etc), with notifications via email, Campfire and others. If you want a rundown of all the options, click the link above – there’s quite a few. I’m using the gem to make sure all critical data for Flying Sphinx is stored in multiple locations – and particularly, with different providers.

The documentation’s pretty solid, so I won’t keep you long, but here’s two examples. First up, here’s my script for copying an archive of essential files (including a SQLite database) off to Ninefold – with the private details changed:

Backup::Model.new(:database_backup, "Database Backup") do
  archive :oedipus do |archive|
    archive.add '/mnt/sphinx/oedipus'
  end

  compress_with Gzip do |compression|
    compression.best = true
  end

  store_with Ninefold do |nf|
    nf.storage_token  = 'STORAGE_TOKEN'
    nf.storage_secret = 'STORAGE_SECRET'
    nf.path           = "oedipus/#{`hostname`.strip}"
    nf.keep           = 20
  end

  notify_by Mail do |mail|
    mail.on_success = true
    mail.on_failure = true

    mail.from      = 'support-at-flying-sphinx'
    mail.to        = 'pat-at-freelancing-gods'
    mail.address   = 'smtp.sendgrid.com'
    mail.user_name = 'SMTP_USER_NAME'
    mail.password  = 'SMTP_PASSWORD'
  end
end

For the above, I added Ninefold support to Backup, and Michael was kind enough to merge my commits in.

For my next script, though, I’m syncing directories to both S3 (in Singapore) and Rackspace (in the UK). The current releases of Backup don’t support syncing to Rackspace – but I ended up taking inspiration from fellow Melburnian Ryan Allen’s Sir Sync-a-Lot and rewrote the S3 support with his bulk MD5 approach. The code was simple enough – thanks to Wesley Beary’s excellent Fog – so I adapted the code to handle Rackspace as well.

However, I’ve not written tests for this, and my code does not yet support mirroring – so, I’ve not yet provided a patch back to Michael. If you want to use my code, feel free – but I will get to submitting a proper patch soon.

All that said, here’s the script:

Backup::Model.new(:volume_backup, "Sphinx Backup") do
  sync_with S3 do |s3|
    s3.access_key_id      = 'ACCESS_KEY'
    s3.secret_access_key  = 'SECRET_KEY'
    s3.bucket             = "fs-#{`hostname`.strip}-sync"
    s3.region             = 'ap-southeast-1'
    s3.path               = ''
    s3.mirror             = false

    s3.directories do |directory|
      directory.add '/mnt/sphinx/oedipus'
      directory.add '/mnt/sphinx/flying-sphinx'
    end
  end

  sync_with Rackspace do |rs|
    rs.api_key  = 'API_KEY'
    rs.username = 'USER_NAME'
    rs.auth_url = 'lon.auth.api.rackspacecloud.com'
    rs.bucket   = "fs-#{`hostname`.strip}-sync"
    rs.path     = ''
    rs.mirror   = false

    rs.directories do |directory|
      directory.add '/mnt/sphinx/oedipus'
      directory.add '/mnt/sphinx/flying-sphinx'
    end
  end

  notify_by Mail do |mail|
    mail.on_success = true
    mail.on_failure = true

    mail.from      = 'support-at-flying-sphinx'
    mail.to        = 'pat-at-freelancing-gods'
    mail.address   = 'smtp.sendgrid.com'
    mail.user_name = 'SMTP_USER_NAME'
    mail.password  = 'SMTP_PASSWORD'
  end
end

I’ve been running the first script for several months, and the second for close to a month – both via cron – and had no problems at all. If you’ve not got a solid backup system in place because you’re finding it complex and frustrating, you’ve now got one less excuse.

21 Nov 2011

Cut and Polish: A Guide to Crafting Gems

As I mentioned here earlier in the year, a few weeks ago I had the pleasure of visiting Ukraine and speaking at the RubyC conference in Kyiv. My talk was a run through of how to build gems, some of the tools that can help, and a few best practices.

The video of my session is now online, if you’re interested:

There’s also the slides with notes, if you prefer that.

One of the questions asked towards the end was about publishing private gems, which I’d not dealt with before. However, Darcy was quick to tweet that Gemfury looks like a promising solution for those scenarios.

Please let me know if you think I’ve missed any critical elements of building and publishing gems – or if you have any further questions.

And many thanks to the RubyC team for putting together the conference and inviting me to speak – I had a great time!

19 Oct 2011

A Sustainable Flying Sphinx?

In which I muse about what a sustainable web service could look like – but first, the backstory:

A year ago – almost to the day – I sat in a wine bar in Sydney’s Surry Hills with Steve Hopkins. I’d been thinking about how to get Sphinx working on Heroku, and ran him through the basic idea in my head of how it could work. His first question was “So, what are you working on tomorrow, then?”

By the end of the following day, I had some idea of how it would work. Over the next few months I had a proof of concept working, hit some walls, began again, and finally got to a point where I could launch an alpha release of Flying Sphinx.

In May, Flying Sphinx became available for all Heroku users – and earlier today (five months later), I received my monthly provider payment from Heroku, with the happy news that I’m now earning enough to cover all related ongoing expenses – things like AWS for the servers, Scalarium to manage them, and Tender for support.

Now, I’m not rolling in cash, and I’m certainly not earning enough through Flying Sphinx to pay rent, let alone be in a position to drop all client work and focus on Flying Sphinx full-time. That’s cool, either of those targets would be amazing.

And of course, money isn’t the be all and end all – even though this is a business, and I certainly don’t want to run at a loss. I want Flying Sphinx to be sustainable – in that it covers not only the hosting costs, but my time as well, along with supporting the broader system around it – code, people and beyond.

But what does a sustainable web service look like, particularly beyond the standard (outmoded) financial axis?

Sustainable Time

Firstly (and selfishly), it should cover the time spent maintaining and expanding the service. Flying Sphinx doesn’t use up a huge amount of my time right at the moment, but I’m definitely keen to improve a few things (in particular, offer Sphinx 2.0.1 alongside the existing 1.10-beta installation), and there is the occasional support query to deal with.

This one’s relatively straight-forward, really – I can track all time spent on Flying Sphinx and multiply that by a decent hourly rate. If it turns out I can’t manage all the work myself, then I pay someone else to help.

It certainly doesn’t look like I’m going to need anyone helping in the near future, mind you – nor am I drowning in support requests.

Sustainable Software

Ignoring the time I spend writing code for Flying Sphinx (as that’s covered by the previous section), pretty much every other piece of software involved with the service is open source. Front and centre among these is Sphinx itself.

I certainly don’t expect to be paid for my own open source contributions, but it certainly helps when there’s some funds trickling in to help motivate dealing with support questions, fixing bugs and adding features. It can also provide a stronger base to build a community as well.

With this in mind, I’m considering setting aside a percentage of any profit for Sphinx development – as any improvements to that help make Flying Sphinx a stronger offering.

(I could also cover my time spent on Thinking Sphinx either with a percentage cut – either way it would end up in my pocket though.)

Sustainable Hardware

This is where things get a little trickier – we’re not just dealing with bits and electrons, but also silicon and metals. The human race is pretty bad at weaning itself off of limited (as opposed to renewable) resources, and the hardware industry certainly is going to hit some limits in the future as certain metals become harder to source.

Of course, the servers use a lot of energy, so one thing I will be doing is offsetting the carbon. I’ve not yet figured out the best service to do this, but will start by looking at Brighter Planet.

From a social perspective, there’s also questions about how those resources are sourced. We should be considering the working conditions of where the metals are mined (and by whom), the people who are soldering the logic boards, and those who place the finished products into racks in data centres.

As an example, let’s look at Amazon. Given the recent issues raised with the conditions for staff in their warehouses, I think it’s fair to seek clarification on the situation of their web service colleagues. And what if there were significant ethical issues for using AWS? What then for Flying Sphinx, which runs EC2 instances and is an add-on for Heroku, a business built entirely on top of Amazon’s offerings?

I could at least use servers elsewhere – but that means bandwidth between servers and Heroku apps starts to cost money – and we introduce a step of latency into the service. Neither of those things are ideal. Or I could just say that I don’t want to support Amazon at all, and shut down Flying Sphinx, remove all my Heroku apps, and find some other hosting service to use.

Am I getting a little too carried away? Perhaps, but this is all hypothetical anyway. I’m guessing Amazon’s techs are looked after decently (though I’d love some confirmation on this), and am hoping the situation improves for their warehouse staff as well.

I am still searching for answers for what truly sustainable hardware – and moreso, sustainable web services – financially, socially, environmentally, and technically. What’s your take? What have I forgotten?

24 Sep 2011

Versioning your APIs

As I developed Flying Sphinx, I found myself both writing and consuming several APIs: from Heroku to Flying Sphinx, Flying Sphinx to Heroku, the flying-sphinx gem in apps to Flying Sphinx, Flying Sphinx to Sphinx servers, and Sphinx servers to Flying Sphinx.

None of that was particularly painful – but when Josh Kalderimis was improving the flying-sphinx gem, he noted that the API it interacts with wasn’t that great. Namely, it was inconsistent with what it returned (sometimes text status messages, sometimes JSON), it was sending authentication credentials as GET/POST parameters instead of in a header, and it wasn’t versioned.

I was thinking that given I control pretty much every aspect of the service, it didn’t matter if the APIs had versions or not. However, as Josh and I worked through improvements, it became clear that the apps using older versions of the flying-sphinx gem were going to have one expectation, and newer versions another. Versioning suddenly became a much more attractive idea.

The next point of discussion was how clients should specify which version they are after. Most APIs put this in the path – here’s Twitter’s as an example, specifying version 1:

https://api.twitter.com/1/statuses/user_timeline.json

However, I’d recently been working with Scalarium’s API, and theirs put the version information in a header (again, version 1):

Accept: application/vnd.scalarium-v1+json

Some research turned up a discussion on Hacker News about best practices for APIs – and it’s argued there that using headers keeps the paths focused on just the resource, which is a more RESTful approach. It also makes for cleaner URLs, which I like as well.

How to implement this in a Rails application though? My routing ended up looking something like this:

namespace :api do
  constrants ApiVersion.new(1) do
    scope :module => :v1 do
      resource :app do
        resources :indices
      end
    end
  end

  constraints ApiVersion.new(2) do
    scope :module => :v2
      resource :app do
        resources :indices
      end
    end
  end
end

The ApiVersion class (which I have saved to app/lib/api_version.rb) is where we check the version header and route accordingly:

class ApiVersion
  def initialize(version)
    @version = version
  end

  def matches?(request)
    versioned_accept_header?(request) || version_one?(request)
  end

  private

  def versioned_accept_header?(request)
    accept = request.headers['Accept']
    accept && accept[/application\/vnd\.flying-sphinx-v#{@version}\+json/]
  end

  def unversioned_accept_header?(request)
    accept = request.headers['Accept']
    accept.blank? || accept[/application\/vnd\.flying-sphinx/].nil?
  end

  def version_one?(request)
    @version == 1 && unversioned_accept_header?(request)
  end
end

You’ll see that I default to version 1 if no header is supplied. This is for the older versions of the flying-sphinx gem – but if I was starting afresh, I may default to the latest version instead.

All of this gives us URLs that look like something like this:

http://flying-sphinx.com/api/app
http://flying-sphinx.com/api/app/indices

My SSL certificate is locked to flying-sphinx.com – if it was wildcarded, then I’d be using a subdomain ‘api’ instead, and clean those URLs up even further.

The controllers are namespaced according to both the path and the version – so we end up with names like Api::V2::AppsController. It does mean you get a new set of controllers for each version, but I’m okay with that (though would welcome suggestions for other approaches).

Authentication is managed by namespaced application controllers – here’s an example for version 2, where I’m using headers:

class Api::V2::ApplicationController < ApplicationController
  skip_before_filter :verify_authenticity_token
  before_filter :check_api_params

  expose(:app) { App.find_by_identifier identifier }

  private

  def check_api_params
    # ensure the response returns with the same header value
    headers['X-Flying-Sphinx-Token'] = request.headers['X-Flying-Sphinx-Token']
    render_json_with_code 403 unless app && app.api_key == api_key
  end

  def api_token
    request.headers['X-Flying-Sphinx-Token']
  end

  def identifier
    api_token && api_token.split(':').first
  end

  def api_key
    api_token && api_token.split(':').last
  end
end

Authentication, in case it’s not clear, is done by a header named X-Flying-Sphinx-Token with a value of the account’s identifier and api_key concatenated together, separated by a colon.

(If you’re not familiar with the expose method, that’s from the excellent decent_exposure gem.)

So where does that leave us? Well, we have an elegantly namespaced API, and both versions and authentication is managed in headers instead of paths and parameters. I also made sure version 2 responses all return JSON. Josh is happy and all versions of the flying-sphinx gem are happy.

The one caveat with all of this? While it works for me, and it suits Flying Sphinx, it’s not the One True Way for API development. We had a great discussion at the most recent Rails Camp up at Lake Ainsworth about different approaches – at the end of the day, it really comes down to the complexity of your API and who it will be used by.

10 Sep 2011

Speaking at RubyC

Just a quick note for anyone in or near Eastern Europe – I’ll be heading over to Kiev for RubyC in November. I’m going to be speaking there about how to build gems and the best practices when doing so.

RubyC

So, if that interests you (or you’d just like to catch up or hear some of the other speakers talk about interesting Ruby-related topics), then hopefully I’ll see you there!

RssSubscribe to the RSS feed

Recent Links

Recent Posts

Tag Density

About Freelancing Gods

Freelancing Gods is written by , who works on the web as a web developer in Melbourne, Australia, specialising in Ruby on Rails.

In case you're wondering what the likely content here will be about (besides code), keep in mind that Pat is passionate about the internet, music, politics, comedy, bringing people together, and making a difference. And pancakes.

His ego isn't as bad as you may think. Honest.

Here's more than you ever wanted to know.

Ruby on Rails Projects

Other Sites

Creative Commons Logo All original content on this site is available through a Creative Commons by-nc-sa licence.