How openGym Survives Two Devices at Once
openGym’s ownership model becomes difficult at the exact moment it becomes useful: a person can work on a laptop, continue on a phone, lose the network, and return later without wanting either device to erase the other. This chapter follows what happens when two copies of one profile diverge. The key idea is that synchronization is not a request to pick the newest file. It is a protocol for proving which version a device saw, recovering the current server copy when that proof is stale, and merging records according to what they mean.
From a Read Revision to a Safe Retry
The server-backed profile is treated as a revisioned document. When a device reads the profile, it learns the current server revision. When it later pushes a change, it sends the revision it last saw as its base. That value is a promise: “the state I am about to write descends from this version.” If the server still has that revision, the write can proceed. If another device has written since, the promise is false, and accepting the whole document would risk silently dropping the other device’s work.
openGym therefore refuses the stale write and returns the current document with a conflict response. The refusal is not the end of the operation. It gives the client the state it was missing, so the client can merge its local changes with the server’s newer copy and retry against the revision it has now received. This is more useful than simply returning an error because the server has already supplied the information needed for recovery. The retry is bounded; repeated conflict or network failure leaves the local change marked as owed rather than pretending it reached the shared profile.
The normal path is intentionally cheaper than a full download every time. While the app is open, a signed-in device can ask for the current revision alone. If the revision has not moved, it can keep its existing copy. If it has moved, or if the device returns from the background or comes back online with an owed change, it performs the fuller pull or push path. A phone that has spent an afternoon offline does not need to guess whether the server changed; it can learn that through the revision boundary.
The sequence protects against a particular class of loss: a stale tab that still holds an old whole-profile copy. Without a conditional write, the tab could save its old routines and workouts after a phone had added new work, making the phone’s history disappear from the server even though the tab had made no conscious decision to delete it. The revision check turns that silent overwrite into a visible recovery path.
The client also keeps track of whether its local copy owes the server a change.