@@ -163,22 +163,32 @@ internal class OperationRepo(
163163 /* *
164164 * Waits until a new operation is enqueued, then wait an additional
165165 * amount of time afterwards, so operations can be grouped/batched.
166+ * NOTE: Any operations that are enqueued while waiting here causes
167+ * the wait timer to restart over. This is intentional, we
168+ * are basically wait for "the dust to settle" / "the water
169+ * is calm" to ensure the app is done making updates.
170+ * FUTURE: Highly recommend not removing this "the dust to settle"
171+ * logic, as it ensures any app stuck in a loop can't
172+ * cause continuous network requests. If the delay is too
173+ * long for legitimate use-cases then allow tweaking the
174+ * opRepoExecutionInterval value or allow commitNow()
175+ * with a budget.
166176 */
167177 private suspend fun waitForNewOperationAndExecutionInterval () {
168178 // 1. Wait for an operation to be enqueued
169179 var wakeMessage = waiter.waitForWake()
170180
171- // 2. Wait at least the time defined in opRepoExecutionInterval
172- // so operations can be grouped, unless one of them used
173- // flush=true (AKA force)
174- var lastTime = _time .currentTimeMillis
181+ // 2. Now wait opRepoExecutionInterval, restart the wait
182+ // time everytime something new is enqueued, to ensure
183+ // the dust has settled.
175184 var remainingTime = _configModelStore .model.opRepoExecutionInterval - wakeMessage.previousWaitedTime
176- while (! wakeMessage.force && remainingTime > 0 ) {
177- withTimeoutOrNull(remainingTime) {
178- wakeMessage = waiter.waitForWake()
179- }
180- remainingTime - = _time .currentTimeMillis - lastTime
181- lastTime = _time .currentTimeMillis
185+ while (! wakeMessage.force) {
186+ val waitedTheFullTime =
187+ withTimeoutOrNull(remainingTime) {
188+ wakeMessage = waiter.waitForWake()
189+ } == null
190+ if (waitedTheFullTime) break
191+ remainingTime = _configModelStore .model.opRepoExecutionInterval
182192 }
183193 }
184194
0 commit comments