Skip to content

Commit

Permalink
Fix app displaying database maintenance screen often during app start…
Browse files Browse the repository at this point in the history
  • Loading branch information
msasikanth authored Nov 4, 2024
1 parent f0e820f commit 9d3f087
Show file tree
Hide file tree
Showing 13 changed files with 105 additions and 80 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@

- Show statin nudge alert when statins can be prescribed

### Fixes

- Fix app displaying database maintenance screen often during app startup

## 2024-08-05-9175

### Internal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,10 @@ class PurgeDatabaseAndroidTest {
assertThat(patientDao.patientProfileImmediate(deletedButUnsyncedPatientProfile.patientUuid)).isEqualTo(deletedButUnsyncedPatientProfile)

// when
appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))
val numberOfPurgedRecords = appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))

// then
assertThat(numberOfPurgedRecords).isEqualTo(1)
assertThat(patientDao.patientProfileImmediate(deletedPatientProfile.patientUuid)).isNull()
assertThat(patientDao.patientProfileImmediate(notDeletedPatientProfile.patientUuid)).isEqualTo(notDeletedPatientProfile)
assertThat(patientDao.patientProfileImmediate(deletedButUnsyncedPatientProfile.patientUuid)).isEqualTo(deletedButUnsyncedPatientProfile)
Expand Down Expand Up @@ -120,9 +121,10 @@ class PurgeDatabaseAndroidTest {
assertThat(phoneNumberDao.phoneNumber(notSyncedPatientProfile.patientUuid).blockingFirst()).containsExactly(deletedButUnsyncedPhoneNumber)

// when
appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))
val numberOfPurgedRecords = appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))

// then
assertThat(numberOfPurgedRecords).isEqualTo(1)
assertThat(phoneNumberDao.phoneNumber(syncedPatientProfile.patientUuid).blockingFirst()).containsExactly(notDeletedPhoneNumber)
assertThat(phoneNumberDao.phoneNumber(notSyncedPatientProfile.patientUuid).blockingFirst()).containsExactly(deletedButUnsyncedPhoneNumber)
}
Expand Down Expand Up @@ -164,9 +166,10 @@ class PurgeDatabaseAndroidTest {
assertThat(businessIdDao.get(deletedButUnsyncedBusinessId.uuid)).isEqualTo(deletedButUnsyncedBusinessId)

// when
appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))
val numberOfPurgedRecords = appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))

// then
assertThat(numberOfPurgedRecords).isEqualTo(1)
assertThat(businessIdDao.get(deletedBusinessId.uuid)).isNull()
assertThat(businessIdDao.get(notDeletedBusinessId.uuid)).isEqualTo(notDeletedBusinessId)
assertThat(businessIdDao.get(deletedButUnsyncedBusinessId.uuid)).isEqualTo(deletedButUnsyncedBusinessId)
Expand Down Expand Up @@ -211,9 +214,10 @@ class PurgeDatabaseAndroidTest {
assertThat(bloodPressureDao.getOne(deletedButUnsyncedBloodPressureMeasurement.uuid)).isEqualTo(deletedButUnsyncedBloodPressureMeasurement)

// when
appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))
val numberOfPurgedRecords = appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))

// then
assertThat(numberOfPurgedRecords).isEqualTo(1)
assertThat(bloodPressureDao.getOne(deletedBloodPressureMeasurement.uuid)).isNull()
assertThat(bloodPressureDao.getOne(notDeletedBloodPressureMeasurement.uuid)).isEqualTo(notDeletedBloodPressureMeasurement)
assertThat(bloodPressureDao.getOne(deletedButUnsyncedBloodPressureMeasurement.uuid)).isEqualTo(deletedButUnsyncedBloodPressureMeasurement)
Expand Down Expand Up @@ -258,9 +262,10 @@ class PurgeDatabaseAndroidTest {
assertThat(bloodSugarDao.getOne(deletedButUnsyncedBloodSugarMeasurement.uuid)).isEqualTo(deletedButUnsyncedBloodSugarMeasurement)

// when
appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))
val numberOfPurgedRecords = appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))

// then
assertThat(numberOfPurgedRecords).isEqualTo(1)
assertThat(bloodSugarDao.getOne(deletedBloodSugarMeasurement.uuid)).isNull()
assertThat(bloodSugarDao.getOne(notDeletedBloodSugarMeasurement.uuid)).isEqualTo(notDeletedBloodSugarMeasurement)
assertThat(bloodSugarDao.getOne(deletedButUnsyncedBloodSugarMeasurement.uuid)).isEqualTo(deletedButUnsyncedBloodSugarMeasurement)
Expand Down Expand Up @@ -305,9 +310,10 @@ class PurgeDatabaseAndroidTest {
assertThat(prescribedDrugsDao.getOne(deletedButUnsyncedPrescripion.uuid)).isEqualTo(deletedButUnsyncedPrescripion)

// when
appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))
val numberOfPurgedRecords = appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))

// then
assertThat(numberOfPurgedRecords).isEqualTo(1)
assertThat(prescribedDrugsDao.getOne(deletedPrescription.uuid)).isNull()
assertThat(prescribedDrugsDao.getOne(notDeletedPrescription.uuid)).isEqualTo(notDeletedPrescription)
assertThat(prescribedDrugsDao.getOne(deletedButUnsyncedPrescripion.uuid)).isEqualTo(deletedButUnsyncedPrescripion)
Expand Down Expand Up @@ -356,9 +362,10 @@ class PurgeDatabaseAndroidTest {
assertThat(appointmentDao.getOne(deletedButUnsyncedAppointment.uuid)).isEqualTo(deletedButUnsyncedAppointment)

// when
appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))
val numberOfPurgedRecords = appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))

// then
assertThat(numberOfPurgedRecords).isEqualTo(1)
assertThat(appointmentDao.getOne(deletedAppointment.uuid)).isNull()
assertThat(appointmentDao.getOne(notDeletedAppointment.uuid)).isEqualTo(notDeletedAppointment)
assertThat(appointmentDao.getOne(deletedButUnsyncedAppointment.uuid)).isEqualTo(deletedButUnsyncedAppointment)
Expand Down Expand Up @@ -403,9 +410,10 @@ class PurgeDatabaseAndroidTest {
assertThat(medicalHistoryDao.getOne(deletedButUnsyncedMedicalHistory.uuid)).isEqualTo(deletedButUnsyncedMedicalHistory)

// when
appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))
val numberOfPurgedRecords = appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))

// then
assertThat(numberOfPurgedRecords).isEqualTo(1)
assertThat(medicalHistoryDao.getOne(deletedMedicalHistory.uuid)).isNull()
assertThat(medicalHistoryDao.getOne(notDeletedMedicalHistory.uuid)).isEqualTo(notDeletedMedicalHistory)
assertThat(medicalHistoryDao.getOne(deletedButUnsyncedMedicalHistory.uuid)).isEqualTo(deletedButUnsyncedMedicalHistory)
Expand Down Expand Up @@ -518,9 +526,10 @@ class PurgeDatabaseAndroidTest {
assertThat(appointmentDao.getOne(visitedAppointmentAndSyncedForPatient1.uuid)).isEqualTo(visitedAppointmentAndSyncedForPatient1)

// when
appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))
val numberOfPurgedRecords = appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))

// then
assertThat(numberOfPurgedRecords).isEqualTo(3)
assertThat(appointmentDao.getOne(scheduledAppointmentAndSyncedForPatient1.uuid)).isNull()
assertThat(appointmentDao.getOne(cancelledAppointmentAndSyncedForPatient1.uuid)).isNull()
assertThat(appointmentDao.getOne(visitedButUnsyncedAppointmentForPatient1.uuid)).isEqualTo(visitedButUnsyncedAppointmentForPatient1)
Expand Down Expand Up @@ -570,9 +579,10 @@ class PurgeDatabaseAndroidTest {
assertThat(patientDao.patientProfileImmediate(patientWithNullRetentionTime.patientUuid)).isEqualTo(patientWithNullRetentionTime)

// when
appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))
val numberOfPurgedRecords = appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))

// then
assertThat(numberOfPurgedRecords).isEqualTo(1)
assertThat(patientDao.patientProfileImmediate(patientWithPassedRetentionTime.patientUuid)).isNull()
assertThat(patientDao.patientProfileImmediate(patientWithNotPassedRetentionTime.patientUuid)).isEqualTo(patientWithNotPassedRetentionTime)
assertThat(patientDao.patientProfileImmediate(patientWithNullRetentionTime.patientUuid)).isEqualTo(patientWithNullRetentionTime)
Expand Down Expand Up @@ -612,9 +622,10 @@ class PurgeDatabaseAndroidTest {
assertThat(bloodPressureDao.getOne(notDeletedBloodPressureMeasurement.uuid)).isEqualTo(notDeletedBloodPressureMeasurement)

// when
appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))
val numberOfPurgedRecords = appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))

// then
assertThat(numberOfPurgedRecords).isEqualTo(1)
assertThat(bloodPressureDao.getOne(deletedBloodPressureMeasurement.uuid)).isNull()
assertThat(bloodPressureDao.getOne(notDeletedBloodPressureMeasurement.uuid)).isEqualTo(notDeletedBloodPressureMeasurement)
}
Expand Down Expand Up @@ -651,9 +662,10 @@ class PurgeDatabaseAndroidTest {
assertThat(bloodSugarDao.getOne(notDeletedBloodSugarMeasurement.uuid)).isEqualTo(notDeletedBloodSugarMeasurement)

// when
appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))
val numberOfPurgedRecords = appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))

// then
assertThat(numberOfPurgedRecords).isEqualTo(1)
assertThat(bloodSugarDao.getOne(deletedBloodSugarMeasurement.uuid)).isNull()
assertThat(bloodSugarDao.getOne(notDeletedBloodSugarMeasurement.uuid)).isEqualTo(notDeletedBloodSugarMeasurement)
}
Expand Down Expand Up @@ -690,9 +702,10 @@ class PurgeDatabaseAndroidTest {
assertThat(appointmentDao.getOne(notDeletedAppointment.uuid)).isEqualTo(notDeletedAppointment)

// when
appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))
val numberOfPurgedRecords = appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))

// then
assertThat(numberOfPurgedRecords).isEqualTo(1)
assertThat(appointmentDao.getOne(deletedAppointment.uuid)).isNull()
assertThat(appointmentDao.getOne(notDeletedAppointment.uuid)).isEqualTo(notDeletedAppointment)
}
Expand Down Expand Up @@ -729,9 +742,10 @@ class PurgeDatabaseAndroidTest {
assertThat(medicalHistoryDao.getOne(notDeletedMedicalHistory.uuid)).isEqualTo(notDeletedMedicalHistory)

// when
appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))
val numberOfPurgedRecords = appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))

// then
assertThat(numberOfPurgedRecords).isEqualTo(1)
assertThat(medicalHistoryDao.getOne(deletedMedicalHistory.uuid)).isNull()
assertThat(medicalHistoryDao.getOne(notDeletedMedicalHistory.uuid)).isEqualTo(notDeletedMedicalHistory)
}
Expand Down Expand Up @@ -768,9 +782,10 @@ class PurgeDatabaseAndroidTest {
assertThat(prescribedDrugsDao.getOne(notDeletedPrescribedDrug.uuid)).isEqualTo(notDeletedPrescribedDrug)

// when
appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))
val numberOfPurgedRecords = appDatabase.purge(Instant.parse("2021-06-01T00:00:00Z"))

// then
assertThat(numberOfPurgedRecords).isEqualTo(1)
assertThat(prescribedDrugsDao.getOne(deletedPrescribedDrug.uuid)).isNull()
assertThat(prescribedDrugsDao.getOne(notDeletedPrescribedDrug.uuid)).isEqualTo(notDeletedPrescribedDrug)
}
Expand Down Expand Up @@ -801,9 +816,10 @@ class PurgeDatabaseAndroidTest {
assertThat(callResultDao.getOne(deletedButUnsyncedCallResult.id)).isEqualTo(deletedButUnsyncedCallResult)

// when
appDatabase.purge(Instant.parse("2018-01-01T00:00:00Z"))
val numberOfPurgedRecords = appDatabase.purge(Instant.parse("2018-01-01T00:00:00Z"))

// then
assertThat(numberOfPurgedRecords).isEqualTo(1)
assertThat(callResultDao.getOne(deletedCallResult.id)).isNull()
assertThat(callResultDao.getOne(notDeletedCallResult.id)).isEqualTo(notDeletedCallResult)
assertThat(callResultDao.getOne(deletedButUnsyncedCallResult.id)).isEqualTo(deletedButUnsyncedCallResult)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package org.simple.clinic.setup

import dagger.Module
import dagger.Provides
import org.simple.clinic.remoteconfig.ConfigReader
import java.time.Duration

@Module
class SetupActivityConfigModule {

@Provides
fun providesSetupActivityConfig(): SetupActivityConfig {
return SetupActivityConfig(databaseMaintenanceTaskInterval = Duration.ofMinutes(1))
fun providesSetupActivityConfig(configReader: ConfigReader): SetupActivityConfig {
val intervalInMins = configReader.long("database_maintenance_interval", 60)
return SetupActivityConfig(databaseMaintenanceTaskInterval = Duration.ofMinutes(intervalInMins))
}
}
91 changes: 47 additions & 44 deletions app/src/main/java/org/simple/clinic/AppDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,12 @@ abstract class AppDatabase : RoomDatabase() {

fun prune(now: Instant) {
optimizeWithAnalytics(PurgeDeleted) {
purge(now)
val numberOfPurgedRecords = purge(now)

try {
vacuumDatabase()
if (numberOfPurgedRecords > 0) {
vacuumDatabase()
}
} catch (e: Exception) {
// Vacuuming is an optimization that's unlikely to fail. But if it
// does, we can ignore it and just report the exception and let
Expand All @@ -234,71 +237,71 @@ abstract class AppDatabase : RoomDatabase() {
}

@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
fun purge(now: Instant) {
runInTransaction {
purgeUnnecessaryPatients(now)
purgeUnnecessaryBloodPressures()
purgeUnnecessaryBloodSugars()
purgeUnnecessaryAppointments()
purgeUnnecessaryMedicalHistories()
purgeUnnecessaryPrescriptions()
purgeUnnecessaryCallResults()
purgeUnnecessaryQuestionnaireResponses()
fun purge(now: Instant): Int {
return runInTransaction<Int> {
purgeUnnecessaryPatients(now) +
purgeUnnecessaryBloodPressures() +
purgeUnnecessaryBloodSugars() +
purgeUnnecessaryAppointments() +
purgeUnnecessaryMedicalHistories() +
purgeUnnecessaryPrescriptions() +
purgeUnnecessaryCallResults() +
purgeUnnecessaryQuestionnaireResponses()
}
}

private fun purgeUnnecessaryPrescriptions() {
with(prescriptionDao()) {
purgeDeleted()
purgePrescribedDrugWhenPatientIsNull()
private fun purgeUnnecessaryPrescriptions(): Int {
return with(prescriptionDao()) {
purgeDeleted() +
purgePrescribedDrugWhenPatientIsNull()
}
}

private fun purgeUnnecessaryMedicalHistories() {
with(medicalHistoryDao()) {
purgeDeleted()
purgeMedicalHistoryWhenPatientIsNull()
private fun purgeUnnecessaryMedicalHistories(): Int {
return with(medicalHistoryDao()) {
purgeDeleted() +
purgeMedicalHistoryWhenPatientIsNull()
}
}

private fun purgeUnnecessaryAppointments() {
with(appointmentDao()) {
purgeDeleted()
purgeUnusedAppointments()
purgeAppointmentsWhenPatientIsNull()
private fun purgeUnnecessaryAppointments(): Int {
return with(appointmentDao()) {
purgeDeleted() +
purgeUnusedAppointments() +
purgeAppointmentsWhenPatientIsNull()
}
}

private fun purgeUnnecessaryBloodSugars() {
with(bloodSugarDao()) {
purgeDeleted()
purgeBloodSugarMeasurementWhenPatientIsNull()
private fun purgeUnnecessaryBloodSugars(): Int {
return with(bloodSugarDao()) {
purgeDeleted() +
purgeBloodSugarMeasurementWhenPatientIsNull()
}
}

private fun purgeUnnecessaryBloodPressures() {
with(bloodPressureDao()) {
purgeDeleted()
purgeBloodPressureMeasurementWhenPatientIsNull()
private fun purgeUnnecessaryBloodPressures(): Int {
return with(bloodPressureDao()) {
purgeDeleted() +
purgeBloodPressureMeasurementWhenPatientIsNull()
}
}

private fun purgeUnnecessaryPatients(now: Instant) {
with(patientDao()) {
purgeDeleted()
purgeDeletedPhoneNumbers()
purgeDeletedBusinessIds()
purgePatientAfterRetentionTime(now)
private fun purgeUnnecessaryPatients(now: Instant): Int {
return with(patientDao()) {
purgeDeleted() +
purgeDeletedPhoneNumbers() +
purgeDeletedBusinessIds() +
purgePatientAfterRetentionTime(now)
}
}

private fun purgeUnnecessaryCallResults() {
callResultDao().purgeDeleted()
private fun purgeUnnecessaryCallResults(): Int {
return callResultDao().purgeDeleted()
}

private fun purgeUnnecessaryQuestionnaireResponses() {
questionnaireDao().purgeDeleted()
questionnaireResponseDao().purgeDeleted()
private fun purgeUnnecessaryQuestionnaireResponses(): Int {
return questionnaireDao().purgeDeleted() +
questionnaireResponseDao().purgeDeleted()
}

private fun vacuumDatabase() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ data class BloodSugarMeasurement(
DELETE FROM BloodSugarMeasurements
WHERE deletedAt IS NOT NULL AND syncStatus == 'DONE'
""")
fun purgeDeleted()
fun purgeDeleted(): Int

@Query(""" SELECT * FROM BloodSugarMeasurements """)
fun getAllBloodSugarMeasurements(): List<BloodSugarMeasurement>
Expand All @@ -207,6 +207,6 @@ data class BloodSugarMeasurement(
WHERE P.uuid IS NULL AND BS.syncStatus == 'DONE'
)
""")
fun purgeBloodSugarMeasurementWhenPatientIsNull()
fun purgeBloodSugarMeasurementWhenPatientIsNull(): Int
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ data class BloodPressureMeasurement(
DELETE FROM BloodPressureMeasurement
WHERE deletedAt IS NOT NULL AND syncStatus == 'DONE'
""")
fun purgeDeleted()
fun purgeDeleted(): Int

@Query("SELECT * FROM BloodPressureMeasurement")
fun getAllBloodPressureMeasurements(): List<BloodPressureMeasurement>
Expand All @@ -249,7 +249,7 @@ data class BloodPressureMeasurement(
WHERE P.uuid IS NULL AND BP.syncStatus == 'DONE'
)
""")
fun purgeBloodPressureMeasurementWhenPatientIsNull()
fun purgeBloodPressureMeasurementWhenPatientIsNull(): Int

@Query("""
SELECT
Expand Down
Loading

0 comments on commit 9d3f087

Please sign in to comment.