Skip to content

Commit

Permalink
Merge branch 'enhancements' of github.com:opensrp/fhircore into enhan…
Browse files Browse the repository at this point in the history
…cements
  • Loading branch information
dubdabasoduba committed Nov 20, 2024
2 parents 63ee9b4 + d57bb07 commit 2c0e792
Show file tree
Hide file tree
Showing 57 changed files with 13,017 additions and 1,603 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ jobs:
force-avd-creation: true
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: ./gradlew clean -PlocalPropertiesFile=local.properties :quest:fhircoreJacocoReport --info -Pandroid.testInstrumentationRunnerArguments.notPackage=org.smartregister.fhircore.quest.performance
script: ./gradlew clean -PlocalPropertiesFile=local.properties :quest:fhircoreJacocoReport --stacktrace -Pandroid.testInstrumentationRunnerArguments.notPackage=org.smartregister.fhircore.quest.performance

- name: Run Quest module unit and instrumentation tests and generate aggregated coverage report (Disabled)
if: false
Expand Down
5 changes: 3 additions & 2 deletions android/buildSrc/src/main/kotlin/BuildConfigs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ object BuildConfigs {
const val compileSdk = 34
const val targetSdk = 34
const val versionCode = 11
const val versionName = "2.0.0"
const val versionName = "2.0.1"
const val applicationId = "org.smartregister.opensrp"
const val jvmToolchain = 17
const val kotlinCompilerExtensionVersion = "1.5.8"
const val jacocoVersion ="0.8.11"
const val ktLintVersion = "0.49.0"
const val enableUnitTestCoverage = true
const val enableAndroidTestCoverage = false
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,9 @@ constructor(
open val fhirPathDataExtractor: FhirPathDataExtractor,
open val parser: IParser,
@ApplicationContext open val context: Context,
open val contentCache: ContentCache,
) {

@Inject lateinit var contentCache: ContentCache

init {
DaggerDefaultRepositoryComponent.create().inject(this)
}

suspend inline fun <reified T : Resource> loadResource(resourceId: String): T? =
fhirEngine.loadResource(resourceId)

Expand Down Expand Up @@ -264,6 +259,10 @@ constructor(
fhirEngine.update(resource)
}

suspend fun applyDbTransaction(block: suspend () -> Unit) {
fhirEngine.withTransaction { block.invoke() }
}

suspend fun loadManagingEntity(group: Group) =
group.managingEntity?.let { reference ->
fhirEngine
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import org.smartregister.fhircore.engine.configuration.ConfigurationRegistry
import org.smartregister.fhircore.engine.configuration.app.ConfigService
import org.smartregister.fhircore.engine.configuration.profile.ProfileConfiguration
import org.smartregister.fhircore.engine.configuration.register.RegisterConfiguration
import org.smartregister.fhircore.engine.data.local.ContentCache
import org.smartregister.fhircore.engine.data.local.DefaultRepository
import org.smartregister.fhircore.engine.domain.model.ActionParameter
import org.smartregister.fhircore.engine.domain.model.ActionParameterType
Expand All @@ -52,6 +53,7 @@ constructor(
override val fhirPathDataExtractor: FhirPathDataExtractor,
override val parser: IParser,
@ApplicationContext override val context: Context,
override val contentCache: ContentCache,
) :
Repository,
DefaultRepository(
Expand All @@ -64,6 +66,7 @@ constructor(
fhirPathDataExtractor = fhirPathDataExtractor,
parser = parser,
context = context,
contentCache = contentCache,
) {

override suspend fun loadRegisterData(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ import java.util.Base64
import javax.inject.Inject
import javax.inject.Singleton
import javax.net.ssl.SSLHandshakeException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.smartregister.fhircore.engine.configuration.app.ConfigService
import org.smartregister.fhircore.engine.data.remote.auth.OAuthService
Expand Down Expand Up @@ -215,8 +217,11 @@ constructor(
addAccountExplicitly(newAccount, oAuthResponse.refreshToken, null)
setAuthToken(newAccount, AUTH_TOKEN_TYPE, oAuthResponse.accessToken)
}

// Save credentials
secureSharedPreference.saveCredentials(username, password)
CoroutineScope(dispatcherProvider.io()).launch {
secureSharedPreference.saveCredentials(username, password)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import org.smartregister.fhircore.engine.configuration.ConfigurationRegistry
import org.smartregister.fhircore.engine.data.local.DefaultRepository
import org.smartregister.fhircore.engine.util.DispatcherProvider
import org.smartregister.fhircore.engine.util.extension.resourceClassType
import org.smartregister.fhircore.engine.util.forEachAsync
import org.smartregister.p2p.dao.ReceiverTransferDao
import org.smartregister.p2p.sync.DataType
import timber.log.Timber
Expand All @@ -46,8 +45,8 @@ constructor(
override fun receiveJson(type: DataType, jsonArray: JSONArray): Long {
var maxLastUpdated = 0L
Timber.i("saving resources from base dai ${type.name} -> ${jsonArray.length()}")
runBlocking {
(0 until jsonArray.length()).forEachAsync {
(0 until jsonArray.length()).forEach {
runBlocking {
val resource =
FhirContext.forR4Cached()
.newJsonParser()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,14 @@ package org.smartregister.fhircore.engine.p2p.dao

import ca.uhn.fhir.context.FhirContext
import com.google.android.fhir.FhirEngine
import com.google.android.fhir.SearchResult
import com.google.android.fhir.datacapture.extensions.logicalId
import java.util.TreeSet
import javax.inject.Inject
import kotlinx.coroutines.runBlocking
import org.hl7.fhir.r4.model.Resource
import org.json.JSONArray
import org.smartregister.fhircore.engine.configuration.ConfigurationRegistry
import org.smartregister.fhircore.engine.util.DefaultDispatcherProvider
import org.smartregister.fhircore.engine.util.extension.resourceClassType
import org.smartregister.fhircore.engine.util.forEachAsync
import org.smartregister.p2p.dao.SenderTransferDao
import org.smartregister.p2p.model.RecordCount
import org.smartregister.p2p.search.data.JsonData
Expand Down Expand Up @@ -58,43 +55,41 @@ constructor(
// TODO: complete retrieval of data implementation
Timber.e("Last updated at value is $lastUpdated")
var highestRecordId = lastUpdated
var records: List<SearchResult<Resource>>
var jsonArrayResult: JSONArray
runBlocking {
records =
dataType.name.resourceClassType().let { classType ->
loadResources(
lastRecordUpdatedAt = highestRecordId,
batchSize = batchSize,
offset = offset,
classType,
)
}

Timber.i("Fetching resources from base dao of type $dataType.name")
highestRecordId =
(if (records.isNotEmpty()) {
records.last().resource.meta?.lastUpdated?.time ?: highestRecordId
} else {
lastUpdated
})

val jsonArray = JSONArray()
records.forEachAsync {
jsonArray.put(FhirContext.forR4Cached().newJsonParser().encodeResourceToString(it.resource))
highestRecordId =
if (it.resource.meta?.lastUpdated?.time!! > highestRecordId) {
it.resource.meta?.lastUpdated?.time!!
} else {
highestRecordId
}
Timber.i(
"Sending ${it.resource.resourceType} with id ====== ${it.resource.logicalId} and lastUpdated = ${it.resource.meta?.lastUpdated?.time!!}",
val records = runBlocking {
dataType.name.resourceClassType().let { classType ->
loadResources(
lastRecordUpdatedAt = highestRecordId,
batchSize = batchSize,
offset = offset,
classType,
)
}
jsonArrayResult = jsonArray
}

Timber.i("Fetching resources from base dao of type $dataType.name")
highestRecordId =
(if (records.isNotEmpty()) {
records.last().resource.meta?.lastUpdated?.time ?: highestRecordId
} else {
lastUpdated
})

val jsonArray = JSONArray()
records.forEach {
jsonArray.put(FhirContext.forR4Cached().newJsonParser().encodeResourceToString(it.resource))
highestRecordId =
if (it.resource.meta?.lastUpdated?.time!! > highestRecordId) {
it.resource.meta?.lastUpdated?.time!!
} else {
highestRecordId
}
Timber.i(
"Sending ${it.resource.resourceType} with id ====== ${it.resource.logicalId} and lastUpdated = ${it.resource.meta?.lastUpdated?.time!!}",
)
}

Timber.e("New highest Last updated at value is $highestRecordId")
return JsonData(jsonArrayResult, highestRecordId)
return JsonData(jsonArray, highestRecordId)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,20 @@
package org.smartregister.fhircore.engine.sync

import android.content.Context
import androidx.work.BackoffPolicy
import androidx.work.Constraints
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.OutOfQuotaPolicy
import androidx.work.WorkManager
import com.google.android.fhir.FhirEngine
import com.google.android.fhir.sync.BackoffCriteria
import com.google.android.fhir.sync.CurrentSyncJobStatus
import com.google.android.fhir.sync.LastSyncJobStatus
import com.google.android.fhir.sync.PeriodicSyncConfiguration
import com.google.android.fhir.sync.PeriodicSyncJobStatus
import com.google.android.fhir.sync.RepeatInterval
import com.google.android.fhir.sync.RetryConfiguration
import com.google.android.fhir.sync.Sync
import com.google.android.fhir.sync.SyncJobStatus
import com.google.android.fhir.sync.download.ResourceParamsBasedDownloadWorkManager
Expand Down Expand Up @@ -76,6 +81,12 @@ constructor(
.setConstraints(
Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build(),
)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.setBackoffCriteria(
BackoffPolicy.LINEAR,
10,
TimeUnit.SECONDS,
)
.build(),
)
}
Expand All @@ -94,6 +105,16 @@ constructor(
syncConstraints =
Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build(),
repeat = RepeatInterval(interval = interval, timeUnit = TimeUnit.MINUTES),
retryConfiguration =
RetryConfiguration(
backoffCriteria =
BackoffCriteria(
backoffDelay = 10,
timeUnit = TimeUnit.SECONDS,
backoffPolicy = BackoffPolicy.EXPONENTIAL,
),
maxRetries = 3,
),
),
)
.handlePeriodicSyncJobStatus(this)
Expand All @@ -104,7 +125,11 @@ constructor(
) {
this.onEach {
syncListenerManager.onSyncListeners.forEach { onSyncListener ->
onSyncListener.onSync(it.currentSyncJobStatus)
onSyncListener.onSync(
if (it.lastSyncJobStatus != null) {
CurrentSyncJobStatus.Succeeded((it.lastSyncJobStatus as LastSyncJobStatus).timestamp)
} else it.currentSyncJobStatus,
)
}
}
.catch { throwable -> Timber.e("Encountered an error during periodic sync:", throwable) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent
import org.hl7.fhir.r4.model.Composition
import org.hl7.fhir.r4.model.Composition.SectionComponent
import org.hl7.fhir.r4.model.Enumerations
import org.hl7.fhir.r4.model.Group
import org.hl7.fhir.r4.model.Identifier
import org.hl7.fhir.r4.model.ListResource
import org.hl7.fhir.r4.model.Reference
Expand Down Expand Up @@ -1006,17 +1007,18 @@ class ConfigurationRegistryTest : RobolectricTest() {

assertEquals(4, requestPathArgumentSlot.size)

assertEquals("Bundle/the-commodities-bundle-id", requestPathArgumentSlot.first().id)
assertEquals(ResourceType.Bundle, requestPathArgumentSlot.first().resourceType)
val bundles = requestPathArgumentSlot.filterIsInstance<Bundle>().first()
assertEquals("Bundle/the-commodities-bundle-id", bundles.id)
assertEquals(ResourceType.Bundle, bundles.resourceType)

assertEquals("Group/1000001", requestPathArgumentSlot.second().id)
assertEquals(ResourceType.Group, requestPathArgumentSlot.second().resourceType)
val groups = requestPathArgumentSlot.filterIsInstance<Group>()
assertEquals(2, groups.size)
assertTrue(groups.any { it.id == "Group/1000001" })
assertTrue(groups.any { it.id == "Group/2000001" })

assertEquals("Group/2000001", requestPathArgumentSlot[2].id)
assertEquals(ResourceType.Group, requestPathArgumentSlot[2].resourceType)

assertEquals("composition-id-1", requestPathArgumentSlot.last().id)
assertEquals(ResourceType.Composition, requestPathArgumentSlot.last().resourceType)
val compositions = requestPathArgumentSlot.filterIsInstance<Composition>().first()
assertEquals("composition-id-1", compositions.id)
assertEquals(ResourceType.Composition, compositions.resourceType)
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ class DefaultRepositoryTest : RobolectricTest() {

@Inject lateinit var parser: IParser

@Inject lateinit var contentCache: ContentCache

@BindValue
val configService: ConfigService =
spyk(AppConfigService(ApplicationProvider.getApplicationContext()))
Expand All @@ -149,6 +151,7 @@ class DefaultRepositoryTest : RobolectricTest() {
fhirPathDataExtractor = fhirPathDataExtractor,
parser = parser,
context = context,
contentCache = contentCache,
)
}

Expand Down Expand Up @@ -562,6 +565,7 @@ class DefaultRepositoryTest : RobolectricTest() {
fhirPathDataExtractor = fhirPathDataExtractor,
parser = parser,
context = context,
contentCache = contentCache,
),
)
coEvery { fhirEngine.search<RelatedPerson>(any()) } returns
Expand Down Expand Up @@ -640,6 +644,7 @@ class DefaultRepositoryTest : RobolectricTest() {
fhirPathDataExtractor = fhirPathDataExtractor,
parser = parser,
context = context,
contentCache = contentCache,
),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import org.smartregister.fhircore.engine.configuration.ConfigType
import org.smartregister.fhircore.engine.configuration.ConfigurationRegistry
import org.smartregister.fhircore.engine.configuration.profile.ProfileConfiguration
import org.smartregister.fhircore.engine.configuration.register.RegisterConfiguration
import org.smartregister.fhircore.engine.data.local.ContentCache
import org.smartregister.fhircore.engine.datastore.syncLocationIdsProtoStore
import org.smartregister.fhircore.engine.domain.model.ActionParameter
import org.smartregister.fhircore.engine.domain.model.ActionParameterType
Expand Down Expand Up @@ -104,6 +105,9 @@ class RegisterRepositoryTest : RobolectricTest() {
@Inject lateinit var fhirEngine: FhirEngine

@Inject lateinit var parser: IParser

@Inject lateinit var contentCache: ContentCache

private val configurationRegistry: ConfigurationRegistry = Faker.buildTestConfigurationRegistry()
private val patient = Faker.buildPatient(PATIENT_ID)
private lateinit var registerRepository: RegisterRepository
Expand All @@ -123,6 +127,7 @@ class RegisterRepositoryTest : RobolectricTest() {
fhirPathDataExtractor = fhirPathDataExtractor,
parser = parser,
context = ApplicationProvider.getApplicationContext(),
contentCache = contentCache,
),
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ import org.smartregister.fhircore.engine.configuration.QuestionnaireConfig
import org.smartregister.fhircore.engine.configuration.app.ConfigService
import org.smartregister.fhircore.engine.configuration.event.EventTriggerCondition
import org.smartregister.fhircore.engine.configuration.event.EventWorkflow
import org.smartregister.fhircore.engine.data.local.ContentCache
import org.smartregister.fhircore.engine.data.local.DefaultRepository
import org.smartregister.fhircore.engine.domain.model.ResourceConfig
import org.smartregister.fhircore.engine.robolectric.RobolectricTest
Expand Down Expand Up @@ -159,6 +160,8 @@ class FhirCarePlanGeneratorTest : RobolectricTest() {

@Inject lateinit var configurationRegistry: ConfigurationRegistry

@Inject lateinit var contentCache: ContentCache

private val context: Context = ApplicationProvider.getApplicationContext()
private val knowledgeManager = KnowledgeManager.create(context)
private val fhirContext: FhirContext = FhirContext.forCached(FhirVersionEnum.R4)
Expand Down Expand Up @@ -192,6 +195,7 @@ class FhirCarePlanGeneratorTest : RobolectricTest() {
fhirPathDataExtractor = fhirPathDataExtractor,
parser = iParser,
context = context,
contentCache = contentCache,
),
)

Expand Down
Loading

0 comments on commit 2c0e792

Please sign in to comment.