-
-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathjobs.go
119 lines (99 loc) · 3.02 KB
/
jobs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package jobs
import (
"github.com/go-co-op/gocron"
"github.com/reaper47/recipya/internal/app"
"github.com/reaper47/recipya/internal/services"
"io/fs"
"log/slog"
"os"
"path/filepath"
"slices"
"sort"
"strconv"
"time"
)
// ScheduleCronJobs schedules cron jobs for the web app. It starts the following jobs:
//
// - Clean Media: Removes unreferenced images and videos from the data folder to save space.
//
// - Send queued emails
//
// - Backup data
//
// - Check for a new release
func ScheduleCronJobs(repo services.RepositoryService, files services.FilesService, email services.EmailService) {
scheduler := gocron.NewScheduler(time.UTC)
// Clean Images
_, _ = scheduler.Every(1).MonthLastDay().Do(func() {
images, videos := repo.Media()
numImages, numBytesImages := cleanMedia(os.DirFS(app.ImagesDir), images, func(file string) error {
_ = os.Remove(filepath.Join(app.ThumbnailsDir, file))
return os.Remove(filepath.Join(app.ImagesDir, file))
})
numVideos, numBytesVideos := cleanMedia(os.DirFS(app.VideosDir), videos, func(file string) error {
return os.Remove(filepath.Join(app.VideosDir, file))
})
var s string
if numBytesImages > 0 || numBytesVideos > 0 {
s = "(" + strconv.FormatFloat(float64(numBytesImages+numBytesVideos)/(1<<20), 'f', 2, 64) + " MB)"
}
slog.Info("Ran CleanMedia job", "numImagesRemoved", numImages, "numVideosRemoved", numVideos, "spaceReclaimed", s)
})
// Send queued emails
_, _ = scheduler.Every(1).Day().At("00:00").Do(func() {
sent, remaining, err := email.SendQueue()
slog.Info("Ran SendQueuedEmails job", "sent", sent, "remaining", remaining, "error", err)
})
// Backup data
_, _ = scheduler.Every(3).Days().Do(func() {
err := files.BackupGlobal()
if err != nil {
slog.Error("Global backup failed", "error", err)
return
}
err = files.BackupUsersData(repo)
if err != nil {
slog.Error("User backups failed", "error", err)
return
}
slog.Info("Backup successful")
})
// Check for a new release
_, _ = scheduler.Every(3).Days().Do(func() {
info, err := repo.CheckUpdate(files)
if err != nil {
slog.Error("Check for update failed", "error", err)
return
}
app.Info.IsUpdateAvailable = info.IsUpdateAvailable
app.Info.LastCheckedUpdateAt = info.LastCheckedUpdateAt
app.Info.LastUpdatedAt = info.LastUpdatedAt
slog.Info("Checked for an application update")
})
scheduler.StartAsync()
}
func cleanMedia(dir fs.FS, used []string, rmFileFunc func(path string) error) (numFilesDeleted, numBytesDeleted int64) {
sort.Strings(used)
_ = fs.WalkDir(dir, ".", func(path string, d fs.DirEntry, _ error) error {
if path == "." || d.IsDir() {
return nil
}
_, found := slices.BinarySearch(used, d.Name())
if !found {
info, err := d.Info()
if err != nil {
slog.Error("Clean media dir walk", "error", err)
return err
}
err = rmFileFunc(path)
if err != nil {
slog.Error("Clean media walk", "error", err, "path", path)
return err
}
numFilesDeleted++
numBytesDeleted += info.Size()
}
return nil
})
return
}