La Previa Restobar is designed to keep working even when the restaurant’s Wi-Fi is unreliable. Every write — whether a new order, a table status change, or a stock update — lands in the local Room database first. When the device reconnects to the network, WorkManager wakes upDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/luisumit/LaPreviaRestobar/llms.txt
Use this file to discover all available pages before exploring further.
SyncWorker, which hands control to SyncManager to push all pending records to Firebase Realtime Database.
The Offline-First Pattern
syncStatus Field
Orders, tables, and inventory items all carry a syncStatus string column in their Room entity:
| Value | Meaning |
|---|---|
"PENDING" | Local change exists that has not yet been pushed to Firebase |
"SYNCED" | Local and remote records are in agreement |
"PENDING" for newly created or locally modified records, and is set to "SYNCED" by SyncManager after a successful Firebase write.
Table records default to "SYNCED" because the initial table list is downloaded from Firebase on first launch. Only tables modified offline (e.g. status change without network) flip to "PENDING".SyncWorker
SyncWorker is a HiltWorker that runs on the IO dispatcher and delegates all sync logic to SyncManager.
WorkManager Constraints
NETWORK_TYPE_CONNECTED ensures the worker only runs when a network interface is active. REQUIRES_BATTERY_NOT_LOW prevents sync tasks from draining a dying device.Retry with back-off
If
doWork() throws, WorkManager retries up to 3 times with BackoffPolicy.EXPONENTIAL starting at a 15-minute interval. After 3 failures, Result.failure() is returned and the work is discarded from the queue.Periodic + immediate
schedule() registers a recurring hourly task. scheduleImmediate() enqueues a one-time task — called when the app detects connectivity restored after a period offline.KEEP policy
ExistingPeriodicWorkPolicy.KEEP prevents duplicate workers accumulating if the app is launched multiple times or the scheduler is called again after a crash.SyncManager
SyncManager is the @Singleton that knows how to read each Room DAO’s pending queue and push records to the corresponding Firebase repository.
Upload Flow (pending local → Firebase)
syncTables), inventory (syncInventory), and products (syncProducts). Each method reads getPending(), pushes each record, and marks it "SYNCED" on success. A failure in one record does not block the rest — the try/catch is per-record, not per-batch.
Download Flow (Firebase → local Room)
updatedAt is strictly greater than the local updatedAt. This prevents a stale Firebase push from silently reverting a more recent offline edit.
Sync Modes
| Method | What it does | Timeout |
|---|---|---|
syncLight() | Uploads pending orders only | 15 s |
uploadAll() | Uploads orders + tables + inventory + products | 30 s |
downloadAll() | Downloads all entity types from Firebase | 30 s |
syncFull() | uploadAll() then downloadAll() | 60 s |
syncLight() is used by SyncWorker for routine background sync to minimize battery and data usage. The full sync variants are called explicitly after login or when a manual refresh is triggered.
Timestamp-Based Conflict Resolution
Every entity that participates in offline sync carries at least anupdatedAt (domain model) and a lastModified (Room entity) timestamp. The conflict resolution rule is simple:
The record with the higher updatedAt timestamp wins.
This means:
- If a waiter updates an order’s status while offline, that change has a newer
updatedAtthan the Firebase copy. - When sync runs,
downloadOrders()skips overwriting the local record becauseremoteOrder.updatedAtis older. - If two devices edit the same record simultaneously, the last write (highest timestamp) prevails after both sync.
updateStatusIfNewer query:
WHERE version < :newVersion clause is a database-level guard: even if application code passes an outdated version number, the SQL statement will silently no-op rather than overwrite a newer record.
Network Connectivity Detection
RealTimeWebSocketClient uses Android’s ConnectivityManager to check for an active network before attempting a WebSocket connection:
WebSocketEvent.Error and schedules a reconnection attempt with exponential back-off (maximum delay: 30 seconds).