Skip to content
This repository was archived by the owner on Mar 28, 2019. It is now read-only.

Client phases

Stefan Arentz edited this page Feb 5, 2015 · 6 revisions

This document summarizes in brief the proposed operation of the Android reading list client.

Local data storage requirements

Each local record is required to store the server GUID (if known), the server modification time (if known), and a three-state flag: no local changes, status-only changes, and significant changes.

A status-only change is one that can be automatically reconciled by the server: e.g., marking a record as read.

It is likely that we'll optimize either status-only or all changes by constructing and storing the PATCH body at the time of the change.

Phase One: upload status-only changes

For all local status-only changes (i.e., changes that can be reconciled on the server with no possibility of conflicts), upload them and apply resultant changes (deletions, etc.)

By definition, any material changes downloaded from the server will apply without conflicts to the local record, so this phase should always proceed without issue.

Do not advance the global server timestamp. Do advance individual record timestamps.

Phase One is cheap, incremental, and independent (each record can be applied individually). It's expected that clients will do partial Phase One syncs as records change locally.

Phase One, Part Two: upload new records

We can also upload new records at this point. Conflicts during upload should always be simple to resolve; the new local item is typically replaced by an existing item.

What are possible conflicts? How do those occur? (What user actions can generate conflicts?)

Phase Two: do an incremental fetch of server-side changes

Make a fetch for records since the the Last-Modified header from the last completed Phase Two. We should expect to receive records that we uploaded in Phase One (see Issue #68).

  • If no results, we're done here:

    • Advance server timestamp.
    • Proceed to Phase Three.
  • If we get results, then for each record:

    • If we have a record locally with that GUID:
      • If the local record timestamp and the server record timestamp match, this is a downloaded dupe; ignore it.
      • If not, then apply changes.
        • If the local record has any material changes, reconcile conflicts and mark the record for upload.
        • If the local record has only status changes, reconcile and mark for upload. (This should not occur, because status changes should be uploaded early and reconciled on the server.)
    • If we have no record locally with that GUID:
      • If we have a record with no GUID but with fields that match (e.g., same URL), reconcile that record. Note that if Phase One Part Two is used, there will be no such records.
      • If we don't, insert the remote record.

Advance the server timestamp.

What is the server timestamp? Is this stored locally? Is it simply the last modified of the most recently changed record?

Phase Three: upload new records and substantial changes

  • For each local record marked for upload:
    • Upload the record. See also Phase One Part Two.
    • If a conflict occurs, reconcile the conflict and mark the record for upload.
    • Otherwise, mark the record as uploaded.
  • Repeat until there are no conflicts to upload. Phases Two and Three can result in a local record state that's a merge of local and remote data (after a conflict), waiting to be uploaded to the server. Rather than interleaving uploads into the download processing, we re-mark these records for upload, and repeatedly apply Phase Three until all uploads have succeeded.