@@ -7,6 +7,7 @@ import androidx.core.app.NotificationCompat
7
7
import androidx.core.app.NotificationManagerCompat
8
8
import androidx.work.CoroutineWorker
9
9
import androidx.work.WorkerParameters
10
+ import com.google.gson.Gson
10
11
import com.mapbox.mapboxsdk.plugins.localization.BuildConfig
11
12
import dagger.android.ContributesAndroidInjector
12
13
import fr.free.nrw.commons.CommonsApplication
@@ -146,61 +147,60 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
146
147
CommonsApplication .NOTIFICATION_CHANNEL_ID_ALL
147
148
)!!
148
149
withContext(Dispatchers .IO ) {
149
- // Doing this so that retry requests do not create new work requests and while a work is
150
- // already running, all the requests should go through this, so kind of a queue
151
- while (contributionDao.getContribution(statesToProcess)
152
- .blockingGet().isNotEmpty()
153
- ) {
154
- val queuedContributions = contributionDao.getContribution(statesToProcess)
155
- .blockingGet()
156
- // Showing initial notification for the number of uploads being processed
157
-
158
- processingUploads.setContentTitle(appContext.getString(R .string.starting_uploads))
159
- processingUploads.setContentText(
160
- appContext.resources.getQuantityString(
161
- R .plurals.starting_multiple_uploads,
162
- queuedContributions.size,
163
- queuedContributions.size
164
- )
150
+ val queuedContributions = contributionDao.getContribution(statesToProcess)
151
+ .blockingGet()
152
+ // Showing initial notification for the number of uploads being processed
153
+
154
+ Timber .e(" Queued Contributions: " + queuedContributions.size)
155
+
156
+ processingUploads.setContentTitle(appContext.getString(R .string.starting_uploads))
157
+ processingUploads.setContentText(
158
+ appContext.resources.getQuantityString(
159
+ R .plurals.starting_multiple_uploads,
160
+ queuedContributions.size,
161
+ queuedContributions.size
165
162
)
166
- notificationManager?.notify(
167
- PROCESSING_UPLOADS_NOTIFICATION_TAG ,
168
- PROCESSING_UPLOADS_NOTIFICATION_ID ,
169
- processingUploads.build()
170
- )
171
-
172
- queuedContributions.asFlow().map { contribution ->
173
- /* *
174
- * If the limited connection mode is on, lets iterate through the queued
175
- * contributions
176
- * and set the state as STATE_QUEUED_LIMITED_CONNECTION_MODE ,
177
- * otherwise proceed with the upload
178
- */
179
- if (isLimitedConnectionModeEnabled()){
180
- if (contribution.state == Contribution .STATE_QUEUED ) {
181
- contribution.state = Contribution .STATE_QUEUED_LIMITED_CONNECTION_MODE
182
- contributionDao.save(contribution)
183
- }
184
- } else {
185
- contribution.transferred = 0
186
- contribution.state = Contribution .STATE_IN_PROGRESS
187
- contributionDao.save(contribution)
188
- uploadContribution(contribution = contribution)
189
- }
190
- }.collect()
163
+ )
164
+ notificationManager?.notify(
165
+ PROCESSING_UPLOADS_NOTIFICATION_TAG ,
166
+ PROCESSING_UPLOADS_NOTIFICATION_ID ,
167
+ processingUploads.build()
168
+ )
191
169
192
- // Dismiss the global notification
193
- notificationManager?.cancel(
194
- PROCESSING_UPLOADS_NOTIFICATION_TAG ,
195
- PROCESSING_UPLOADS_NOTIFICATION_ID
196
- )
170
+ /* *
171
+ * To avoid race condition when multiple of these workers are working, assign this state
172
+ so that the next one does not process these contribution again
173
+ */
174
+ queuedContributions.forEach {
175
+ it.state= Contribution .STATE_IN_PROGRESS
176
+ contributionDao.saveSynchronous(it)
177
+ }
197
178
198
- // No need to keep looking if the limited connection mode is on,
199
- // If the user toggles it, the work manager will be started again
200
- if (isLimitedConnectionModeEnabled()){
201
- break ;
179
+ queuedContributions.asFlow().map { contribution ->
180
+ /* *
181
+ * If the limited connection mode is on, lets iterate through the queued
182
+ * contributions
183
+ * and set the state as STATE_QUEUED_LIMITED_CONNECTION_MODE ,
184
+ * otherwise proceed with the upload
185
+ */
186
+ if (isLimitedConnectionModeEnabled()) {
187
+ if (contribution.state == Contribution .STATE_QUEUED ) {
188
+ contribution.state = Contribution .STATE_QUEUED_LIMITED_CONNECTION_MODE
189
+ contributionDao.saveSynchronous(contribution)
190
+ }
191
+ } else {
192
+ contribution.transferred = 0
193
+ contribution.state = Contribution .STATE_IN_PROGRESS
194
+ contributionDao.saveSynchronous(contribution)
195
+ uploadContribution(contribution = contribution)
202
196
}
203
- }
197
+ }.collect()
198
+
199
+ // Dismiss the global notification
200
+ notificationManager?.cancel(
201
+ PROCESSING_UPLOADS_NOTIFICATION_TAG ,
202
+ PROCESSING_UPLOADS_NOTIFICATION_ID
203
+ )
204
204
}
205
205
// TODO make this smart, think of handling retries in the future
206
206
return Result .success()
@@ -307,6 +307,7 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
307
307
Timber .e(exception)
308
308
Timber .e(" Upload from stash failed for contribution : $filename " )
309
309
showFailedNotification(contribution)
310
+ contribution.state= Contribution .STATE_FAILED
310
311
if (STASH_ERROR_CODES .contains(exception.message)) {
311
312
clearChunks(contribution)
312
313
}
@@ -315,26 +316,28 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
315
316
StashUploadState .PAUSED -> {
316
317
showPausedNotification(contribution)
317
318
contribution.state = Contribution .STATE_PAUSED
318
- contributionDao.save (contribution).blockingGet( )
319
+ contributionDao.saveSynchronous (contribution)
319
320
}
320
321
else -> {
321
322
Timber .e(""" upload file to stash failed with status: ${stashUploadResult.state} """ )
322
323
showFailedNotification(contribution)
323
324
contribution.state = Contribution .STATE_FAILED
324
325
contribution.chunkInfo = null
325
- contributionDao.save (contribution).blockingAwait( )
326
+ contributionDao.saveSynchronous (contribution)
326
327
}
327
328
}
328
329
}catch (exception: Exception ){
329
330
Timber .e(exception)
330
331
Timber .e(" Stash upload failed for contribution: $filename " )
331
332
showFailedNotification(contribution)
333
+ contribution.state= Contribution .STATE_FAILED
334
+ clearChunks(contribution)
332
335
}
333
336
}
334
337
335
338
private fun clearChunks (contribution : Contribution ) {
336
339
contribution.chunkInfo= null
337
- contributionDao.save (contribution).blockingAwait( )
340
+ contributionDao.saveSynchronous (contribution)
338
341
}
339
342
340
343
/* *
0 commit comments