mirror of
https://github.com/greenart7c3/Amber.git
synced 2026-10-06 11:28:22 +00:00
Optimize log/history storage to reduce disk usage
- Add count-based caps: keep at most 1000 log entries and 2000 history entries per account, pruning oldest beyond that on each cleanup run - Reduce log retention from 7 days to 3 days (relay connection events are ephemeral and accumulate quickly) - Truncate history content field to 500 chars before storing to avoid large event payloads inflating the database - Run VACUUM on both databases after each cleanup so SQLite actually reclaims freed page space on disk https://claude.ai/code/session_01BCMhs2yA9XNUvfaX4sqsfv
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -29,6 +29,13 @@ interface LogDao {
|
||||
@Query("SELECT * FROM amber_log where url = :url ORDER BY time DESC")
|
||||
fun getLogsByUrlPaging(url: String): PagingSource<Int, LogEntity>
|
||||
|
||||
@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()
|
||||
|
||||
@@ -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 = "",
|
||||
|
||||
Reference in New Issue
Block a user