Commit, Recover & Transactions in Ruby
The spec says 'transactions', we immediately think 'InnoDB'. But what if you're not using a database, working on a light-weight application, or simply want to ensure a graceful recovery process? In the past that usually meant layers of additional logic, variables to keep and capture intermediate state, and all the other associated headaches. That is, until Gregory Brown and Austin Ziegler published Transaction::Simple - a gem, both literally and figuratively, which makes transaction support in Ruby a walk in the park.

Transaction::Simple provides a generic way to inject transaction support into any object - that's right, any Ruby object. All the magic happens directly in memory, and thus there are no dependencies on additional backends. Your only theoretical limit is the memory of your machine, as object versions are created transparently and on the fly. In addition, the gem offers nested transactions, named transactions, transaction groups, commit and recovery procedures. Talk about fully featured! An example is due:
require 'rubygems' require 'transaction/simple' # Create a Ruby hash to store the balance bank = {"Bob" => 100, "Jon" => 50} # Add tranasction support to our Ruby hash bank.extend(Transaction::Simple) bank.start_transaction(:deposit) bank['Bob'] += 25 # -> 125 bank.commit_transaction(:deposit) # block-form usage Transaction::Simple.start(bank) do |t| # v has been extended with Transaction::Simple and an unnamed t.transaction_open? # -> true bank['Bob'] -= 25 # -> 100 # Hmm, I think we made an error, let's abort! t.rewind_transaction t.transaction_open? # -> true bank['Bob'] -= 25 # -> 100 puts "Bob's balance: #{bank['Bob']}, expecting: 100" # Break out of the transaction block and abort the transaction t.abort_transaction end puts "Bob's balance: #{bank['Bob']}, expecting: 125" # -> Bob's balance: 100, expecting: 100 # -> Bob's balance: 125, expecting: 125
Advanced Commit and Recovery
Applying similar patterns as we saw above, we can greatly simplify our recovery procedures in almost any Ruby program with minimal intervention:
# applying to arbitrary objects obj = SomeObject.new obj.extend(Transaction::Simple) # Recover, rewind, and retry use-case begin v.start_transaction if v.do_work v.commit_transaction else v.abort_transaction rescue Exception v.rewind_transaction v.recover retry end
And as if this is not enough, make sure to explore transaction groups once you dive into the documentation. Named transactions, in conjunction with transaction groups will allow you to easily manage a group of objects as if they were a single object. Man, I love Ruby. What is your (most recent) favorite gem?
About this entry
- Published:
- 21.01.08 / 10am
- Category:
- Ruby
- Tagged:
- gem, library, Ruby, transactions
Related Posts
- 10.10 Hands on MySQL Backup & Migration
- 07.09 Validating URL/URI in Ruby on Rails
- 19.06 Splunk Your Distributed Logs in EC2
- 07.11 Monit makes Mongrel play nice!
- 27.04 Web Security With Ingress Filtering

















Entries RSS
13 Comments
comments rss | trackback uri