MA5: Offline-first sync: outboxes, retries and conflicts
Sending each change once
🎯You'll be able to
Send outbox changes in order, use idempotency keys so a repeated send is stored once, and start syncing when the connection returns.
🏠The everyday picture
A shopkeeper gives a numbered receipt for each payment. If a customer comes back saying "did my payment go through?", the shopkeeper checks the number instead of taking the money again.
📘What it really is
- In order: send the oldest change first, and stop if it fails, so later changes to the same visit don't arrive before earlier ones.
-
Lost answers happen: the server may store a change and the answer may never reach the phone. The phone can't tell this apart from a change that never arrived, so it sends again.
-
Idempotency keys: each change carries a unique key (its change ID) in a header. The server remembers keys and returns the first answer for a repeat, without storing the change twice.
-
When to sync: after each save, when the connection comes back (NetInfo tells the app), and every so often while the app is open.
- Base versions: each change says which version of the visit it was made on, so the server can spot conflicts (Lesson 5).
📝A worked example
Input: KhetNote's test 5: the server stores a visit, then the answer is lost.
Steps:
- The first send fails with a network error, so the change stays in the outbox with one attempt recorded.
- The next sync sends it again with the same
Idempotency-Key. - The server finds the key, returns the stored answer, and doesn't write again; the phone removes the change.
Expected output: one copy of the visit on the server, and an empty outbox.
🌍Where it's used
- Payment APIs use idempotency keys so a retried payment isn't charged twice.
- Messaging uses message IDs so a resent message appears once.
- Order systems use them for orders placed on weak connections.
📝Case scenario
A delivery app retried "mark delivered" after timeouts, without keys. Some deliveries were recorded three times, and drivers were paid for them. Adding a key per change, kept by the server for a few days, ended the duplicates.
🖱️Try it
In server/logic.js, find where the server remembers keys. Explain what it returns for a repeated key. Success: you can name the map and
the line that returns the stored answer.
⚠️Common mistakes
- A new key on each retry. Sign: duplicates continue. Fix: the key belongs to the change, not the attempt.
- Sending out of order. Sign: an older change overwrites a newer one. Fix: oldest first, stop on failure.
- Syncing only when the app starts. Sign: changes wait for hours. Fix: also sync when the connection returns.
🛠️For your project
Project 1's tests 4 and 5 check syncing on reconnect and one copy after a lost answer.
✅Quick check
Why can't the phone tell whether a timed-out change was stored?
Show the answer
The server may have stored it and the answer been lost on the way back.
What does the server do when it sees an idempotency key it already knows?
Show the answer
It returns the first answer and doesn't store the change again.
