Airmail Journal #4

Timestamp Concerns

As stated in my previous post, I'm using update timestamps to provide granular conflict resolution. Every time an object is changed on the device, the timestamp of that change is logged and sent to the server as part of the change. So if two users change the name of a single Envelope before a sync occurs, the server resolves to use the newest of the two names.

As I've discovered to my pain previously: some people don't pay much attention to whether the clock on their device is set correctly, which would cause a lot of problems to this approach for conflict resolution. There are many potential solutions to a problem like this, but I've decided to do something simple.

I'm using Express.js to serve the API, so I've added a middleware step that checks a custom timestamp header on the request. If that header is more than 5 minutes off (or missing) it is considered an error.

function checkClientTimestampHeader(request, response, next) {
    var clientTimestamp = request.headers["x-airmail-client-timestamp"];
    if (!clientTimestamp) {
        // respond with error
    }
    else {
        var currentTimestamp = Math.round(Date.now() / 1000);
        var difference = Math.abs(currentTimestamp - clientTimestamp);
        if (difference > 300) {
            // respond with error
        }
        else {
            next();
        }
    }
}

I intend to have the device modify its timestamps based on the timestamp from the last request made to the server. The logic will be similar: if the device's current time was more than 5 minutes off after the last request, use the difference to adjust timestamps that are being logged. The response error is only for extreme circumstances where something actual goes wrong on the client. Plus, it gives me a chance to use 418 I'm a teapot, because it's hilarious (and I couldn't find anything more suitable but specific enough).

While we're on the subject of timestamps, can everyone just stop using strings to represent dates unless they're being shown to a user? Parsing date strings is a massive performance overhead.