Skip to content

Commit

Permalink
[ANDROAPP-5701] Check server available instead of internet connection
Browse files Browse the repository at this point in the history
Signed-off-by: andresmr <[email protected]>
  • Loading branch information
andresmr committed Apr 18, 2024
1 parent 46057ab commit 65274a6
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,22 @@ class GranularSyncModule(
view,
repository,
schedulerProvider,
object : DispatcherProvider {
override fun io() = Dispatchers.IO

override fun computation() = Dispatchers.Default

override fun ui() = Dispatchers.Main
},
provideDispatchers(),
syncContext,
workManagerController,
smsSyncProvider,
)
}

@Provides
fun provideDispatchers() = object : DispatcherProvider {
override fun io() = Dispatchers.IO

override fun computation() = Dispatchers.Default

override fun ui() = Dispatchers.Main
}

@Provides
fun granularSyncRepository(
d2: D2,
Expand All @@ -87,6 +90,7 @@ class GranularSyncModule(
dhisProgramUtils,
periodUtils,
resourceManager,
provideDispatchers(),
)

@Provides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,15 @@ class GranularSyncModule(
periodUtils: DhisPeriodUtils,
preferenceProvider: PreferenceProvider,
resourceManager: ResourceManager,
dispatcherProvider: DispatcherProvider,
): GranularSyncRepository = GranularSyncRepository(
d2,
syncContext,
preferenceProvider,
dhisProgramUtils,
periodUtils,
resourceManager,
dispatcherProvider,
)

@Provides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ class GranularSyncPresenter(
workerName = workerName()
}

private val _serverAvailability = MutableLiveData<Boolean>()
val serverAvailability: LiveData<Boolean> = _serverAvailability

private fun loadSyncInfo(forcedState: State? = null) {
viewModelScope.launch(dispatcher.io()) {
val syncState = async {
Expand Down Expand Up @@ -424,4 +427,15 @@ class GranularSyncPresenter(
}
}
}

fun checkServerAvailability() {
viewModelScope.launch(dispatcher.io()) {
try {
repository.checkServerAvailability()
_serverAvailability.value = true
} catch (error: RuntimeException) {
_serverAvailability.value = false
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.dhis2.utils.granularsync

import io.reactivex.Single
import kotlinx.coroutines.withContext
import org.dhis2.R
import org.dhis2.commons.bindings.categoryOptionCombo
import org.dhis2.commons.bindings.countEventImportConflicts
Expand Down Expand Up @@ -41,6 +42,7 @@ import org.dhis2.commons.sync.ConflictType
import org.dhis2.commons.sync.SyncContext
import org.dhis2.commons.sync.SyncStatusItem
import org.dhis2.commons.sync.SyncStatusType
import org.dhis2.commons.viewmodel.DispatcherProvider
import org.dhis2.data.dhislogic.DhisProgramUtils
import org.hisp.dhis.android.core.D2
import org.hisp.dhis.android.core.common.State
Expand All @@ -57,6 +59,7 @@ class GranularSyncRepository(
private val dhisProgramUtils: DhisProgramUtils,
private val periodUtils: DhisPeriodUtils,
private val resourceManager: ResourceManager,
private val dispatcher: DispatcherProvider,
) {

fun getUiState(forcedState: State? = null): SyncUiState {
Expand Down Expand Up @@ -554,7 +557,7 @@ class GranularSyncRepository(

val teiMainAttribute = tei.let {
d2.teiMainAttributes(it.uid(), programUid)
} ?: emptyList()
}

val label = teiMainAttribute.firstOrNull()?.let { (attributeName, value) ->
"$attributeName: $value"
Expand Down Expand Up @@ -980,6 +983,10 @@ class GranularSyncRepository(
.map { it.displayName() }
}
}

suspend fun checkServerAvailability() = withContext(dispatcher.io()) {
d2.systemInfoModule().ping().blockingGet()
}
}

fun List<SyncStatusItem>.sortedByState(): List<SyncStatusItem> {
Expand Down
18 changes: 11 additions & 7 deletions app/src/main/java/org/dhis2/utils/granularsync/SyncStatusDialog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,18 @@ class SyncStatusDialog : BottomSheetDialogFragment(), GranularSyncContracts.View
}

private fun onSyncClick() {
when {
networkUtils.isOnline() -> syncGranular()
viewModel.canSendSMS() &&
viewModel.isSMSEnabled(context?.showSMS() == true) -> syncSms()

!networkUtils.isOnline() &&
!viewModel.isSMSEnabled(context?.showSMS() == true) -> showSnackbar()
viewModel.serverAvailability.observe(viewLifecycleOwner) { isAvailable ->
val canSendSMS = viewModel.canSendSMS()
val isSMSEnabled = viewModel.isSMSEnabled(context?.showSMS() == true)

when {
isAvailable -> syncGranular()
canSendSMS && isSMSEnabled -> syncSms()
else -> showSnackbar()
}
}

viewModel.checkServerAvailability()
}

private fun showSnackbar() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import androidx.lifecycle.Observer
import androidx.work.WorkInfo
import io.reactivex.Completable
import io.reactivex.Single
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import org.dhis2.commons.Constants
import org.dhis2.commons.sync.ConflictType
Expand All @@ -23,14 +25,18 @@ import org.hisp.dhis.android.core.common.ObjectWithUid
import org.hisp.dhis.android.core.common.State
import org.hisp.dhis.android.core.dataset.DataSet
import org.hisp.dhis.android.core.dataset.DataSetElement
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.ArgumentMatchers.anyList
import org.mockito.Mockito
import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.doThrow
import org.mockito.kotlin.mock
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
Expand All @@ -49,14 +55,25 @@ class GranularSyncPresenterTest {
private val trampolineSchedulerProvider = TrampolineSchedulerProvider()
private val testingDispatcher = UnconfinedTestDispatcher()
private val testDispatcher: DispatcherProvider = mock {
on { io() } doReturn testingDispatcher
on { ui() } doReturn testingDispatcher
on { io() } doReturn Dispatchers.Unconfined
on { ui() } doReturn Dispatchers.Unconfined
}
private val workManager = Mockito.mock(WorkManagerController::class.java)
private val smsSyncProvider: SMSSyncProvider = mock()
private val context: Context = mock()
private val syncContext: SyncContext = SyncContext.Global()

@Before
fun setUp() {
// Dispatchers.setMain(testingDispatcher)
}

@After
fun tearDown() {
// Dispatchers.resetMain()
// testDispatcher.cleanupTestCoroutines()
}

@Test
fun `should return tracker program error state`() {
val presenter = GranularSyncPresenter(
Expand Down Expand Up @@ -463,4 +480,44 @@ class GranularSyncPresenterTest {
verify(workManager).syncDataForWorker(Constants.DATA_NOW, Constants.INITIAL_SYNC)
verify(workInfoObserver).onChanged(anyList())
}

@Test
fun shouldCheckAvailableConnection() = runBlocking {
whenever(repository.checkServerAvailability()) doReturn "pong"

val presenter = GranularSyncPresenter(
d2,
view,
repository,
trampolineSchedulerProvider,
testDispatcher,
SyncContext.Global(),
workManager,
smsSyncProvider,
)

presenter.checkServerAvailability()

assertTrue(presenter.serverAvailability.value!!)
}

@Test
fun shouldCheckUnavailableConnection() = runBlocking {
whenever(repository.checkServerAvailability()) doThrow RuntimeException()

val presenter = GranularSyncPresenter(
d2,
view,
repository,
trampolineSchedulerProvider,
testDispatcher,
SyncContext.Global(),
workManager,
smsSyncProvider,
)

presenter.checkServerAvailability()

assertFalse(presenter.serverAvailability.value!!)
}
}
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ hilt = '2.47'
hiltCompiler = '1.0.0'
jacoco = '0.8.10'
designSystem = "0.2-20240412.132136-56"
dhis2sdk = "1.10.0-20240322.092247-38"
dhis2sdk = "1.10.0-20240410.081505-42"
ruleEngine = "3.0.0-20240119.134348-12"
expressionParser = "1.1.0-20240219.115041-14"
appcompat = "1.6.1"
Expand Down

0 comments on commit 65274a6

Please sign in to comment.