github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/worker/trash/trash.go (about) 1 package trash 2 3 import ( 4 "fmt" 5 "runtime" 6 "time" 7 8 "github.com/cozy/cozy-stack/model/job" 9 "github.com/cozy/cozy-stack/model/vfs" 10 "github.com/cozy/cozy-stack/pkg/config/config" 11 "github.com/cozy/cozy-stack/pkg/consts" 12 "github.com/cozy/cozy-stack/pkg/couchdb" 13 "github.com/cozy/cozy-stack/pkg/couchdb/mango" 14 "github.com/hashicorp/go-multierror" 15 "github.com/justincampbell/bigduration" 16 ) 17 18 func init() { 19 job.AddWorker(&job.WorkerConfig{ 20 WorkerType: "trash-files", 21 Concurrency: runtime.NumCPU() * 4, 22 MaxExecCount: 2, 23 Reserved: true, 24 Timeout: 2 * time.Hour, 25 WorkerFunc: WorkerTrashFiles, 26 }) 27 28 job.AddWorker(&job.WorkerConfig{ 29 WorkerType: "clean-old-trashed", 30 Concurrency: runtime.NumCPU() * 4, 31 MaxExecCount: 2, 32 Reserved: true, 33 Timeout: 2 * time.Hour, 34 WorkerFunc: WorkerCleanOldTrashed, 35 }) 36 } 37 38 // WorkerTrashFiles is a worker to remove files in Swift after they have been 39 // removed from CouchDB. It is used when cleaning the trash, as removing a lot 40 // of files from Swift can take some time. 41 func WorkerTrashFiles(ctx *job.TaskContext) error { 42 opts := vfs.TrashJournal{} 43 if err := ctx.UnmarshalMessage(&opts); err != nil { 44 return err 45 } 46 fs := ctx.Instance.VFS() 47 if err := fs.EnsureErased(opts); err != nil { 48 ctx.Logger().WithField("critical", "true"). 49 Errorf("Error: %s", err) 50 return err 51 } 52 return nil 53 } 54 55 // WorkerCleanOldTrashed is a worker used to automatically delete files and 56 // directories that are in the trash for too long. The threshold for deletion 57 // is configurable per context in the config file, via the 58 // fs.auto_clean_trashed_after parameter. 59 func WorkerCleanOldTrashed(ctx *job.TaskContext) error { 60 cfg := config.GetConfig().Fs.AutoCleanTrashedAfter 61 after, ok := cfg[ctx.Instance.ContextName] 62 if !ok || after == "" { 63 return nil 64 } 65 delay, err := bigduration.ParseDuration(after) 66 if err != nil { 67 ctx.Logger().WithField("critical", "true"). 68 Errorf("Invalid config for auto_clean_trashed_after: %s", err) 69 return err 70 } 71 before := time.Now().Add(-delay) 72 73 var list []*vfs.DirOrFileDoc 74 sel := mango.And( 75 mango.Equal("dir_id", consts.TrashDirID), 76 mango.Lt("updated_at", before), 77 ) 78 req := &couchdb.FindRequest{ 79 UseIndex: "by-dir-id-updated-at", 80 Selector: sel, 81 Limit: 1000, 82 } 83 if _, err := couchdb.FindDocsRaw(ctx.Instance, consts.Files, req, &list); err != nil { 84 return err 85 } 86 87 var errm error 88 fs := ctx.Instance.VFS() 89 push := pushTrashJob(fs) 90 for _, item := range list { 91 d, f := item.Refine() 92 if f != nil { 93 err = fs.DestroyFile(f) 94 } else if d != nil { 95 err = fs.DestroyDirAndContent(d, push) 96 } else { 97 err = fmt.Errorf("Invalid type for %v", item) 98 } 99 if err != nil { 100 errm = multierror.Append(errm, err) 101 } 102 } 103 return errm 104 } 105 106 func pushTrashJob(fs vfs.VFS) func(vfs.TrashJournal) error { 107 return func(journal vfs.TrashJournal) error { 108 return fs.EnsureErased(journal) 109 } 110 }