diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/database/HistoryDao.kt b/app/src/main/java/com/greenart7c3/nostrsigner/database/HistoryDao.kt index 2f537825..3bb019f9 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/database/HistoryDao.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/database/HistoryDao.kt @@ -13,6 +13,8 @@ import androidx.room.Transaction import com.greenart7c3.nostrsigner.Amber import com.greenart7c3.nostrsigner.models.Permission +private const val MAX_CONTENT_LENGTH = 500 + @Dao interface HistoryDao { @Query("SELECT * FROM history where pkKey = :pk ORDER BY time DESC") @@ -38,6 +40,13 @@ interface HistoryDao { @Query("DELETE FROM history where pkKey = :pk") suspend fun deleteHistory(pk: String) + @Query("SELECT COUNT(*) FROM history") + suspend fun getCount(): Long + + @Query("DELETE FROM history WHERE id NOT IN (SELECT id FROM history ORDER BY time DESC LIMIT :keepCount)") + @Transaction + suspend fun deleteExcessHistory(keepCount: Int): Int + @Query("SELECT COUNT(*) FROM history WHERE time < :time") @Transaction suspend fun countOldHistory(time: Long): Long @@ -65,6 +74,7 @@ interface HistoryDao { val permission = Permission(entity.type.toLowerCase(Locale.current), entity.kind) val localEntity = entity.copy( translatedPermission = permission.toLocalizedString(Amber.instance, true), + content = if (entity.content.length > MAX_CONTENT_LENGTH) entity.content.take(MAX_CONTENT_LENGTH) else entity.content, ) innerAddHistory(localEntity) npub?.let { diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/database/LogDao.kt b/app/src/main/java/com/greenart7c3/nostrsigner/database/LogDao.kt index fda920a2..aae1ae33 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/database/LogDao.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/database/LogDao.kt @@ -29,6 +29,13 @@ interface LogDao { @Query("SELECT * FROM amber_log where url = :url ORDER BY time DESC") fun getLogsByUrlPaging(url: String): PagingSource + @Query("SELECT COUNT(*) FROM amber_log") + suspend fun getCount(): Long + + @Query("DELETE FROM amber_log WHERE id NOT IN (SELECT id FROM amber_log ORDER BY time DESC LIMIT :keepCount)") + @Transaction + suspend fun deleteExcessLogs(keepCount: Int): Int + @Query("DELETE FROM amber_log") @Transaction suspend fun clearLogs() diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/service/ClearLogsWorker.kt b/app/src/main/java/com/greenart7c3/nostrsigner/service/ClearLogsWorker.kt index fd48b196..9fd270b4 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/ClearLogsWorker.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/ClearLogsWorker.kt @@ -8,35 +8,54 @@ import com.greenart7c3.nostrsigner.Amber import com.greenart7c3.nostrsigner.LocalPreferences import com.greenart7c3.nostrsigner.database.LogEntity import com.vitorpamplona.quartz.utils.TimeUtils -import com.vitorpamplona.quartz.utils.TimeUtils.ONE_WEEK import kotlin.coroutines.cancellation.CancellationException +private const val THREE_DAYS_MILLIS = 3 * 24 * 60 * 60 * 1000L +private const val MAX_LOG_ENTRIES = 1000 +private const val MAX_HISTORY_ENTRIES = 2000 + class ClearLogsWorker(appContext: Context, workerParams: WorkerParameters) : CoroutineWorker(appContext, workerParams) { override suspend fun doWork(): Result { LocalPreferences.allSavedAccounts(Amber.instance).forEach { try { val now = System.currentTimeMillis() - val oneWeek = now - (ONE_WEEK * 1000L) + val threeDaysAgo = now - THREE_DAYS_MILLIS val oneWeekAgo = TimeUtils.oneWeekAgo() val historyDatabase = Amber.instance.getHistoryDatabase(it.npub) - val deletedHistory = historyDatabase.dao().deleteOldHistory(oneWeekAgo) + val historyDao = historyDatabase.dao() + + val deletedHistory = historyDao.deleteOldHistory(oneWeekAgo) if (deletedHistory > 0) { Log.d(Amber.TAG, "Deleted $deletedHistory old history entries") } + val excessHistory = historyDao.deleteExcessHistory(MAX_HISTORY_ENTRIES) + if (excessHistory > 0) { + Log.d(Amber.TAG, "Trimmed $excessHistory excess history entries (cap: $MAX_HISTORY_ENTRIES)") + } val logDatabase = Amber.instance.getLogDatabase(it.npub) - val deletedLogs = logDatabase.dao().deleteOldLog(oneWeek) + val logDao = logDatabase.dao() + + val deletedLogs = logDao.deleteOldLog(threeDaysAgo) if (deletedLogs > 0) { Log.d(Amber.TAG, "Deleted $deletedLogs old log entries") } + val excessLogs = logDao.deleteExcessLogs(MAX_LOG_ENTRIES) + if (excessLogs > 0) { + Log.d(Amber.TAG, "Trimmed $excessLogs excess log entries (cap: $MAX_LOG_ENTRIES)") + } + + // Reclaim freed space from SQLite pages + logDatabase.openHelper.writableDatabase.execSQL("VACUUM") + historyDatabase.openHelper.writableDatabase.execSQL("VACUUM") val database = Amber.instance.getDatabase(it.npub) database.dao().updateExpiredPermissions(TimeUtils.now()) val deleted = database.dao().deleteOldApplications(now / 1000) if (deleted > 0) { - logDatabase.dao().insertLog( + logDao.insertLog( LogEntity( id = 0, url = "",