| 754 | // This only works if auto_vacuum is enabled. |
| 755 | #[expect(clippy::arithmetic_side_effects)] |
| 756 | async fn incremental_vacuum(context: &Context) -> Result<()> { |
| 757 | context |
| 758 | .sql |
| 759 | .call_write(move |conn| { |
| 760 | let mut stmt = conn |
| 761 | .prepare("PRAGMA incremental_vacuum") |
| 762 | .context("Failed to prepare incremental_vacuum statement")?; |
| 763 | |
| 764 | // It is important to step the statement until it returns no more rows. |
| 765 | // Otherwise it will not free as many pages as it can: |
| 766 | // <https://stackoverflow.com/questions/53746807/sqlite-incremental-vacuum-removing-only-one-free-page>. |
| 767 | let mut rows = stmt |
| 768 | .query(()) |
| 769 | .context("Failed to run incremental_vacuum statement")?; |
| 770 | let mut row_count = 0; |
| 771 | while let Some(_row) = rows |
| 772 | .next() |
| 773 | .context("Failed to step incremental_vacuum statement")? |
| 774 | { |
| 775 | row_count += 1; |
| 776 | } |
| 777 | info!(context, "Incremental vacuum freed {row_count} pages."); |
| 778 | Ok(()) |
| 779 | }) |
| 780 | .await |
| 781 | } |
| 782 | |
| 783 | /// Cleanup the account to restore some storage and optimize the database. |
| 784 | pub async fn housekeeping(context: &Context) -> Result<()> { |