-
Notifications
You must be signed in to change notification settings - Fork 0
/
retention.go
119 lines (98 loc) · 2.49 KB
/
retention.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 duckron
import (
"io/fs"
"log"
"os"
"time"
)
var (
ErrFolderDeletionFailed = newError("folder", "failed to delete snapshot")
)
type folderMetadata struct {
name string
createdAt time.Time
}
type retentionManager struct {
client DatabaseConnection
options *retentionOptions
timer *Timer
}
type retentionOptions struct {
interval time.Duration
path string
}
func NewRetentionManager(client DatabaseConnection, options *retentionOptions) (*retentionManager, *Error) {
if options.interval == 0 {
options = &retentionOptions{
interval: time.Hour * 24,
}
}
if err := client.Ping(); err != nil {
return nil, ErrConnectionFailed.wrap(err)
}
timer := NewTimer(options.interval)
return &retentionManager{client: client, options: options, timer: timer}, nil
}
func (rm *retentionManager) clean(errChan chan *Error) *Error {
go func(errChan chan *Error) {
rm.timer.Start(
func() *Error {
log.Println("Cleaning snapshots")
files, err := rm.readFoldersInPath(rm.options.path)
if err != nil {
return ErrSnapshotFailed.wrap(err)
}
fMeta, err := rm.readSnapshotTimestamps(files)
if err != nil {
return ErrSnapshotFailed.wrap(err)
}
if err := rm.deleteOldSnapshots(fMeta); err != nil {
errChan <- err
return ErrFolderDeletionFailed
}
return nil
},
)
}(errChan)
return nil
}
func (rm *retentionManager) readFoldersInPath(path string) ([]fs.FileInfo, error) {
folder, err := os.Open(path)
if err != nil {
return nil, err
}
defer folder.Close()
files, err := folder.Readdir(0)
if err != nil {
return nil, err
}
return files, nil
}
func (rm *retentionManager) readSnapshotTimestamps(file []fs.FileInfo) ([]*folderMetadata, error) {
var fMeta []*folderMetadata
if len(file) == 0 {
return fMeta, nil
}
for _, file := range file {
fMeta = append(fMeta, &folderMetadata{
name: file.Name(),
createdAt: file.ModTime(),
})
}
return fMeta, nil
}
func (rm *retentionManager) deleteOldSnapshots(files []*folderMetadata) *Error {
for _, file := range files {
if time.Since(file.createdAt).Hours() > float64(rm.options.interval.Hours()) {
log.Println("Deleting snapshot", file.name)
log.Println("Snapshot created at", file.createdAt)
log.Println("Snapshot age", time.Since(file.createdAt).Hours())
err := os.RemoveAll(rm.options.path + "/" + file.name)
if err != nil {
return ErrFolderDeletionFailed.wrap(err)
}
log.Println("Snapshot deleted", file.name)
}
}
return nil
}