Offline queue, retries & backoff
Every recorded fix goes into a SQLite database on the device before anything is sent. Upload failures never lose a fix by themselves, and they never stop tracking.
The queue
Section titled “The queue”-
One row per record, keyed by its
uuid, oldest first. -
Lives in app storage (on iOS, excluded from backups) and survives app kills, reboots and app updates.
-
Pruned after each insert:
- beyond
persistence.maxRecords(default 10,000), the oldest records are deleted; - records older than
persistence.maxDays(default 7) are deleted.
Both are logged with counts. At a 30 s moving interval, 10,000 records is roughly 80 hours of driving.
- beyond
-
Uploads continue after
stop()until the queue is empty.
const waiting = await LongPing.getQueueCount();const sent = await LongPing.sync(); // upload now; resolves the number of records uploadedawait LongPing.clearQueue(); // delete everything waiting (e.g. on logout)When an upload runs
Section titled “When an upload runs”An upload is triggered when:
- a record is inserted, and
uploadIntervalSecis0or that many seconds have passed since the last attempt; - connectivity comes back;
- you call
sync()orsetAuthorization(); - the 60-second watchdog finds records waiting and the next-attempt time has passed.
Only one upload runs at a time. Each request carries up to maxBatchSize records (or one, with
batch: false), and the run continues until the queue is empty or a request fails. sync() and
setAuthorization() ignore both uploadIntervalSec and backoff.
During an upload the device holds a partial wake lock (Android, 60 s timeout) or a background task (iOS), so the OS doesn’t suspend it mid-request.
Failures
Section titled “Failures”| Response | What happens to the records | When the next try is |
|---|---|---|
| 2xx | Deleted. | Normal pace; backoff resets. |
| 401 / 403 | Kept. | After a token refresh (retried once), or after setAuthorization() / 15 minutes. See Authentication. |
| 413 | Kept. | Immediately, with half the batch (min 1). |
| 408, 429, 5xx, network error, timeout | Kept. | After backoff. |
| Other 4xx | attempts + 1 each; deleted at 3 attempts (logged as dropped). |
The current run ends; records retry on the next trigger. |
Backoff
Section titled “Backoff”delay = min(900, 10 × 2^n) seconds, ±20 % jitter (n = failures in a row so far)So roughly 10 s, 20 s, 40 s, 80 s … capped at 15 minutes. A Retry-After header in seconds wins over the
computed delay (iOS also accepts the HTTP-date form). A 2xx resets the count.
When connectivity returns after a network failure, the device retries right away instead of waiting out the backoff. After a server error (5xx, 429) it waits.
Seeing it happen
Section titled “Seeing it happen”onHttpfires for every attempt with{ status, ok, count, responseText }(status0means a network error;responseTextis the first 2 KB).getState()includesqueueCountandauthorizationRequired.- The on-device log has a line for every request, backoff, pruning and dropped record.