Adobe AIR: Synchronizing SQLite Databases With The Server
One of the most common tasks and questions that I believe has come of the Adobe AIR (formerly Apollo) runtime is how to synchronize a SQLite database and server database for offline access. Adobe has left a glaring hole in AIR with a lack of a synchronization strategy, and this will surely be a place where a lot of users write a lot of code, and maybe a few component developers will find a nice cash crop. There are lots of things to consider when writing a sync engine for the first time, and there are several ways to go about it. My current project (not related to Lab49) involved building a way to synchronize data across AIR and Microsoft SQL Server. I will explain, in brief, how one can accomplish this here. I will not be releasing the code for the synchronization engine, so please don't ask. And unless you want to license it for a considerable sum, I will not be releasing the binaries either. This is a large piece of intellectual property with a vast amount of R&D placed into it. Keep in mind that there is no "flip of a switch" solution. This is not an easy problem to solve, and will take you a considerable amount of time to do properly. When developing a sync engine, there are four major components you will have to consider: 1. Server side database 2. Client side database (generally same schema) 3. Server side endpoint (WSDL/Web Service or REST service/JSON service) 4. Client side API to the server endpoint When developing your database, you have a few options. There are two types of synchronization you can choose from, row-based and field-based synchronization. I will discuss both briefly below: Row-based Synchronization: This is the easiest to implement. To do this, you will throw a DateUpdated field (that you will hold in UTC) on each row in the database. In addition, you will hold your LastSyncDate in a separate table. When you want to sync, you will do the following: 1. Read the LastSyncDate 2. Go through your tables (in the proper order to avoid breaking foreign key constraints) and find rows where DateUpdated > LastSyncDate 3. Send the rows up to your server, along with the LastSyncDate using your client side API 4. The server will select all things on its side where DateUpdated > LastSyncDate . 5. If there are any conflicts (rows that changed on both the server and client), the server will need to send the row back down for conflict resolution. a. You will need an algorithm or UI to allow a user to choose which version of the row he wanted. The most simple algorithm is to take the newest, but this could result in data loss. 6. The server either inserts or updates rows into the SQL Server on its side and sends back the rows that its seen change since LastSyncDate 7. The client either inserts or updates rows into its local SQLite store. While row based synchronization is easy and will work, it is also a very manual process to configure, hard to fix when schema changes occur, and prone to conflicts and therefore data loss. Field-based Synchronization: The other (better) option is field based synchronization. Anyone building an enterprise app will be interested in pursuing this approach. To properly do field-based sync, you will need a transaction log that holds a history of the changes made on a field-by-field level. This is not a trivial task, but allows the same record to be updated in different places and sync smoothly. In general, no user UI to choose a version is needed because the chances of overlap are so small, you can generally just assume that "newest is best". To implement this pattern, you will need to hold a transaction log, much like any SQL Server does internally. The log will hold your changes, and you will sync and "replay" the log on either side to keep both databases in sync. Because I don't want to give out too much of my intellectual property (at least until I release my first version of my application), I am going to end the field-based sync discussion here. I hope that this gives you some general ideas on how to properly implement sync between your two databases. Regardless of the types of databases you are syncing, the general guidelines will be the same. Keep in mind, in the ActionScript world, you will want to do this all asynchronously, as you don't want to freeze up your application while you are syncing. This adds a tremendous technical burden due to the constraints of the ActionScript threading model. Good luck!

