Martyn Loughran

Scraps of life…
Islington, London
Cell 07966632396

Tumblr

Roaming calls swindle continues...

Since the EU regulations on roaming charges within Europe came into force, I’ve been pleased to receive a handy little text from O2 whenever I enter a new country:

Calls to the UK & the EU cost 35ppm and 18pmm to receive (inc VAT). Further info on freephone 2266. Voicemail works as it does in the UK.

Nice, but they don’t tell you one very important thing: While incoming calls are metered by the second, outgoing ones are rounded up to the next minute! I don’t much like spending 35p to hear “This is the voicemail service… [hangup]”. And it’s not much better when you took 10 seconds to say “Where are you? OK. I’ll be there in 5.”

The current regulations agreed in 2007 are due to expire in 2010, but a proposal to extend them in an amended form are currently in progress. While I’m pleased that the call costs are being reduced slightly year on year (although I wonder whether competition is being stifled), these proposals are much more useful:

  • Per second billing
  • Caps on data usage

Unfortunately the data cap is only for wholesale rates between operators, and starting at €1 / MB excluding VAT this June is still outrageously expensive. By June 2011 it will be reduced to €0.50, but that’s another two years, by which point we will all be even hungrier for data. The other proposal is for a cut off limit so that you at least know that the charges will be within some bounds. Useful, if only because the charges are still so steep.

Let’s hope that this goes though, but also that competition kicks in and we see some more competitive deals, especially for data roaming.

See these links from the European Parliament for more information:

more…

New Bamboo

APICache

You want to use the Twitter API but you don’t want to die? I have the solution to API caching:

APICache.get("http://twitter.com/statuses/public_timeline.rss")

You get the following functionality for free:

  • New data every 10 minutes
  • If the twitter API dies then keep using the last data received for a day. Then assume it’s invalid and announce that Twitter has FAILED (optional).
  • Don’t hit the rate limit (70 requests per 60 minutes)

So what exactly does APICache do? Given cached data less than 10 minutes old, it returns that. Otherwise, assuming it didn’t try to request the URL within the last minute (to avoid the rate limit), it makes a get request to the Twitter API. If the Twitter API timeouts or doesn’t return a 2xx code (very likely) we’re still fine: it just returns the last data fetched (as long as it’s less than a day old). In the exceptional case that all is lost and no data can be returned, it raises an APICache::NotAvailableError exception. You’re responsible for catching this exception and complaining bitterly to the internet.

All very simple. What if you need to do something more complicated? Say you need authentication or the silly API you’re using doesn’t follow a nice convention of returning 2xx for success. Then you need a block:

APICache.get('twitter_replies', :cache => 3600) do
  Net::HTTP.start('twitter.com') do |http|
    req = Net::HTTP::Get.new('/statuses/replies.xml')
    req.basic_auth 'username', 'password'
    response = http.request(req)
    case response
    when Net::HTTPSuccess
      # 2xx response code
      response.body
    else
      raise APICache::Invalid
    end
  end
end

All the caching is still handled for you. If you supply a block then the first argument to APICache.get is assumed to be a unique key rather than a URL. Throwing APICache::Invalid signals to APICache that the request was not successful.

You can send any of the following options to APICache.get(url, options = {}, &block). These are the default values (times are all in seconds):

{
  :cache => 600,    # 10 minutes  After this time fetch new data
  :valid => 86400,  # 1 day       Maximum time to use old data
                    #             :forever is a valid option
  :period => 60,    # 1 minute    Maximum frequency to call API
  :timeout => 5     # 5 seconds   API response timeout
}

Before using the APICache you need to initialize the caches. In merb, for example, put this in your init.rb:

APICache.start

Currently there are two stores available: MemcacheStore and MemoryStore. MemcacheStore is the default but if you’d like to use MemoryStore, or another store - see AbstractStore, just supply it to the start method:

APICache.start(APICache::MemoryStore)

I suppose you’ll want to get your hands on this magic. For now just grab the source from http://github.com/mloughran/api_cache/tree/master and rake install. I’ll get a gem sorted soon.

This is the irb quickstart so that you don’t have to re-parse the above:

require 'rubygems'
require 'api_cache'
APICache.start(APICache::MemoryStore)
APICache.get("http://twitter.com/statuses/public_timeline.rss")

Please send feedback if you think of any other functionality that would be handy.

Nested layouts in Merb

First a simple solution using throw_content and catch_content. more…

Freeze gems in a Merb application

Frozen gems in Merb == gems installed inside the application. more…

How to use git / github with capistrano

I’m assuming that you’re using private key authentication for git and that you’ve got an ssh agent set up (if you’re running Leopard then you automatically have this). more…

more…

You