From 8129afdfcbfa09f4d9bf10d4441902751c1f50bb Mon Sep 17 00:00:00 2001 From: Aurangzaib Umer Date: Fri, 23 Aug 2024 15:41:31 +0500 Subject: [PATCH] Caching questionnaires and their SM --- .../engine/task/FhirCarePlanGenerator.kt | 2 +- .../quest/ui/questionnaire/ContentCache.kt | 19 ++++++++++++ .../questionnaire/QuestionnaireViewModel.kt | 30 +++++++++++++++++-- 3 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/ContentCache.kt diff --git a/android/engine/src/main/java/org/smartregister/fhircore/engine/task/FhirCarePlanGenerator.kt b/android/engine/src/main/java/org/smartregister/fhircore/engine/task/FhirCarePlanGenerator.kt index 6fee7dfe88..44581b5db2 100644 --- a/android/engine/src/main/java/org/smartregister/fhircore/engine/task/FhirCarePlanGenerator.kt +++ b/android/engine/src/main/java/org/smartregister/fhircore/engine/task/FhirCarePlanGenerator.kt @@ -214,7 +214,7 @@ constructor( } source.setParameter(Task.SP_PERIOD, period) source.setParameter(ActivityDefinition.SP_VERSION, IntegerType(index)) - + //need to cache these SM too val structureMap = fhirEngine.get(IdType(action.transform).idPart) structureMapUtilities.transform( transformSupportServices.simpleWorkerContext, diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/ContentCache.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/ContentCache.kt new file mode 100644 index 0000000000..e92f201555 --- /dev/null +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/ContentCache.kt @@ -0,0 +1,19 @@ +package org.smartregister.fhircore.quest.ui.questionnaire + +import androidx.collection.LruCache +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.hl7.fhir.r4.model.Resource + +object ContentCache { + private val maxMemory: Int = (Runtime.getRuntime().maxMemory() / 1024).toInt() + private val cacheSize: Int = maxMemory / 8 + private val cache = LruCache(cacheSize) + + suspend fun saveResource(resourceId: String, resource: Resource) = + withContext(Dispatchers.IO) { cache.put("${resource::class.simpleName}/$resourceId", resource) } + + fun getResource(resourceId: String) = cache[resourceId] + + suspend fun invalidate() = withContext(Dispatchers.IO) { cache.evictAll() } +} \ No newline at end of file diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireViewModel.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireViewModel.kt index 12c43c1dc3..a955bc0fe5 100644 --- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireViewModel.kt +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireViewModel.kt @@ -61,6 +61,7 @@ import org.hl7.fhir.r4.model.QuestionnaireResponse.QuestionnaireResponseItemComp import org.hl7.fhir.r4.model.RelatedPerson import org.hl7.fhir.r4.model.Resource import org.hl7.fhir.r4.model.ResourceType +import org.hl7.fhir.r4.model.StructureMap import org.smartregister.fhircore.engine.BuildConfig import org.smartregister.fhircore.engine.configuration.ConfigType import org.smartregister.fhircore.engine.configuration.ConfigurationRegistry @@ -146,7 +147,18 @@ constructor( questionnaireConfig: QuestionnaireConfig, ): Questionnaire? { if (questionnaireConfig.id.isEmpty() || questionnaireConfig.id.isBlank()) return null - return defaultRepository.loadResource(questionnaireConfig.id) + var questionnaire = ContentCache.getResource(ResourceType.Questionnaire.name + "/" + questionnaireConfig.id)?.copy() + if (questionnaire == null) { + questionnaire = defaultRepository.loadResource(questionnaireConfig.id)?.also { ques -> + ContentCache.saveResource( + questionnaireConfig.id, + ques.copy(), + ) + } + } + + + return questionnaire as Questionnaire } /** @@ -631,7 +643,7 @@ constructor( transformSupportServices = transformSupportServices, structureMapProvider = { structureMapUrl: String?, _: IWorkerContext -> structureMapUrl?.substringAfterLast("/")?.let { - defaultRepository.loadResource(it) + fetchStructureMap(it) } }, ), @@ -661,6 +673,20 @@ constructor( } .getOrDefault(Bundle()) + + private suspend fun fetchStructureMap(structureMapUrl: String?): StructureMap? { + var structureMap: Resource? = null + structureMapUrl?.substringAfterLast("/")?.run { + structureMap = ContentCache.getResource(ResourceType.StructureMap.name + "/" + this) ?.let { + defaultRepository.loadResource(this)?.also { + it.let { ContentCache.saveResource(this, it) } + } + } + } + return structureMap as StructureMap? + } + + /** * This function saves [QuestionnaireResponse] as draft if any of the [QuestionnaireResponse.item] * has an answer.