Cleanup the account to restore some storage and optimize the database.
(context: &Context)
| 782 | |
| 783 | /// Cleanup the account to restore some storage and optimize the database. |
| 784 | pub async fn housekeeping(context: &Context) -> Result<()> { |
| 785 | let Ok(_housekeeping_lock) = context.housekeeping_mutex.try_lock() else { |
| 786 | // Housekeeping is already running in another thread, do nothing. |
| 787 | return Ok(()); |
| 788 | }; |
| 789 | // Setting `Config::LastHousekeeping` at the beginning avoids endless loops when things do not |
| 790 | // work out for whatever reason or are interrupted by the OS. |
| 791 | if let Err(e) = context |
| 792 | .set_config_internal(Config::LastHousekeeping, Some(&time().to_string())) |
| 793 | .await |
| 794 | { |
| 795 | warn!(context, "Can't set config: {e:#}."); |
| 796 | } |
| 797 | |
| 798 | http_cache_cleanup(context) |
| 799 | .await |
| 800 | .context("Failed to cleanup HTTP cache") |
| 801 | .log_err(context) |
| 802 | .ok(); |
| 803 | migrations::msgs_to_key_contacts(context) |
| 804 | .await |
| 805 | .context("migrations::msgs_to_key_contacts") |
| 806 | .log_err(context) |
| 807 | .ok(); |
| 808 | |
| 809 | if let Err(err) = remove_unused_files(context).await { |
| 810 | warn!( |
| 811 | context, |
| 812 | "Housekeeping: cannot remove unused files: {:#}.", err |
| 813 | ); |
| 814 | } |
| 815 | |
| 816 | if let Err(err) = start_ephemeral_timers(context).await { |
| 817 | warn!( |
| 818 | context, |
| 819 | "Housekeeping: cannot start ephemeral timers: {:#}.", err |
| 820 | ); |
| 821 | } |
| 822 | |
| 823 | if let Err(err) = prune_tombstones(&context.sql).await { |
| 824 | warn!( |
| 825 | context, |
| 826 | "Housekeeping: Cannot prune message tombstones: {:#}.", err |
| 827 | ); |
| 828 | } |
| 829 | |
| 830 | if let Err(err) = incremental_vacuum(context).await { |
| 831 | warn!(context, "Failed to run incremental vacuum: {err:#}."); |
| 832 | } |
| 833 | // Work around possible checkpoint starvations (there were cases reported when a WAL file is |
| 834 | // bigger than 200M) and also make sure we truncate the WAL periodically. Auto-checkponting does |
| 835 | // not normally truncate the WAL (unless the `journal_size_limit` pragma is set), see |
| 836 | // https://www.sqlite.org/wal.html. |
| 837 | if let Err(err) = Sql::wal_checkpoint(&context.sql, context).await { |
| 838 | warn!(context, "wal_checkpoint() failed: {err:#}."); |
| 839 | debug_assert!(false); |
| 840 | } |
| 841 |