Eventual Consistency, or things will all work out…eventually
So we’re working with Amazon’s SimpleDB. It’s pretty sweet, though the ruby libraries for it are still a bit primitive. One of the problems you run up against when you’re writing integration tests against it is eventual consistency.
Take this test :
it "should save" do customer = Customer.create!(:name => 'bob', :email => 'bob@example.com') customer = Customer.find(customer.key) customer.name.should == 'bob' end
The way SimpleDB works, you’re assured that Customer.find will work…eventually, but not right away.
For a couple days we contented ourselves to just run the integration tests a couple times until they didn’t error out. But that got old.
Enter “eventually” :
it "should save" do customer = Customer.create!(:name => 'bob', :email => 'bob@example.com') customer = eventually { Customer.find(customer.key) } customer.name.should == 'bob' end
It’s a very simple method (below) that just retries the passed in block until it succeeds, timing out after 10 tries. Super simple, works like a charm. Thank you ruby.
Here’s the source :
def eventually(tries = 0, &block) yield rescue raise if tries >= 10 sleep 0.5 eventually(tries + 1, &block) end
I will say, I can’t help but smile every time I write “eventually” in a test…