diff --git a/internal/db/sqlite/db_service.go b/internal/db/sqlite/db_service.go index 3786fbc10..647c1fdc1 100644 --- a/internal/db/sqlite/db_service.go +++ b/internal/db/sqlite/db_service.go @@ -8,6 +8,7 @@ package sqlite import ( "context" + "fmt" "time" "github.com/syncthing/syncthing/internal/db" @@ -16,6 +17,7 @@ import ( const ( internalMetaPrefix = "dbsvc" lastMaintKey = "lastMaint" + MaxDeletedFileAge = 180 * 24 * time.Hour ) type Service struct { @@ -24,6 +26,10 @@ type Service struct { internalMeta *db.Typed } +func (s *Service) String() string { + return fmt.Sprintf("sqlite.service@%p", s) +} + func newService(sdb *DB, maintenanceInterval time.Duration) *Service { return &Service{ sdb: sdb, @@ -73,6 +79,9 @@ func (s *Service) periodic(ctx context.Context) error { t1 := time.Now() defer func() { l.Debugln("Periodic done in", time.Since(t1), "+", t1.Sub(t0)) }() + if err := s.garbageCollectOldDeletedLocked(); err != nil { + return wrap(err) + } if err := s.garbageCollectBlocklistsAndBlocksLocked(ctx); err != nil { return wrap(err) } @@ -85,6 +94,22 @@ func (s *Service) periodic(ctx context.Context) error { return nil } +func (s *Service) garbageCollectOldDeletedLocked() error { + // Remove deleted files that are marked as not needed (we have processed + // them) and they were deleted more than MaxDeletedFileAge ago. + res, err := s.sdb.stmt(` + DELETE FROM files + WHERE deleted AND modified < ? AND local_flags & {{.FlagLocalNeeded}} == 0 + `).Exec(time.Now().Add(-MaxDeletedFileAge).UnixNano()) + if err != nil { + return wrap(err) + } + if aff, err := res.RowsAffected(); err == nil { + l.Debugln("Removed old deleted file records:", aff) + } + return nil +} + func (s *Service) garbageCollectBlocklistsAndBlocksLocked(ctx context.Context) error { // Remove all blocklists not referred to by any files and, by extension, // any blocks not referred to by a blocklist. This is an expensive diff --git a/lib/syncthing/utils.go b/lib/syncthing/utils.go index 41fc77545..019b59eaa 100644 --- a/lib/syncthing/utils.go +++ b/lib/syncthing/utils.go @@ -251,6 +251,11 @@ func TryMigrateDatabase() error { return err } _ = snap.WithHaveSequence(0, func(fi protocol.FileInfo) bool { + if fi.Deleted && time.Since(fi.ModTime()) > sqlite.MaxDeletedFileAge { + // Skip deleted files that match the garbage collection + // criteria in the database + return true + } fis <- fi return true })