forked from opensrp/fhircore
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Quest/Malawi Core] Feature Request: Push Local changes from FHIR Eng…
…ine database in case of sync failure (#86) * [Quest/Malawi Core] Feature Request: Push Local changes from FHIR Engine database in case of sync failure * Bug fix: Room dependency missing * Feature request : Run in the background * Trigger push changes manually Revert "Trigger push changes manually" This reverts commit 9bf5af1. * Trigger push changes manually * Bug fix * Visible when FHIR sync worker fails at least 3 times
- Loading branch information
1 parent
815f31b
commit a9d4786
Showing
21 changed files
with
998 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
...oid/engine/src/main/java/org/smartregister/fhircore/engine/data/local/TingatheDatabase.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* | ||
* Copyright 2021 Ona Systems, Inc | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.smartregister.fhircore.engine.data.local | ||
|
||
import android.content.Context | ||
import androidx.room.Database | ||
import androidx.room.Room | ||
import androidx.room.RoomDatabase | ||
import org.smartregister.fhircore.engine.data.local.localChange.LocalChangeDao | ||
import org.smartregister.fhircore.engine.data.local.localChange.LocalChangeEntity | ||
import org.smartregister.fhircore.engine.data.local.syncAttempt.SyncAttemptTrackerDao | ||
import org.smartregister.fhircore.engine.data.local.syncAttempt.SyncAttemptTrackerEntity | ||
|
||
@Database( | ||
version = 2, | ||
entities = | ||
[ | ||
LocalChangeEntity::class, | ||
SyncAttemptTrackerEntity::class, | ||
], | ||
) | ||
abstract class TingatheDatabase : RoomDatabase() { | ||
|
||
abstract val localChangeDao: LocalChangeDao | ||
abstract val syncAttemptTrackerDao: SyncAttemptTrackerDao | ||
|
||
companion object { | ||
fun databaseBuilder(context: Context): Builder<TingatheDatabase> { | ||
return Room.databaseBuilder(context, TingatheDatabase::class.java, "tingathe_db") | ||
} | ||
} | ||
} |
38 changes: 38 additions & 0 deletions
38
.../src/main/java/org/smartregister/fhircore/engine/data/local/localChange/LocalChangeDao.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* | ||
* Copyright 2021 Ona Systems, Inc | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.smartregister.fhircore.engine.data.local.localChange | ||
|
||
import androidx.room.Dao | ||
import androidx.room.Insert | ||
import androidx.room.OnConflictStrategy | ||
import androidx.room.Query | ||
import kotlinx.coroutines.flow.Flow | ||
|
||
@Dao | ||
abstract class LocalChangeDao { | ||
|
||
@Query("SELECT * FROM LocalChangeEntity ORDER BY resourceType") | ||
abstract fun query(): Flow<List<LocalChangeEntity>> | ||
|
||
@Insert(onConflict = OnConflictStrategy.REPLACE) | ||
abstract suspend fun upsert(data: List<LocalChangeEntity>) | ||
|
||
@Query("SELECT * FROM LocalChangeEntity WHERE status != 2 ORDER BY type") | ||
abstract suspend fun get(): List<LocalChangeEntity> | ||
|
||
@Query("DELETE FROM LocalChangeEntity") abstract suspend fun deleteAll(): Int | ||
} |
48 changes: 48 additions & 0 deletions
48
...c/main/java/org/smartregister/fhircore/engine/data/local/localChange/LocalChangeEntity.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* | ||
* Copyright 2021 Ona Systems, Inc | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.smartregister.fhircore.engine.data.local.localChange | ||
|
||
import androidx.room.Entity | ||
import androidx.room.PrimaryKey | ||
import com.google.android.fhir.LocalChange | ||
|
||
@Entity | ||
data class LocalChangeEntity( | ||
val resourceId: String, | ||
val resourceType: String, | ||
val versionId: String? = null, | ||
val type: String, | ||
@PrimaryKey(autoGenerate = false) val payload: String, | ||
val status: Int = 0, | ||
) { | ||
enum class Type(val value: Int) { | ||
INSERT(1), // create a new resource. payload is the entire resource json. | ||
UPDATE(2), // patch. payload is the json patch. | ||
DELETE(3), // delete. payload is empty string. | ||
; | ||
|
||
companion object { | ||
fun from(input: String): Type = entries.first { it.name == input } | ||
|
||
fun from(input: Int): Type = entries.first { it.value == input } | ||
} | ||
} | ||
} | ||
|
||
fun LocalChange.toEntity(): LocalChangeEntity { | ||
return LocalChangeEntity(resourceId, resourceType, versionId, type.name, payload) | ||
} |
29 changes: 29 additions & 0 deletions
29
...in/java/org/smartregister/fhircore/engine/data/local/localChange/LocalChangeStateEvent.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* Copyright 2021 Ona Systems, Inc | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.smartregister.fhircore.engine.data.local.localChange | ||
|
||
sealed interface LocalChangeStateEvent { | ||
data object Idle : LocalChangeStateEvent | ||
|
||
data object Finished : LocalChangeStateEvent | ||
|
||
data class Processing(val localChange: LocalChangeEntity) : LocalChangeStateEvent | ||
|
||
data class Completed(val localChange: LocalChangeEntity) : LocalChangeStateEvent | ||
|
||
data class Failed(val p0: LocalChangeEntity, val p1: Exception) : LocalChangeStateEvent | ||
} |
76 changes: 76 additions & 0 deletions
76
...src/main/java/org/smartregister/fhircore/engine/data/local/localChange/LocalChangeUtil.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* Copyright 2021 Ona Systems, Inc | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.smartregister.fhircore.engine.data.local.localChange | ||
|
||
import ca.uhn.fhir.context.FhirContext | ||
import ca.uhn.fhir.context.FhirVersionEnum | ||
import ca.uhn.fhir.parser.IParser | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.withContext | ||
import org.hl7.fhir.r4.model.Binary | ||
import org.hl7.fhir.r4.model.Bundle | ||
import org.hl7.fhir.r4.model.Resource | ||
import org.smartregister.fhircore.engine.data.local.localChange.LocalChangeEntity.Type.Companion.from | ||
|
||
val jsonParser: IParser = FhirContext.forCached(FhirVersionEnum.R4).newJsonParser() | ||
const val contentType = "application/json" | ||
|
||
suspend fun bundleComponent( | ||
localChangeEntities: List<LocalChangeEntity>, | ||
): List<Bundle.BundleEntryComponent> { | ||
return withContext(Dispatchers.IO) { | ||
val updateLocalChange = | ||
localChangeEntities | ||
.filter { from(it.type) == LocalChangeEntity.Type.UPDATE } | ||
.map { createRequest(it, createPathRequest(it)) } | ||
|
||
val insertDeleteLocalChange = | ||
localChangeEntities | ||
.filterNot { from(it.type) == LocalChangeEntity.Type.UPDATE } | ||
.sortedBy { it.versionId } | ||
.map { change -> | ||
createRequest(change, (jsonParser.parseResource(change.payload) as Resource)) | ||
} | ||
insertDeleteLocalChange + updateLocalChange | ||
} | ||
} | ||
|
||
fun createPathRequest(localChangeEntity: LocalChangeEntity): Binary { | ||
return Binary().apply { | ||
contentType = "application/json-patch+json" | ||
data = localChangeEntity.payload.toByteArray() | ||
} | ||
} | ||
|
||
fun createRequest( | ||
localChange: LocalChangeEntity, | ||
resourceToUpload: Resource, | ||
): Bundle.BundleEntryComponent { | ||
return Bundle.BundleEntryComponent().apply { | ||
resource = resourceToUpload | ||
request = | ||
Bundle.BundleEntryRequestComponent().apply { | ||
url = "${localChange.resourceType}/${localChange.resourceId}" | ||
method = | ||
when (from(localChange.type)) { | ||
LocalChangeEntity.Type.INSERT -> Bundle.HTTPVerb.PUT | ||
LocalChangeEntity.Type.UPDATE -> Bundle.HTTPVerb.PATCH | ||
LocalChangeEntity.Type.DELETE -> Bundle.HTTPVerb.DELETE | ||
} | ||
} | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
...va/org/smartregister/fhircore/engine/data/local/localChange/repository/LocalChangeRepo.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* Copyright 2021 Ona Systems, Inc | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.smartregister.fhircore.engine.data.local.localChange.repository | ||
|
||
import kotlinx.coroutines.flow.Flow | ||
import org.smartregister.fhircore.engine.data.local.localChange.LocalChangeEntity | ||
|
||
interface LocalChangeRepo { | ||
suspend fun queryFHIRLocalChanges() | ||
|
||
suspend fun deleteAll() | ||
|
||
fun query(): Flow<List<LocalChangeEntity>> | ||
|
||
suspend fun get(): List<LocalChangeEntity> | ||
|
||
suspend fun upsert(data: List<LocalChangeEntity>) | ||
|
||
operator fun invoke(index: Int, localChange: LocalChangeEntity): Flow<LocalChangeIndex> | ||
} |
Oops, something went wrong.