1
0
Fork 0
mirror of https://github.com/miniflux/v2.git synced 2025-08-26 18:21:01 +00:00
miniflux-v2/internal/cli/cleanup_tasks.go
jvoisin 5c26e06780 feat(entry): keep only metadata for removed entries
This should significantly shrink the space taken by miniflux' database:

```sql
miniflux=#
SELECT
  relname, pg_size_pretty(pg_total_relation_size(relname::regclass))
FROM
  pg_catalog.pg_statio_user_tables
ORDER BY
  pg_total_relation_size(relname::regclass)
DESC;

       relname        | pg_size_pretty
----------------------+----------------
 entries              | 158 MB
 icons                | 3312 kB
 enclosures           | 1568 kB
 sessions             | 1048 kB
 feeds                | 288 kB
 feed_icons           | 72 kB
 users                | 64 kB
 user_sessions        | 64 kB
 categories           | 48 kB
 integrations         | 32 kB
 api_keys             | 32 kB
 webauthn_credentials | 24 kB
 schema_version       | 16 kB
 acme_cache           | 16 kB
(14 rows)

miniflux=#
```

This should close #3524
2025-08-16 20:57:59 -07:00

56 lines
2.1 KiB
Go

// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package cli // import "miniflux.app/v2/internal/cli"
import (
"log/slog"
"time"
"miniflux.app/v2/internal/config"
"miniflux.app/v2/internal/metric"
"miniflux.app/v2/internal/model"
"miniflux.app/v2/internal/storage"
)
func runCleanupTasks(store *storage.Storage) {
nbSessions := store.CleanOldSessions(config.Opts.CleanupRemoveSessionsDays())
nbUserSessions := store.CleanOldUserSessions(config.Opts.CleanupRemoveSessionsDays())
slog.Info("Sessions cleanup completed",
slog.Int64("application_sessions_removed", nbSessions),
slog.Int64("user_sessions_removed", nbUserSessions),
)
startTime := time.Now()
if rowsAffected, err := store.ArchiveEntries(model.EntryStatusRead, config.Opts.CleanupArchiveReadDays(), config.Opts.CleanupArchiveBatchSize()); err != nil {
slog.Error("Unable to archive read entries", slog.Any("error", err))
} else {
slog.Info("Archiving read entries completed",
slog.Int64("read_entries_archived", rowsAffected),
)
if config.Opts.HasMetricsCollector() {
metric.ArchiveEntriesDuration.WithLabelValues(model.EntryStatusRead).Observe(time.Since(startTime).Seconds())
}
}
startTime = time.Now()
if rowsAffected, err := store.ArchiveEntries(model.EntryStatusUnread, config.Opts.CleanupArchiveUnreadDays(), config.Opts.CleanupArchiveBatchSize()); err != nil {
slog.Error("Unable to archive unread entries", slog.Any("error", err))
} else {
slog.Info("Archiving unread entries completed",
slog.Int64("unread_entries_archived", rowsAffected),
)
if config.Opts.HasMetricsCollector() {
metric.ArchiveEntriesDuration.WithLabelValues(model.EntryStatusUnread).Observe(time.Since(startTime).Seconds())
}
}
if rowsAffected, err := store.DeleteContentRemovedEntries(); err != nil {
slog.Error("Unable to delete the content of removed entries", slog.Any("error", err))
} else {
slog.Info("Deleting content of removed entries completed",
slog.Int64("removed_entries_content_removed", rowsAffected))
}
}