Skip to content

Commit 6092a72

Browse files
authored
Merge pull request #17210 from wordpress-mobile/analysis/wordpress-coroutines-warnings
[Compile Warnings As Errors] WordPress Module - Resolve Coroutines Warnings
2 parents 9cf8a97 + 43949f1 commit 6092a72

22 files changed

+82
-108
lines changed

WordPress/src/main/java/org/wordpress/android/models/usecases/LocalCommentCacheUpdateHandler.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.wordpress.android.models.usecases
22

3+
import kotlinx.coroutines.ExperimentalCoroutinesApi
34
import kotlinx.coroutines.flow.merge
45
import org.wordpress.android.models.usecases.LocalCommentCacheUpdateUseCase.PropagateCommentsUpdateAction.UpdatedComments
56
import javax.inject.Inject
@@ -11,6 +12,7 @@ class LocalCommentCacheUpdateHandler @Inject constructor(
1112
) {
1213
private val useCases = listOf(localCommentCacheUpdateUseCase)
1314

15+
@OptIn(ExperimentalCoroutinesApi::class)
1416
fun subscribe() = useCases.map { it.subscribe() }.merge()
1517

1618
suspend fun requestCommentsUpdate() = localCommentCacheUpdateUseCase.manageAction(

WordPress/src/main/java/org/wordpress/android/models/usecases/UnifiedCommentsListHandler.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.wordpress.android.models.usecases
22

3+
import kotlinx.coroutines.ExperimentalCoroutinesApi
34
import kotlinx.coroutines.flow.merge
45
import org.wordpress.android.models.usecases.BatchModerateCommentsUseCase.ModerateCommentsAction.OnModerateComments
56
import org.wordpress.android.models.usecases.BatchModerateCommentsUseCase.Parameters.ModerateCommentsParameters
@@ -21,6 +22,7 @@ class UnifiedCommentsListHandler @Inject constructor(
2122
) {
2223
private val useCases = listOf(paginateCommentsUseCase, batchModerationUseCase, moderationWithUndoUseCase)
2324

25+
@OptIn(ExperimentalCoroutinesApi::class)
2426
fun subscribe() = useCases.map { it.subscribe() }.merge()
2527

2628
suspend fun requestPage(parameters: GetPageParameters) = paginateCommentsUseCase.manageAction(

WordPress/src/main/java/org/wordpress/android/modules/ThreadModule.kt

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,49 +10,34 @@ import kotlinx.coroutines.Dispatchers
1010
import org.wordpress.android.util.helpers.Debouncer
1111
import javax.inject.Named
1212

13-
@Deprecated(message = "Implement CoroutineScope interface and cancel all child coroutines in onCleared/onDestroy/..")
14-
const val UI_SCOPE = "UI_SCOPE"
15-
@Deprecated(message = "Implement CoroutineScope interface and cancel all child coroutines in onCleared/onDestroy/..")
16-
const val DEFAULT_SCOPE = "DEFAULT_SCOPE"
1713
const val APPLICATION_SCOPE = "APPLICATION_SCOPE"
14+
1815
const val UI_THREAD = "UI_THREAD"
1916
const val BG_THREAD = "BG_THREAD"
2017
const val IO_THREAD = "IO_THREAD"
2118

2219
@InstallIn(SingletonComponent::class)
2320
@Module
2421
class ThreadModule {
22+
/* SCOPE */
23+
2524
@Provides
26-
@Named(UI_SCOPE)
27-
fun provideUiScope(): CoroutineScope {
28-
return CoroutineScope(Dispatchers.Main)
25+
@Named(APPLICATION_SCOPE)
26+
fun provideApplicationScope(): CoroutineScope {
27+
return CoroutineScope(Dispatchers.Default)
2928
}
3029

30+
/* DISPATCHER */
31+
3132
@Provides
3233
@Named(UI_THREAD)
3334
fun provideUiDispatcher(): CoroutineDispatcher {
3435
return Dispatchers.Main
3536
}
3637

37-
@Provides
38-
@Named(DEFAULT_SCOPE)
39-
@Deprecated(
40-
message = "CoroutineScope should be provided by an object which implements CoroutineScope",
41-
replaceWith = ReplaceWith("Inject dispatcher and implement CoroutineScope interface")
42-
)
43-
fun provideBackgroundScope(): CoroutineScope {
44-
return CoroutineScope(Dispatchers.Default)
45-
}
46-
47-
@Provides
48-
@Named(APPLICATION_SCOPE)
49-
fun provideApplicationScope(): CoroutineScope {
50-
return CoroutineScope(Dispatchers.Default)
51-
}
52-
5338
@Provides
5439
@Named(BG_THREAD)
55-
fun provideBackgroundDispatcher(): CoroutineDispatcher {
40+
fun provideBgDispatcher(): CoroutineDispatcher {
5641
return Dispatchers.Default
5742
}
5843

@@ -62,6 +47,8 @@ class ThreadModule {
6247
return Dispatchers.IO
6348
}
6449

50+
/* OTHER */
51+
6552
@Provides
6653
fun provideDebouncer(): Debouncer {
6754
return Debouncer()

WordPress/src/main/java/org/wordpress/android/ui/uploads/UploadStarter.kt

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import kotlinx.coroutines.Job
1212
import kotlinx.coroutines.async
1313
import kotlinx.coroutines.coroutineScope
1414
import kotlinx.coroutines.launch
15+
import kotlinx.coroutines.sync.Mutex
1516
import org.wordpress.android.analytics.AnalyticsTracker.Stat
1617
import org.wordpress.android.fluxc.Dispatcher
1718
import org.wordpress.android.fluxc.generated.UploadActionBuilder
@@ -64,6 +65,13 @@ class UploadStarter @Inject constructor(
6465
) : CoroutineScope {
6566
private val job = Job()
6667

68+
/**
69+
* When the app comes to foreground both `queueUploadFromAllSites` and `queueUploadFromSite` are invoked.
70+
* The problem is that they can run in parallel and `uploadServiceFacade.isPostUploadingOrQueued(it)` might return
71+
* out-of-date result and a same post is added twice.
72+
*/
73+
private val mutex = Mutex()
74+
6775
override val coroutineContext: CoroutineContext get() = job + bgDispatcher
6876

6977
/**
@@ -134,44 +142,44 @@ class UploadStarter @Inject constructor(
134142

135143
/**
136144
* This is meant to be used by [checkConnectionAndUpload] only.
137-
*
138-
* The method needs to be synchronized from the following reasons. When the app comes to foreground both
139-
* `queueUploadFromAllSites` and `queueUploadFromSite` are invoked. The problem is that they can run in parallel
140-
* and `uploadServiceFacade.isPostUploadingOrQueued(it)` might return out-of-date result and a same post is added
141-
* twice.
142145
*/
143-
@Synchronized
144146
private suspend fun upload(site: SiteModel) = coroutineScope {
145-
val posts = async { postStore.getPostsWithLocalChanges(site) }
146-
val pages = async { pageStore.getPagesWithLocalChanges(site) }
147-
val list = posts.await() + pages.await()
147+
try {
148+
mutex.lock()
149+
150+
val posts = async { postStore.getPostsWithLocalChanges(site) }
151+
val pages = async { pageStore.getPagesWithLocalChanges(site) }
152+
val list = posts.await() + pages.await()
148153

149-
list.asSequence()
150-
.map { post ->
151-
val action = uploadActionUseCase.getAutoUploadAction(post, site)
152-
Pair(post, action)
153-
}
154-
.filter { (_, action) ->
155-
action != DO_NOTHING
156-
}
157-
.toList()
158-
.forEach { (post, action) ->
159-
trackAutoUploadAction(action, post.status, post.isPage)
160-
AppLog.d(
161-
AppLog.T.POSTS,
162-
"UploadStarter for post (isPage: ${post.isPage}) title: ${post.title}, action: $action"
163-
)
164-
dispatcher.dispatch(
165-
UploadActionBuilder.newIncrementNumberOfAutoUploadAttemptsAction(
166-
post
167-
)
168-
)
169-
uploadServiceFacade.uploadPost(
170-
context = context,
171-
post = post,
172-
trackAnalytics = false
173-
)
174-
}
154+
list.asSequence()
155+
.map { post ->
156+
val action = uploadActionUseCase.getAutoUploadAction(post, site)
157+
Pair(post, action)
158+
}
159+
.filter { (_, action) ->
160+
action != DO_NOTHING
161+
}
162+
.toList()
163+
.forEach { (post, action) ->
164+
trackAutoUploadAction(action, post.status, post.isPage)
165+
AppLog.d(
166+
AppLog.T.POSTS,
167+
"UploadStarter for post (isPage: ${post.isPage}) title: ${post.title}, action: $action"
168+
)
169+
dispatcher.dispatch(
170+
UploadActionBuilder.newIncrementNumberOfAutoUploadAttemptsAction(
171+
post
172+
)
173+
)
174+
uploadServiceFacade.uploadPost(
175+
context = context,
176+
post = post,
177+
trackAnalytics = false
178+
)
179+
}
180+
} finally {
181+
mutex.unlock()
182+
}
175183
}
176184

177185
private fun trackAutoUploadAction(

WordPress/src/main/java/org/wordpress/android/ui/utils/ConcurrentContinuationWrapper.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.wordpress.android.ui.utils
22

33
import kotlinx.coroutines.CancellableContinuation
4+
import kotlinx.coroutines.ExperimentalCoroutinesApi
45
import kotlinx.coroutines.suspendCancellableCoroutine
56

67
class ConcurrentContinuationWrapper<T> : ContinuationWrapper<T> {
@@ -18,6 +19,7 @@ class ConcurrentContinuationWrapper<T> : ContinuationWrapper<T> {
1819
}
1920
}
2021

22+
@OptIn(ExperimentalCoroutinesApi::class)
2123
override fun continueWith(t: T) {
2224
continuationList.removeFirstOrNull()?.let {
2325
if (it.isActive) {

WordPress/src/test/java/org/wordpress/android/ui/jetpack/backup/download/usecases/GetBackupDownloadStatusUseCaseTest.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package org.wordpress.android.ui.jetpack.backup.download.usecases
22

33
import com.nhaarman.mockitokotlin2.any
44
import com.nhaarman.mockitokotlin2.whenever
5-
import kotlinx.coroutines.ExperimentalCoroutinesApi
65
import kotlinx.coroutines.InternalCoroutinesApi
76
import kotlinx.coroutines.flow.toList
87
import org.assertj.core.api.Assertions.assertThat
@@ -30,7 +29,6 @@ import java.util.Calendar
3029
import java.util.Date
3130

3231
@InternalCoroutinesApi
33-
@ExperimentalCoroutinesApi
3432
class GetBackupDownloadStatusUseCaseTest : BaseUnitTest() {
3533
private lateinit var useCase: GetBackupDownloadStatusUseCase
3634
@Mock lateinit var networkUtilsWrapper: NetworkUtilsWrapper

WordPress/src/test/java/org/wordpress/android/ui/jetpack/restore/usecases/GetRestoreStatusUseCaseTest.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package org.wordpress.android.ui.jetpack.restore.usecases
22

33
import com.nhaarman.mockitokotlin2.any
44
import com.nhaarman.mockitokotlin2.whenever
5-
import kotlinx.coroutines.ExperimentalCoroutinesApi
65
import kotlinx.coroutines.InternalCoroutinesApi
76
import kotlinx.coroutines.flow.toList
87
import org.assertj.core.api.Assertions.assertThat
@@ -41,7 +40,6 @@ private const val CURRENT_ENTRY = "current entry"
4140
private val PUBLISHED = Date()
4241

4342
@InternalCoroutinesApi
44-
@ExperimentalCoroutinesApi
4543
@RunWith(MockitoJUnitRunner::class)
4644
class GetRestoreStatusUseCaseTest {
4745
private lateinit var useCase: GetRestoreStatusUseCase

WordPress/src/test/java/org/wordpress/android/ui/jetpack/scan/ScanViewModelTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ private const val ON_ENTER_SERVER_CREDS_MESSAGE_CLICKED_PARAM_POSITION = 7
6464
private const val TEST_SITE_ID = 1L
6565
private const val SERVER_CREDS_LINK = "${Constants.URL_JETPACK_SETTINGS}/$TEST_SITE_ID}"
6666

67-
@ExperimentalCoroutinesApi
68-
@InternalCoroutinesApi
6967
@Suppress("LargeClass")
68+
@InternalCoroutinesApi
69+
@ExperimentalCoroutinesApi
7070
class ScanViewModelTest : BaseUnitTest() {
7171
@Rule
7272
@JvmField val coroutineScope = MainCoroutineScopeRule()

WordPress/src/test/java/org/wordpress/android/ui/jetpack/scan/usecases/FetchFixThreatsStatusUseCaseTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ import org.wordpress.android.ui.jetpack.scan.usecases.FetchFixThreatsStatusUseCa
3030
import org.wordpress.android.ui.jetpack.scan.usecases.FetchFixThreatsStatusUseCase.FetchFixThreatsState.NotStarted
3131
import org.wordpress.android.util.NetworkUtilsWrapper
3232

33-
@ExperimentalCoroutinesApi
3433
@InternalCoroutinesApi
34+
@ExperimentalCoroutinesApi
3535
class FetchFixThreatsStatusUseCaseTest : BaseUnitTest() {
3636
@Rule
3737
@JvmField val coroutineScope = MainCoroutineScopeRule()

WordPress/src/test/java/org/wordpress/android/ui/jetpack/scan/usecases/FetchScanStateUseCaseTest.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import com.nhaarman.mockitokotlin2.anyOrNull
55
import com.nhaarman.mockitokotlin2.times
66
import com.nhaarman.mockitokotlin2.verify
77
import com.nhaarman.mockitokotlin2.whenever
8-
import kotlinx.coroutines.ExperimentalCoroutinesApi
98
import kotlinx.coroutines.InternalCoroutinesApi
109
import kotlinx.coroutines.flow.toList
1110
import org.assertj.core.api.Assertions.assertThat
@@ -27,7 +26,6 @@ import org.wordpress.android.ui.jetpack.scan.usecases.FetchScanStateUseCase.Fetc
2726
import org.wordpress.android.ui.jetpack.scan.usecases.FetchScanStateUseCase.FetchScanState.Success
2827
import org.wordpress.android.util.NetworkUtilsWrapper
2928

30-
@ExperimentalCoroutinesApi
3129
@InternalCoroutinesApi
3230
class FetchScanStateUseCaseTest : BaseUnitTest() {
3331
private lateinit var useCase: FetchScanStateUseCase

0 commit comments

Comments
 (0)