diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.kt b/app/src/main/java/info/nightscout/androidaps/MainApp.kt index 8137bfeb03..ec4215aaba 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.kt +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.kt @@ -184,7 +184,7 @@ class MainApp : DaggerApplication() { Thread.currentThread().uncaughtExceptionHandler?.uncaughtException(Thread.currentThread(), e) return@setErrorHandler } - aapsLogger.warn(LTag.CORE, "Undeliverable exception received, not sure what to do", e) + aapsLogger.warn(LTag.CORE, "Undeliverable exception received, not sure what to do", e.toString()) } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt index 0284a57efb..9d161e9855 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt @@ -5,6 +5,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.text.toSpanned import dagger.android.support.DaggerFragment import info.nightscout.androidaps.R import info.nightscout.androidaps.activities.SingleFragmentActivity @@ -29,11 +30,13 @@ import info.nightscout.androidaps.plugins.general.overview.OverviewData import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.DashHistoryDatabase import info.nightscout.androidaps.plugins.pump.omnipod.eros.history.database.ErosHistoryDatabase import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.protection.ProtectionCheck import info.nightscout.androidaps.utils.protection.ProtectionCheck.Protection.PREFERENCES import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.shared.logging.AAPSLogger +import info.nightscout.shared.logging.LTag import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.kotlin.plusAssign @@ -113,6 +116,25 @@ class MaintenanceFragment : DaggerFragment() { }) } } + binding.cleanupDb.setOnClickListener { + activity?.let { activity -> + var result = "" + OKDialog.showConfirmation(activity, rh.gs(R.string.maintenance), rh.gs(R.string.cleanup_db_confirm), Runnable { + disposable += Completable.fromAction { result = repository.cleanupDatabase(93, deleteTrackedChanges = true) } + .subscribeOn(aapsSchedulers.io) + .observeOn(aapsSchedulers.main) + .subscribeBy( + onError = { aapsLogger.error("Error cleaning up databases", it) }, + onComplete = { + if (result.isNotEmpty()) + OKDialog.show(activity, rh.gs(R.string.result), HtmlHelper.fromHtml("" + rh.gs(R.string.cleared_entries) + "\n" + result).toSpanned()) + aapsLogger.info(LTag.CORE, "Cleaned up databases with result: $result") + } + ) + uel.log(Action.CLEANUP_DATABASES, Sources.Maintenance) + }) + } + } binding.navExport.setOnClickListener { uel.log(Action.EXPORT_SETTINGS, Sources.Maintenance) // start activity for checking permissions... diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenancePlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenancePlugin.kt index 466d455141..1ccdd3b467 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenancePlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenancePlugin.kt @@ -69,14 +69,14 @@ class MaintenancePlugin @Inject constructor( val files = logDir.listFiles { _: File?, name: String -> (name.startsWith("AndroidAPS") && name.endsWith(".zip")) } - val autotunefiles = logDir.listFiles { _: File?, name: String -> + val autotuneFiles = logDir.listFiles { _: File?, name: String -> (name.startsWith("autotune") && name.endsWith(".zip")) } val amount = sp.getInt(R.string.key_logshipper_amount, keep) val keepIndex = amount - 1 - if (autotunefiles != null && autotunefiles.isNotEmpty()) { - Arrays.sort(autotunefiles) { f1: File, f2: File -> f2.name.compareTo(f1.name) } - var delAutotuneFiles = listOf(*autotunefiles) + if (autotuneFiles != null && autotuneFiles.isNotEmpty()) { + Arrays.sort(autotuneFiles) { f1: File, f2: File -> f2.name.compareTo(f1.name) } + var delAutotuneFiles = listOf(*autotuneFiles) if (keepIndex < delAutotuneFiles.size) { delAutotuneFiles = delAutotuneFiles.subList(keepIndex, delAutotuneFiles.size) for (file in delAutotuneFiles) { diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveWorker.kt b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveWorker.kt index 84424ad9c4..8a07fe9afe 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveWorker.kt +++ b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveWorker.kt @@ -37,6 +37,7 @@ import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.widget.updateWidget import info.nightscout.shared.logging.AAPSLogger import info.nightscout.shared.logging.LTag +import info.nightscout.shared.sharedPreferences.SP import java.util.concurrent.TimeUnit import javax.inject.Inject import kotlin.math.abs @@ -62,6 +63,7 @@ class KeepAliveWorker( @Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var maintenancePlugin: MaintenancePlugin @Inject lateinit var rh: ResourceHelper + @Inject lateinit var sp: SP init { (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) @@ -122,10 +124,22 @@ class KeepAliveWorker( checkAPS() maintenancePlugin.deleteLogs(30) workerDbStatus() + databaseCleanup() return Result.success() } + // Perform history data cleanup every day + // Keep 6 months + private fun databaseCleanup() { + val lastRun = sp.getLong(R.string.key_last_cleanup_run, 0L) + if (lastRun < dateUtil.now() - T.days(1).msecs()) { + val result = repository.cleanupDatabase(6 * 31, deleteTrackedChanges = false) + aapsLogger.debug(LTag.CORE, "Cleanup result: $result") + sp.putLong(R.string.key_last_cleanup_run, dateUtil.now()) + } + } + // When Worker DB grows too much, work operations become slow // Library is cleaning DB every 7 days which may not be sufficient for NSClient full sync private fun workerDbStatus() { diff --git a/app/src/main/res/drawable/ic_database_cleanup.xml b/app/src/main/res/drawable/ic_database_cleanup.xml new file mode 100644 index 0000000000..1bb7386f2d --- /dev/null +++ b/app/src/main/res/drawable/ic_database_cleanup.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/app/src/main/res/layout/maintenance_fragment.xml b/app/src/main/res/layout/maintenance_fragment.xml index ca0708a692..852d2b906e 100644 --- a/app/src/main/res/layout/maintenance_fragment.xml +++ b/app/src/main/res/layout/maintenance_fragment.xml @@ -211,6 +211,21 @@ app:layout_gravity="fill" app:layout_row="0" /> + + + app:layout_row="1" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 62cda2d4a7..5a94b2dadf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -56,6 +56,7 @@ ns_profile_store_last_synced_timestamp local_profile_last_change ns_sync_slow + last_cleanup_run Treatments safety Max allowed bolus [U] Max allowed carbs [g] @@ -1258,5 +1259,8 @@ Error asking for permissions dynisf_adjust_sensitivity Adjust sensitivity and BG + Database cleanup + Do you want to cleanup the database?\nIt will remove tracked changes and historic data older than 3 months. + Cleared entries diff --git a/core/src/main/java/info/nightscout/androidaps/utils/Translator.kt b/core/src/main/java/info/nightscout/androidaps/utils/Translator.kt index 195d69874c..9248492ce4 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/Translator.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/Translator.kt @@ -89,6 +89,7 @@ class Translator @Inject internal constructor( Action.EXPORT_SETTINGS -> rh.gs(R.string.uel_export_settings) Action.IMPORT_SETTINGS -> rh.gs(R.string.uel_import_settings) Action.RESET_DATABASES -> rh.gs(R.string.uel_reset_databases) + Action.CLEANUP_DATABASES -> rh.gs(R.string.uel_cleanup_databases) Action.EXPORT_DATABASES -> rh.gs(R.string.uel_export_databases) Action.IMPORT_DATABASES -> rh.gs(R.string.uel_import_databases) Action.OTP_EXPORT -> rh.gs(R.string.uel_otp_export) diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 03690a4142..498d600629 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -462,6 +462,7 @@ EXPORT SETTINGS IMPORT SETTINGS RESET DATABASES + CLEANUP DATABASES EXPORT DATABASES IMPORT DATABASES OTP EXPORT diff --git a/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt b/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt index 2ce6796e66..dd2d33806d 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt @@ -12,7 +12,9 @@ import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.schedulers.Schedulers import io.reactivex.rxjava3.subjects.PublishSubject +import java.lang.StringBuilder import java.util.concurrent.Callable +import java.util.concurrent.TimeUnit import javax.inject.Inject import javax.inject.Singleton import kotlin.math.roundToInt @@ -46,7 +48,7 @@ import kotlin.math.roundToInt * Executes a transaction and returns its result * Runs on IO scheduler */ - fun runTransactionForResult(transaction: Transaction): Single { + fun runTransactionForResult(transaction: Transaction): Single { val changes = mutableListOf() return Single.fromCallable { database.runInTransaction(Callable { @@ -60,6 +62,57 @@ import kotlin.math.roundToInt fun clearDatabases() = database.clearAllTables() + fun cleanupDatabase(keepDays: Long, deleteTrackedChanges: Boolean): String { + val than = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(keepDays) + val removed = mutableListOf>() + removed.add(Pair("GlucoseValue", database.glucoseValueDao.deleteOlderThan(than))) + removed.add(Pair("TherapyEvent", database.therapyEventDao.deleteOlderThan(than))) + removed.add(Pair("TemporaryBasal", database.temporaryBasalDao.deleteOlderThan(than))) + removed.add(Pair("ExtendedBolus", database.extendedBolusDao.deleteOlderThan(than))) + removed.add(Pair("Bolus", database.bolusDao.deleteOlderThan(than))) + removed.add(Pair("MultiWaveBolus", database.multiwaveBolusLinkDao.deleteOlderThan(than))) + //removed.add(Pair("TotalDailyDose", database.totalDailyDoseDao.deleteOlderThan(than))) + removed.add(Pair("Carbs", database.carbsDao.deleteOlderThan(than))) + removed.add(Pair("TemporaryTarget", database.temporaryTargetDao.deleteOlderThan(than))) + removed.add(Pair("ApsResultLink", database.apsResultLinkDao.deleteOlderThan(than))) + removed.add(Pair("BolusCalculatorResult", database.bolusCalculatorResultDao.deleteOlderThan(than))) + // keep at least one EPS + if (database.effectiveProfileSwitchDao.getEffectiveProfileSwitchDataFromTime(than + 1).blockingGet().isNotEmpty()) + removed.add(Pair("EffectiveProfileSwitch", database.effectiveProfileSwitchDao.deleteOlderThan(than))) + removed.add(Pair("ProfileSwitch", database.profileSwitchDao.deleteOlderThan(than))) + removed.add(Pair("ApsResult", database.apsResultDao.deleteOlderThan(than))) + //database.versionChangeDao.deleteOlderThan(than) + removed.add(Pair("UserEntry", database.userEntryDao.deleteOlderThan(than))) + removed.add(Pair("PreferenceChange", database.preferenceChangeDao.deleteOlderThan(than))) + //database.foodDao.deleteOlderThan(than) + removed.add(Pair("DeviceStatus", database.deviceStatusDao.deleteOlderThan(than))) + removed.add(Pair("OfflineEvent", database.offlineEventDao.deleteOlderThan(than))) + + if (deleteTrackedChanges) { + removed.add(Pair("GlucoseValue", database.glucoseValueDao.deleteTrackedChanges())) + removed.add(Pair("TherapyEvent", database.therapyEventDao.deleteTrackedChanges())) + removed.add(Pair("TemporaryBasal", database.temporaryBasalDao.deleteTrackedChanges())) + removed.add(Pair("Bolus", database.bolusDao.deleteTrackedChanges())) + removed.add(Pair("ExtendedBolus", database.extendedBolusDao.deleteTrackedChanges())) + removed.add(Pair("MultiWaveBolus", database.multiwaveBolusLinkDao.deleteTrackedChanges())) + //removed.add(Pair("TotalDailyDose", database.totalDailyDoseDao.deleteTrackedChanges())) + removed.add(Pair("Carbs", database.carbsDao.deleteTrackedChanges())) + removed.add(Pair("TemporaryTarget", database.temporaryTargetDao.deleteTrackedChanges())) + removed.add(Pair("ApsResultLink", database.apsResultLinkDao.deleteTrackedChanges())) + removed.add(Pair("BolusCalculatorResult", database.bolusCalculatorResultDao.deleteTrackedChanges())) + removed.add(Pair("EffectiveProfileSwitch", database.effectiveProfileSwitchDao.deleteTrackedChanges())) + removed.add(Pair("ProfileSwitch", database.profileSwitchDao.deleteTrackedChanges())) + removed.add(Pair("ApsResult", database.apsResultDao.deleteTrackedChanges())) + //database.foodDao.deleteHistory() + removed.add(Pair("OfflineEvent", database.offlineEventDao.deleteTrackedChanges())) + } + val ret = StringBuilder() + removed + .filter { it.second > 0 } + .map { ret.append(it.first + " " + it.second + "\n") } + return ret.toString() + } + fun clearCachedData(from: Long) { database.totalDailyDoseDao.deleteNewerThan(from, InterfaceIDs.PumpType.CACHE) } diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/APSResultDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/APSResultDao.kt index 5eabc904b9..2958ba90db 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/APSResultDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/APSResultDao.kt @@ -15,6 +15,12 @@ internal interface APSResultDao : TraceableDao { @Query("DELETE FROM $TABLE_APS_RESULTS") override fun deleteAllEntries() + @Query("DELETE FROM $TABLE_APS_RESULTS WHERE timestamp < :than") + override fun deleteOlderThan(than: Long): Int + + @Query("DELETE FROM $TABLE_APS_RESULTS WHERE referenceId IS NOT NULL") + override fun deleteTrackedChanges(): Int + @Query("SELECT * FROM $TABLE_APS_RESULTS WHERE dateCreated > :since AND dateCreated <= :until LIMIT :limit OFFSET :offset") suspend fun getNewEntriesSince(since: Long, until: Long, limit: Int, offset: Int): List } \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/APSResultLinkDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/APSResultLinkDao.kt index c5318c49f8..1b0568c917 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/APSResultLinkDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/APSResultLinkDao.kt @@ -6,7 +6,6 @@ import info.nightscout.androidaps.database.TABLE_APS_RESULTS import info.nightscout.androidaps.database.TABLE_APS_RESULT_LINKS import info.nightscout.androidaps.database.entities.APSResultLink -@Suppress("FunctionName") @Dao internal interface APSResultLinkDao : TraceableDao { @@ -16,6 +15,12 @@ internal interface APSResultLinkDao : TraceableDao { @Query("DELETE FROM $TABLE_APS_RESULTS") override fun deleteAllEntries() + @Query("DELETE FROM $TABLE_APS_RESULTS WHERE dateCreated < :than") + override fun deleteOlderThan(than: Long): Int + + @Query("DELETE FROM $TABLE_APS_RESULTS WHERE referenceId IS NOT NULL") + override fun deleteTrackedChanges(): Int + @Query("SELECT * FROM $TABLE_APS_RESULT_LINKS WHERE dateCreated > :since AND dateCreated <= :until LIMIT :limit OFFSET :offset") suspend fun getNewEntriesSince(since: Long, until: Long, limit: Int, offset: Int): List } \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/BolusCalculatorResultDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/BolusCalculatorResultDao.kt index 654dfb6a3f..05554208c8 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/BolusCalculatorResultDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/BolusCalculatorResultDao.kt @@ -7,7 +7,6 @@ import info.nightscout.androidaps.database.entities.BolusCalculatorResult import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.core.Single -@Suppress("FunctionName") @Dao internal interface BolusCalculatorResultDao : TraceableDao { @@ -18,6 +17,12 @@ internal interface BolusCalculatorResultDao : TraceableDao diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/BolusDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/BolusDao.kt index 60e054d409..c1a35fac28 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/BolusDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/BolusDao.kt @@ -8,7 +8,6 @@ import info.nightscout.androidaps.database.entities.Bolus import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.core.Single -@Suppress("FunctionName") @Dao internal interface BolusDao : TraceableDao { @@ -18,6 +17,12 @@ internal interface BolusDao : TraceableDao { @Query("DELETE FROM $TABLE_BOLUSES") override fun deleteAllEntries() + @Query("DELETE FROM $TABLE_BOLUSES WHERE timestamp < :than") + override fun deleteOlderThan(than: Long): Int + + @Query("DELETE FROM $TABLE_BOLUSES WHERE referenceId IS NOT NULL") + override fun deleteTrackedChanges(): Int + @Query("SELECT id FROM $TABLE_BOLUSES ORDER BY id DESC limit 1") fun getLastId(): Maybe diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/CarbsDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/CarbsDao.kt index 51bd4eda5a..53bd6c789b 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/CarbsDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/CarbsDao.kt @@ -2,13 +2,11 @@ package info.nightscout.androidaps.database.daos import androidx.room.Dao import androidx.room.Query -import info.nightscout.androidaps.database.TABLE_BOLUSES import info.nightscout.androidaps.database.TABLE_CARBS import info.nightscout.androidaps.database.entities.Carbs import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.core.Single -@Suppress("FunctionName") @Dao internal interface CarbsDao : TraceableDao { @@ -18,6 +16,12 @@ internal interface CarbsDao : TraceableDao { @Query("DELETE FROM $TABLE_CARBS") override fun deleteAllEntries() + @Query("DELETE FROM $TABLE_CARBS WHERE timestamp < :than") + override fun deleteOlderThan(than: Long): Int + + @Query("DELETE FROM $TABLE_CARBS WHERE referenceId IS NOT NULL") + override fun deleteTrackedChanges(): Int + @Query("SELECT id FROM $TABLE_CARBS ORDER BY id DESC limit 1") fun getLastId(): Maybe diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/DeviceStatusDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/DeviceStatusDao.kt index fe35bc7f34..addf3e2f21 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/DeviceStatusDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/DeviceStatusDao.kt @@ -4,8 +4,8 @@ import androidx.room.Dao import androidx.room.Insert import androidx.room.Query import androidx.room.Update -import info.nightscout.androidaps.database.entities.DeviceStatus import info.nightscout.androidaps.database.TABLE_DEVICE_STATUS +import info.nightscout.androidaps.database.entities.DeviceStatus import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.core.Single @@ -25,6 +25,9 @@ internal interface DeviceStatusDao { @Query("DELETE FROM $TABLE_DEVICE_STATUS") fun deleteAllEntries() + @Query("DELETE FROM $TABLE_DEVICE_STATUS WHERE timestamp < :than") + fun deleteOlderThan(than: Long): Int + @Query("SELECT id FROM $TABLE_DEVICE_STATUS ORDER BY id DESC limit 1") fun getLastId(): Maybe diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/EffectiveProfileSwitchDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/EffectiveProfileSwitchDao.kt index 9cd85e6e39..aeeb9d1066 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/EffectiveProfileSwitchDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/EffectiveProfileSwitchDao.kt @@ -7,7 +7,6 @@ import info.nightscout.androidaps.database.entities.EffectiveProfileSwitch import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.core.Single -@Suppress("FunctionName") @Dao internal interface EffectiveProfileSwitchDao : TraceableDao { @@ -17,6 +16,12 @@ internal interface EffectiveProfileSwitchDao : TraceableDao diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/ExtendedBolusDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/ExtendedBolusDao.kt index 639c6981e1..84a9aa4557 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/ExtendedBolusDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/ExtendedBolusDao.kt @@ -2,15 +2,12 @@ package info.nightscout.androidaps.database.daos import androidx.room.Dao import androidx.room.Query -import info.nightscout.androidaps.database.TABLE_CARBS import info.nightscout.androidaps.database.TABLE_EXTENDED_BOLUSES import info.nightscout.androidaps.database.embedments.InterfaceIDs -import info.nightscout.androidaps.database.entities.Carbs import info.nightscout.androidaps.database.entities.ExtendedBolus import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.core.Single -@Suppress("FunctionName") @Dao internal interface ExtendedBolusDao : TraceableDao { @@ -20,6 +17,12 @@ internal interface ExtendedBolusDao : TraceableDao { @Query("DELETE FROM $TABLE_EXTENDED_BOLUSES") override fun deleteAllEntries() + @Query("DELETE FROM $TABLE_EXTENDED_BOLUSES WHERE timestamp < :than") + override fun deleteOlderThan(than: Long): Int + + @Query("DELETE FROM $TABLE_EXTENDED_BOLUSES WHERE referenceId IS NOT NULL") + override fun deleteTrackedChanges(): Int + @Query("SELECT id FROM $TABLE_EXTENDED_BOLUSES ORDER BY id DESC limit 1") fun getLastId(): Maybe diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/FoodDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/FoodDao.kt index a4b0d29977..492f02329e 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/FoodDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/FoodDao.kt @@ -7,7 +7,6 @@ import info.nightscout.androidaps.database.entities.Food import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.core.Single -@Suppress("FunctionName") @Dao internal interface FoodDao : TraceableDao { @@ -17,6 +16,12 @@ internal interface FoodDao : TraceableDao { @Query("DELETE FROM $TABLE_FOODS") override fun deleteAllEntries() + @Query("DELETE FROM $TABLE_FOODS WHERE dateCreated < :than") + override fun deleteOlderThan(than: Long): Int + + @Query("DELETE FROM $TABLE_FOODS WHERE referenceId IS NOT NULL") + override fun deleteTrackedChanges(): Int + @Query("SELECT id FROM $TABLE_FOODS ORDER BY id DESC limit 1") fun getLastId(): Maybe diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/GlucoseValueDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/GlucoseValueDao.kt index e5cc439a0b..02687b0a7d 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/GlucoseValueDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/GlucoseValueDao.kt @@ -16,6 +16,12 @@ internal interface GlucoseValueDao : TraceableDao { @Query("DELETE FROM $TABLE_GLUCOSE_VALUES") override fun deleteAllEntries() + @Query("DELETE FROM $TABLE_GLUCOSE_VALUES WHERE timestamp < :than") + override fun deleteOlderThan(than: Long): Int + + @Query("DELETE FROM $TABLE_GLUCOSE_VALUES WHERE referenceId IS NOT NULL") + override fun deleteTrackedChanges(): Int + @Query("SELECT * FROM $TABLE_GLUCOSE_VALUES WHERE isValid = 1 AND referenceId IS NULL ORDER BY timestamp DESC limit 1") fun getLast(): Maybe diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/MultiwaveBolusLinkDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/MultiwaveBolusLinkDao.kt index 032bf9fd60..0bdb02b863 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/MultiwaveBolusLinkDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/MultiwaveBolusLinkDao.kt @@ -2,12 +2,9 @@ package info.nightscout.androidaps.database.daos import androidx.room.Dao import androidx.room.Query -import info.nightscout.androidaps.database.TABLE_GLUCOSE_VALUES import info.nightscout.androidaps.database.TABLE_MULTIWAVE_BOLUS_LINKS -import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.entities.MultiwaveBolusLink -@Suppress("FunctionName") @Dao internal interface MultiwaveBolusLinkDao : TraceableDao { @@ -17,6 +14,12 @@ internal interface MultiwaveBolusLinkDao : TraceableDao { @Query("DELETE FROM $TABLE_MULTIWAVE_BOLUS_LINKS") override fun deleteAllEntries() + @Query("DELETE FROM $TABLE_MULTIWAVE_BOLUS_LINKS WHERE dateCreated < :than") + override fun deleteOlderThan(than: Long): Int + + @Query("DELETE FROM $TABLE_MULTIWAVE_BOLUS_LINKS WHERE referenceId IS NOT NULL") + override fun deleteTrackedChanges(): Int + @Query("SELECT * FROM $TABLE_MULTIWAVE_BOLUS_LINKS WHERE dateCreated > :since AND dateCreated <= :until LIMIT :limit OFFSET :offset") suspend fun getNewEntriesSince(since: Long, until: Long, limit: Int, offset: Int): List } \ No newline at end of file diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/OfflineEventDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/OfflineEventDao.kt index 6b9b8f545c..d8ce6c88a3 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/OfflineEventDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/OfflineEventDao.kt @@ -2,14 +2,11 @@ package info.nightscout.androidaps.database.daos import androidx.room.Dao import androidx.room.Query -import info.nightscout.androidaps.database.TABLE_GLUCOSE_VALUES import info.nightscout.androidaps.database.TABLE_OFFLINE_EVENTS -import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.entities.OfflineEvent import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.core.Single -@Suppress("FunctionName") @Dao internal interface OfflineEventDao : TraceableDao { @@ -19,6 +16,12 @@ internal interface OfflineEventDao : TraceableDao { @Query("DELETE FROM $TABLE_OFFLINE_EVENTS") override fun deleteAllEntries() + @Query("DELETE FROM $TABLE_OFFLINE_EVENTS WHERE timestamp < :than") + override fun deleteOlderThan(than: Long): Int + + @Query("DELETE FROM $TABLE_OFFLINE_EVENTS WHERE referenceId IS NOT NULL") + override fun deleteTrackedChanges(): Int + @Query("SELECT id FROM $TABLE_OFFLINE_EVENTS ORDER BY id DESC limit 1") fun getLastId(): Maybe diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/PreferenceChangeDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/PreferenceChangeDao.kt index 4dd332c00c..a617e254e3 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/PreferenceChangeDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/PreferenceChangeDao.kt @@ -3,11 +3,8 @@ package info.nightscout.androidaps.database.daos import androidx.room.Dao import androidx.room.Insert import androidx.room.Query -import info.nightscout.androidaps.database.TABLE_GLUCOSE_VALUES import info.nightscout.androidaps.database.TABLE_PREFERENCE_CHANGES -import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.entities.PreferenceChange -import io.reactivex.rxjava3.core.Single @Dao interface PreferenceChangeDao { @@ -15,6 +12,9 @@ interface PreferenceChangeDao { @Insert fun insert(preferenceChange: PreferenceChange) + @Query("DELETE FROM $TABLE_PREFERENCE_CHANGES WHERE timestamp < :than") + fun deleteOlderThan(than: Long): Int + @Query("SELECT * FROM $TABLE_PREFERENCE_CHANGES WHERE timestamp > :since AND timestamp <= :until LIMIT :limit OFFSET :offset") suspend fun getNewEntriesSince(since: Long, until: Long, limit: Int, offset: Int): List diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/ProfileSwitchDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/ProfileSwitchDao.kt index 8684800614..ca994c6ccf 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/ProfileSwitchDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/ProfileSwitchDao.kt @@ -9,7 +9,6 @@ import info.nightscout.androidaps.database.entities.ProfileSwitch import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.core.Single -@Suppress("FunctionName") @Dao internal interface ProfileSwitchDao : ProfileSwitchDaoWorkaround { @@ -19,6 +18,12 @@ internal interface ProfileSwitchDao : ProfileSwitchDaoWorkaround { @Query("DELETE FROM $TABLE_PROFILE_SWITCHES") override fun deleteAllEntries() + @Query("DELETE FROM $TABLE_PROFILE_SWITCHES WHERE timestamp < :than") + override fun deleteOlderThan(than: Long): Int + + @Query("DELETE FROM $TABLE_PROFILE_SWITCHES WHERE referenceId IS NOT NULL") + override fun deleteTrackedChanges(): Int + @Query("SELECT id FROM $TABLE_PROFILE_SWITCHES ORDER BY id DESC limit 1") fun getLastId(): Maybe diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/TemporaryBasalDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/TemporaryBasalDao.kt index 5c13d2dafe..40a84e90c5 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/TemporaryBasalDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/TemporaryBasalDao.kt @@ -8,7 +8,6 @@ import info.nightscout.androidaps.database.entities.TemporaryBasal import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.core.Single -@Suppress("FunctionName") @Dao internal interface TemporaryBasalDao : TraceableDao { @@ -18,6 +17,12 @@ internal interface TemporaryBasalDao : TraceableDao { @Query("DELETE FROM $TABLE_TEMPORARY_BASALS") override fun deleteAllEntries() + @Query("DELETE FROM $TABLE_TEMPORARY_BASALS WHERE timestamp < :than") + override fun deleteOlderThan(than: Long): Int + + @Query("DELETE FROM $TABLE_TEMPORARY_BASALS WHERE referenceId IS NOT NULL") + override fun deleteTrackedChanges(): Int + @Query("SELECT id FROM $TABLE_TEMPORARY_BASALS ORDER BY id DESC limit 1") fun getLastId(): Maybe diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/TemporaryTargetDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/TemporaryTargetDao.kt index 57172e6c23..c002085377 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/TemporaryTargetDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/TemporaryTargetDao.kt @@ -2,14 +2,11 @@ package info.nightscout.androidaps.database.daos import androidx.room.Dao import androidx.room.Query -import info.nightscout.androidaps.database.TABLE_GLUCOSE_VALUES import info.nightscout.androidaps.database.TABLE_TEMPORARY_TARGETS -import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.entities.TemporaryTarget import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.core.Single -@Suppress("FunctionName") @Dao internal interface TemporaryTargetDao : TraceableDao { @@ -19,6 +16,12 @@ internal interface TemporaryTargetDao : TraceableDao { @Query("DELETE FROM $TABLE_TEMPORARY_TARGETS") override fun deleteAllEntries() + @Query("DELETE FROM $TABLE_TEMPORARY_TARGETS WHERE timestamp < :than") + override fun deleteOlderThan(than: Long): Int + + @Query("DELETE FROM $TABLE_TEMPORARY_TARGETS WHERE referenceId IS NOT NULL") + override fun deleteTrackedChanges(): Int + @Query("SELECT id FROM $TABLE_TEMPORARY_TARGETS ORDER BY id DESC limit 1") fun getLastId(): Maybe diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/TherapyEventDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/TherapyEventDao.kt index 633e262a51..4a170f7fae 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/TherapyEventDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/TherapyEventDao.kt @@ -2,9 +2,7 @@ package info.nightscout.androidaps.database.daos import androidx.room.Dao import androidx.room.Query -import info.nightscout.androidaps.database.TABLE_TEMPORARY_TARGETS import info.nightscout.androidaps.database.TABLE_THERAPY_EVENTS -import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.TherapyEvent import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.core.Single @@ -18,6 +16,12 @@ internal interface TherapyEventDao : TraceableDao { @Query("DELETE FROM $TABLE_THERAPY_EVENTS") override fun deleteAllEntries() + @Query("DELETE FROM $TABLE_THERAPY_EVENTS WHERE timestamp < :than") + override fun deleteOlderThan(than: Long): Int + + @Query("DELETE FROM $TABLE_THERAPY_EVENTS WHERE referenceId IS NOT NULL") + override fun deleteTrackedChanges(): Int + @Query("SELECT id FROM $TABLE_THERAPY_EVENTS ORDER BY id DESC limit 1") fun getLastId(): Maybe diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/TotalDailyDoseDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/TotalDailyDoseDao.kt index 1a6d578d2c..f630a6ef20 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/TotalDailyDoseDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/TotalDailyDoseDao.kt @@ -8,7 +8,6 @@ import info.nightscout.androidaps.database.entities.TotalDailyDose import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.core.Single -@Suppress("FunctionName") @Dao internal interface TotalDailyDoseDao : TraceableDao { @@ -18,6 +17,12 @@ internal interface TotalDailyDoseDao : TraceableDao { @Query("DELETE FROM $TABLE_TOTAL_DAILY_DOSES") override fun deleteAllEntries() + @Query("DELETE FROM $TABLE_TOTAL_DAILY_DOSES WHERE timestamp < :than") + override fun deleteOlderThan(than: Long): Int + + @Query("DELETE FROM $TABLE_TOTAL_DAILY_DOSES WHERE referenceId IS NOT NULL") + override fun deleteTrackedChanges(): Int + @Query("SELECT * FROM $TABLE_TOTAL_DAILY_DOSES WHERE pumpId = :pumpId AND pumpType = :pumpType AND pumpSerial = :pumpSerial AND referenceId IS NULL") fun findByPumpIds(pumpId: Long, pumpType: InterfaceIDs.PumpType, pumpSerial: String): TotalDailyDose? diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/TraceableDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/TraceableDao.kt index b9f58db158..080987c185 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/TraceableDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/TraceableDao.kt @@ -11,7 +11,8 @@ internal interface TraceableDao : TraceableDaoWorkaround> + fun deleteOlderThan(than: Long): Int + fun deleteTrackedChanges(): Int @Insert fun insert(entry: T): Long @@ -49,7 +50,7 @@ internal fun TraceableDao.updateExistingEntryImpl(entr val lastModified = System.currentTimeMillis() entry.dateCreated = lastModified val current = findById(entry.id) - ?: throw IllegalArgumentException("The entry with the specified ID does not exist.") + ?: throw IllegalArgumentException("The entry with the specified ID does not exist.") if (current.referenceId != null) throw IllegalArgumentException("The entry with the specified ID is historic and cannot be updated.") entry.version = current.version + 1 update(entry) diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/UserEntryDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/UserEntryDao.kt index 83331c02fd..a5f1979c35 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/UserEntryDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/UserEntryDao.kt @@ -14,6 +14,9 @@ interface UserEntryDao { @Insert fun insert(userEntry: UserEntry) + @Query("DELETE FROM $TABLE_USER_ENTRY WHERE timestamp < :than") + fun deleteOlderThan(than: Long): Int + @Query("SELECT * FROM $TABLE_USER_ENTRY ORDER BY id DESC") fun getAll(): Single> diff --git a/database/src/main/java/info/nightscout/androidaps/database/daos/VersionChangeDao.kt b/database/src/main/java/info/nightscout/androidaps/database/daos/VersionChangeDao.kt index 3004fc5f73..c691981c50 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/daos/VersionChangeDao.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/daos/VersionChangeDao.kt @@ -3,11 +3,8 @@ package info.nightscout.androidaps.database.daos import androidx.room.Dao import androidx.room.Insert import androidx.room.Query -import info.nightscout.androidaps.database.TABLE_TEMPORARY_TARGETS import info.nightscout.androidaps.database.TABLE_VERSION_CHANGES -import info.nightscout.androidaps.database.entities.TemporaryTarget import info.nightscout.androidaps.database.entities.VersionChange -import io.reactivex.rxjava3.core.Single @Dao interface VersionChangeDao { @@ -15,6 +12,9 @@ interface VersionChangeDao { @Insert fun insert(versionChange: VersionChange) + @Query("DELETE FROM $TABLE_VERSION_CHANGES WHERE timestamp < :than") + fun deleteOlderThan(than: Long): Int + @Query("SELECT * FROM $TABLE_VERSION_CHANGES ORDER BY id DESC LIMIT 1") fun getMostRecentVersionChange(): VersionChange? diff --git a/database/src/main/java/info/nightscout/androidaps/database/entities/UserEntry.kt b/database/src/main/java/info/nightscout/androidaps/database/entities/UserEntry.kt index 161b7fffe4..53e012c85e 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/entities/UserEntry.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/entities/UserEntry.kt @@ -97,6 +97,7 @@ data class UserEntry( EXPORT_SETTINGS (ColorGroup.Aaps), IMPORT_SETTINGS (ColorGroup.Aaps), RESET_DATABASES (ColorGroup.Aaps), + CLEANUP_DATABASES (ColorGroup.Aaps), EXPORT_DATABASES (ColorGroup.Aaps), IMPORT_DATABASES (ColorGroup.Aaps), OTP_EXPORT (ColorGroup.Aaps),