The Accelerate HR Blog
Rails for the Enterprise: the Uninterruptible Application Supply (Mon Dec 24 2007)
The web can be a fragile and capricious animal. And, as I reported in my last post, there may be reason to fear more breakages and slowdowns than ever in the coming years. Which presents us with a problem if we're trying to persuade clients that they should entrust their business-critical information to our shiny new web-based enterprise software releases. If and when the web breaks, we need to be able to provide a fail-safe back-up service.
It's just like covering the risk of a power failure. If the mains power fails on your laptop, it switches over to battery power automatically. For the home user, this is probably good enough. If fully charged, the battery's going to give you two of three hours of life - probably enough till mains power is restored. But for many business users, this doesn't cut it. Not if you're a bank, and you need your computer systems to be 100% reliable all the time. Their risk management plan will call for a back-up power system - a generator perhaps. And in case there's damage to the building, they may have other contingency plans - a mirror site in another location for their key data, for instance.
Businesses that think this way would never dream of committing to a web-based system that had no plan for web failure. So how can we assure them of an Uninterruptible Application Supply?
These, I think, are the requirements:
1. If the Web fails - or at any time the user determines - it should be possible to move to an off-line version of the application.
2. All the client's current data should be available in the off-line version.
3. Both the data and the off-line application should remain fully secured.
4. Users should be able to use the application normally, both to read and to write data.
5. When a user goes back online, all changes made offline should be automatically synchronized with the master database, retaining the integrity of all data relationships.
6. If the client chooses to stay off-line, this should be possible. However if the online application is updated, it should be possible for the client to pull the latest modifications into the off-line version.
7. It should not be necessary to rewrite the application for all this to work.
What we're looking for essentially, is a hybrid web / desktop application with seamless, transparent switching between the two modes.
For those of us who use the Ruby on Rails framework, the good news is that most of the elements are already in place or available:
A. Many Rails programmers use Subversion as a version-control repository for their applications. The core use for Subversion is to allow teams of programmers to work on an application simultaneously. Changes are made in a branch of the application, and when the changes have been accepted they're committed to the trunk. Subversion makes it easy to roll back to a previous version if necessary. But it's also possible to use Subversion simply to transfer an application - or part of an application - to a third party. In fact that's how many Rails plugins are distributed today. So, first we'd get our clients to download a security version of the application, using Subversion.
The client would also need to install a local version of Rails and Ruby and a MySql (or other) database. For Windows users that's pretty straightforward, using Instant Rails. And Mac's OS X Leopard gives you everything you need in one bundle too. Best of all, it's all open source and free.
With Subversion, clients would also be able to upgrade to the latest version in 'trunk' at any time, fulfilling requirement 6.
B. In Rails we work with slightly different configurations depending on whether we're in development or production mode, and normally three different databases - for development, testing and production. Changing the configuration and the database connection is trivial.
I'm proposing that another mode should be added - an offline mode. I need advice on this but I'd see the configuration being the same as the production mode, but with connection to a password-protected, client-specific database - the one that we asked the client to install above, with a default name - let's call it 'offline'.
C. The application would need to track the last update made to a client's data while online.
D. It's common practice to include the fields created_at (or _on) and updated_at in our data models. These would be essential throughout the offline database, so that any changes made since the last online update can be detected when the client goes back online. I envisage the offline capability as a plugin. One of the plugin's tasks would be to check each model for the existence of these two fields and add them to the offline database where necessary.
Both these field are timestamped, so changes are automatically logged.
E. Whenever the user goes back online, the application automatically checks the offline version for changes since the last time online, and appends them to the master database.
There are two steps involved. First new fields are appended, and as ever, their ids will be generated automatically in the master database. Secondly, any foreign fields in the changed records will need to be relinked to their equivalents in the master database. This is tricky, but not as much as it might be because of the Rails injunction 'Convention over configuration'. It'll be easy to identify the fields with the _id affix and the belongs to / has many (one) references in the model. Thirdly, any remaining fields in the changed records need to be updated in the master database.
All this needs to be transparent to the user, running in the background as a rake task in the plugin.
F. This covers all the bases ... except one. How do we make sure that the client's offline database contains the latest data? In my application, an HR database, entries are not especially time-critical. For our purposes, it's probably enough for a daily back-up of the master database. Then on demand from the client, a rake task could extrapolate all the latest client-related data and import it into the offline database. But we'd need to be careful with this, setting up validation to ensure that records already changed in the offline database weren't overwritten by the import from the master database.
I'm aware that Joyent's Slingshot already claims to offer dual online / offline functionality for Rails applications. This may or may not provide the solution I'm looking for. The Slingshot demo doesn't leave me feeling too optimistic - it seems developer- rather than user-oriented: I'd like to see the minimum amount of work for the developer, and the same application interface for the user.
There are also issues raised by critics of Slingshot that we need to address. If the developer provides the application source to the user, how is intellectual property safeguarded?
This is a blueprint, and it needs your comments and criticism. If the concept excites you and you think you could have a role to play as a contributor, do contact me at alan_miles@ajobwelldone.info with your thoughts.
Postscript:
Just as I was about to post this, I came across this great article on the Invisible Blog, reinforcing my reservations about Slingshot and pointing out other issues that we'll need to address: including globally unique IDs, taking care of time-zone differences, out-of-sync clocks between servers and local clients, tracking deletions.... It seems that Lotus Notes, while dealing with atomic rather than relational data, overcame most of these issues successfully.