commit fbfe0c2566f35b8599da2dddcaffbdf0f96cf70d Author: Fabio Mazza Date: Wed Apr 10 22:36:52 2024 +0200 Avoid non-stop request of trip data that simply fails to download diff --git a/app/src/main/java/it/reyboz/bustorino/data/MatoTripsDownloadWorker.kt b/app/src/main/java/it/reyboz/bustorino/data/MatoTripsDownloadWorker.kt index 5e391ef..0f03a28 100644 --- a/app/src/main/java/it/reyboz/bustorino/data/MatoTripsDownloadWorker.kt +++ b/app/src/main/java/it/reyboz/bustorino/data/MatoTripsDownloadWorker.kt @@ -82,15 +82,20 @@ class MatoTripsDownloadWorker(appContext: Context, workerParams: WorkerParameter } requestCountDown.await() val tripsIDsCompleted = downloadedMatoTrips.map { trip-> trip.tripID } - val doInsert = (queriedMatoTrips subtract failedMatoTripsDownload).containsAll(tripsIDsCompleted) - Log.i(DEBUG_TAG, "Inserting missing GtfsTrips in the database, should insert $doInsert") - if(doInsert){ + if (tripsIDsCompleted.isEmpty()){ + Log.d(DEBUG_TAG, "No trips have been downloaded, set work to fail") + return Result.failure() + } else { + val doInsert = (queriedMatoTrips subtract failedMatoTripsDownload).containsAll(tripsIDsCompleted) + Log.i(DEBUG_TAG, "Inserting missing GtfsTrips in the database, should insert $doInsert") + if (doInsert) { - gtfsRepository.gtfsDao.insertTrips(downloadedMatoTrips) + gtfsRepository.gtfsDao.insertTrips(downloadedMatoTrips) - } + } - return Result.success() + return Result.success() + } } override suspend fun getForegroundInfo(): ForegroundInfo { val notificationManager = @@ -109,8 +114,8 @@ class MatoTripsDownloadWorker(appContext: Context, workerParams: WorkerParameter const val TAG_TRIPS ="gtfsTripsDownload" - fun downloadTripsFromMato(trips: List, context: Context, debugTag: String): Boolean{ - if (trips.isEmpty()) return false + fun requestMatoTripsDownload(trips: List, context: Context, debugTag: String): OneTimeWorkRequest? { + if (trips.isEmpty()) return null val workManager = WorkManager.getInstance(context) val info = workManager.getWorkInfosForUniqueWork(TAG_TRIPS).get() @@ -128,8 +133,8 @@ class MatoTripsDownloadWorker(appContext: Context, workerParams: WorkerParameter .addTag(TAG_TRIPS) .build() workManager.enqueueUniqueWork(TAG_TRIPS, ExistingWorkPolicy.KEEP, requ) - } - return true + return requ + } else return null; } } } diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/LinesDetailFragment.kt b/app/src/main/java/it/reyboz/bustorino/fragments/LinesDetailFragment.kt index 5a15293..98cf68c 100644 --- a/app/src/main/java/it/reyboz/bustorino/fragments/LinesDetailFragment.kt +++ b/app/src/main/java/it/reyboz/bustorino/fragments/LinesDetailFragment.kt @@ -366,7 +366,7 @@ class LinesDetailFragment() : ScreenBaseFragment() { //download missing tripIDs liveBusViewModel.tripsGtfsIDsToQuery.observe(viewLifecycleOwner){ //gtfsPosViewModel.downloadTripsFromMato(dat); - MatoTripsDownloadWorker.downloadTripsFromMato( + MatoTripsDownloadWorker.requestMatoTripsDownload( it, requireContext().applicationContext, "BusTO-MatoTripDownload" ) diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/MapFragment.java b/app/src/main/java/it/reyboz/bustorino/fragments/MapFragment.java index 0035c62..6e3992e 100644 --- a/app/src/main/java/it/reyboz/bustorino/fragments/MapFragment.java +++ b/app/src/main/java/it/reyboz/bustorino/fragments/MapFragment.java @@ -46,7 +46,6 @@ import androidx.preference.PreferenceManager; import it.reyboz.bustorino.backend.gtfs.LivePositionUpdate; import it.reyboz.bustorino.backend.mato.MQTTMatoClient; import it.reyboz.bustorino.backend.utils; -import it.reyboz.bustorino.data.MatoTripsDownloadWorker; import it.reyboz.bustorino.data.gtfs.MatoPattern; import it.reyboz.bustorino.data.gtfs.TripAndPatternWithStops; import it.reyboz.bustorino.map.*; @@ -374,12 +373,16 @@ public class MapFragment extends ScreenBaseFragment { else livePositionsViewModel.requestGTFSUpdates(); //mapViewModel.testCascade(); + livePositionsViewModel.isLastWorkResultGood().observe(this, d -> + Log.d(DEBUG_TAG, "Last trip download result is "+d)); livePositionsViewModel.getTripsGtfsIDsToQuery().observe(this, dat -> { Log.i(DEBUG_TAG, "Have these trips IDs missing from the DB, to be queried: "+dat); - //gtfsPosViewModel.downloadTripsFromMato(dat); - MatoTripsDownloadWorker.Companion.downloadTripsFromMato(dat, + livePositionsViewModel.downloadTripsFromMato(dat); + /*MatoTripsDownloadWorker.Companion.requestMatoTripsDownload(dat, requireContext().getApplicationContext(), "BusTO-MatoTripDownload"); + + */ }); } /*else if(gtfsPosViewModel!=null){ gtfsPosViewModel.requestUpdates(); diff --git a/app/src/main/java/it/reyboz/bustorino/viewmodels/GtfsPositionsViewModel.kt b/app/src/main/java/it/reyboz/bustorino/viewmodels/GtfsPositionsViewModel.kt index 5b1e26b..aa195cf 100644 --- a/app/src/main/java/it/reyboz/bustorino/viewmodels/GtfsPositionsViewModel.kt +++ b/app/src/main/java/it/reyboz/bustorino/viewmodels/GtfsPositionsViewModel.kt @@ -20,6 +20,7 @@ package it.reyboz.bustorino.viewmodels import android.app.Application import android.util.Log import androidx.lifecycle.* +import androidx.work.OneTimeWorkRequest import com.android.volley.Response import it.reyboz.bustorino.backend.NetworkVolleyManager import it.reyboz.bustorino.backend.gtfs.LivePositionUpdate @@ -166,8 +167,8 @@ class GtfsPositionsViewModel(application: Application): AndroidViewModel(applica Keep in mind that trips DO CHANGE often, and so do the Patterns */ - fun downloadTripsFromMato(trips: List): Boolean{ - return MatoTripsDownloadWorker.downloadTripsFromMato(trips,getApplication(), DEBUG_TI) + fun downloadTripsFromMato(trips: List): OneTimeWorkRequest?{ + return MatoTripsDownloadWorker.requestMatoTripsDownload(trips,getApplication(), "BusTO-MatoTripsDown") } private fun downloadMissingPatterns(routeIds: List): Boolean{ return MatoPatternsDownloadWorker.downloadPatternsForRoutes(routeIds, getApplication()) diff --git a/app/src/main/java/it/reyboz/bustorino/viewmodels/LivePositionsViewModel.kt b/app/src/main/java/it/reyboz/bustorino/viewmodels/LivePositionsViewModel.kt index 53c6e51..27f3df6 100644 --- a/app/src/main/java/it/reyboz/bustorino/viewmodels/LivePositionsViewModel.kt +++ b/app/src/main/java/it/reyboz/bustorino/viewmodels/LivePositionsViewModel.kt @@ -20,6 +20,8 @@ package it.reyboz.bustorino.viewmodels import android.app.Application import android.util.Log import androidx.lifecycle.* +import androidx.work.WorkInfo +import androidx.work.WorkManager import com.android.volley.DefaultRetryPolicy import com.android.volley.Response import it.reyboz.bustorino.backend.NetworkVolleyManager @@ -28,9 +30,14 @@ import it.reyboz.bustorino.backend.gtfs.LivePositionUpdate import it.reyboz.bustorino.backend.mato.MQTTMatoClient import it.reyboz.bustorino.data.GtfsRepository import it.reyboz.bustorino.data.MatoPatternsDownloadWorker +import it.reyboz.bustorino.data.MatoTripsDownloadWorker import it.reyboz.bustorino.data.gtfs.TripAndPatternWithStops import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import java.util.* +import kotlin.collections.ArrayList +import kotlin.collections.HashMap +import kotlin.collections.HashSet class LivePositionsViewModel(application: Application): AndroidViewModel(application) { @@ -49,6 +56,27 @@ class LivePositionsViewModel(application: Application): AndroidViewModel(applica private val gtfsRtRequestRunning = MutableLiveData(false) + private val lastFailedTripsRequest = HashMap() + private val workManager = WorkManager.getInstance(application) + + private var lastRequestedDownloadTrips = MutableLiveData>() + + var isLastWorkResultGood = workManager + .getWorkInfosForUniqueWorkLiveData(MatoTripsDownloadWorker.TAG_TRIPS).map { it -> + if (it.isEmpty()) return@map false + var res = true + if(it[0].state == WorkInfo.State.FAILED){ + val currDate = Date() + res = false + lastRequestedDownloadTrips.value?.let { trips-> + for(tr in trips){ + lastFailedTripsRequest[tr] = currDate + } + } + + } + return@map res + } /** * Responder to the MQTT Client */ @@ -218,8 +246,42 @@ class LivePositionsViewModel(application: Application): AndroidViewModel(applica mqttClient.disconnect() super.onCleared() } + //Request trips download + fun downloadTripsFromMato(trips: List): Boolean{ + if(trips.isEmpty()) + return false + var shouldContinue = false + val currentDateTime = Date().time + + for (tr in trips){ + if (!lastFailedTripsRequest.containsKey(tr)){ + shouldContinue = true + break + } else{ + //Log.i(DEBUG_TI, "Last time the trip has failed is ${lastFailedTripsRequest[tr]}") + if ((lastFailedTripsRequest[tr]!!.time - currentDateTime) > MAX_TIME_RETRY){ + shouldContinue =true + break + } + } + } + if (shouldContinue) { + //if one trip + val workRequ =MatoTripsDownloadWorker.requestMatoTripsDownload(trips, getApplication(), "BusTO-MatoTripsDown") + workRequ?.let { req -> + Log.d(DEBUG_TI, "Enqueueing new work, saving work info") + lastRequestedDownloadTrips.postValue(trips) + //isLastWorkResultGood = + } + } else{ + Log.w(DEBUG_TI, "Requested to fetch data for ${trips.size} trips but they all have failed before in the last $MAX_MINUTES_RETRY mins") + } + return shouldContinue + } companion object{ private const val DEBUG_TI = "BusTO-LivePosViewModel" + private const val MAX_MINUTES_RETRY = 3 + private const val MAX_TIME_RETRY = MAX_MINUTES_RETRY*60*1000 //3 minutes (in milliseconds) } } \ No newline at end of file