Skip to content

Commit 983291c

Browse files
gudvinrfguillot
authored andcommitted
refactor(cli): use time.Duration for cleanup tasks
1 parent 7060ecc commit 983291c

File tree

8 files changed

+94
-45
lines changed

8 files changed

+94
-45
lines changed

internal/cli/cleanup_tasks.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ import (
1414
)
1515

1616
func runCleanupTasks(store *storage.Storage) {
17-
nbSessions := store.CleanOldSessions(config.Opts.CleanupRemoveSessionsDays())
18-
nbUserSessions := store.CleanOldUserSessions(config.Opts.CleanupRemoveSessionsDays())
17+
nbSessions := store.CleanOldSessions(config.Opts.CleanupRemoveSessionsInterval())
18+
nbUserSessions := store.CleanOldUserSessions(config.Opts.CleanupRemoveSessionsInterval())
1919
slog.Info("Sessions cleanup completed",
2020
slog.Int64("application_sessions_removed", nbSessions),
2121
slog.Int64("user_sessions_removed", nbUserSessions),
2222
)
2323

2424
startTime := time.Now()
25-
if rowsAffected, err := store.ArchiveEntries(model.EntryStatusRead, config.Opts.CleanupArchiveReadDays(), config.Opts.CleanupArchiveBatchSize()); err != nil {
25+
if rowsAffected, err := store.ArchiveEntries(model.EntryStatusRead, config.Opts.CleanupArchiveReadInterval(), config.Opts.CleanupArchiveBatchSize()); err != nil {
2626
slog.Error("Unable to archive read entries", slog.Any("error", err))
2727
} else {
2828
slog.Info("Archiving read entries completed",
@@ -35,7 +35,7 @@ func runCleanupTasks(store *storage.Storage) {
3535
}
3636

3737
startTime = time.Now()
38-
if rowsAffected, err := store.ArchiveEntries(model.EntryStatusUnread, config.Opts.CleanupArchiveUnreadDays(), config.Opts.CleanupArchiveBatchSize()); err != nil {
38+
if rowsAffected, err := store.ArchiveEntries(model.EntryStatusUnread, config.Opts.CleanupArchiveUnreadInterval(), config.Opts.CleanupArchiveBatchSize()); err != nil {
3939
slog.Error("Unable to archive unread entries", slog.Any("error", err))
4040
} else {
4141
slog.Info("Archiving unread entries completed",

internal/config/config_test.go

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -645,12 +645,22 @@ func TestDefaultCleanupArchiveReadDaysValue(t *testing.T) {
645645
t.Fatalf(`Parsing failure: %v`, err)
646646
}
647647

648-
expected := 60
649-
result := opts.CleanupArchiveReadDays()
648+
expected := 60 * 24 * time.Hour
649+
result := opts.CleanupArchiveReadInterval()
650650

651651
if result != expected {
652652
t.Fatalf(`Unexpected CLEANUP_ARCHIVE_READ_DAYS value, got %v instead of %v`, result, expected)
653653
}
654+
655+
sorted := opts.SortedOptions(false)
656+
i := slices.IndexFunc(sorted, func(opt *option) bool {
657+
return opt.Key == "CLEANUP_ARCHIVE_READ_DAYS"
658+
})
659+
660+
expectedSerialized := 60
661+
if got := sorted[i].Value; got != expectedSerialized {
662+
t.Fatalf(`Unexpected value in option output, got %q instead of %q`, got, expectedSerialized)
663+
}
654664
}
655665

656666
func TestCleanupArchiveReadDays(t *testing.T) {
@@ -664,12 +674,22 @@ func TestCleanupArchiveReadDays(t *testing.T) {
664674
t.Fatalf(`Parsing failure: %v`, err)
665675
}
666676

667-
expected := 7
668-
result := opts.CleanupArchiveReadDays()
677+
expected := 7 * 24 * time.Hour
678+
result := opts.CleanupArchiveReadInterval()
669679

670680
if result != expected {
671681
t.Fatalf(`Unexpected CLEANUP_ARCHIVE_READ_DAYS value, got %v instead of %v`, result, expected)
672682
}
683+
684+
sorted := opts.SortedOptions(false)
685+
i := slices.IndexFunc(sorted, func(opt *option) bool {
686+
return opt.Key == "CLEANUP_ARCHIVE_READ_DAYS"
687+
})
688+
689+
expectedSerialized := 7
690+
if got := sorted[i].Value; got != expectedSerialized {
691+
t.Fatalf(`Unexpected value in option output, got %q instead of %q`, got, expectedSerialized)
692+
}
673693
}
674694

675695
func TestDefaultCleanupRemoveSessionsDaysValue(t *testing.T) {
@@ -681,12 +701,22 @@ func TestDefaultCleanupRemoveSessionsDaysValue(t *testing.T) {
681701
t.Fatalf(`Parsing failure: %v`, err)
682702
}
683703

684-
expected := 30
685-
result := opts.CleanupRemoveSessionsDays()
704+
expected := 30 * 24 * time.Hour
705+
result := opts.CleanupRemoveSessionsInterval()
686706

687707
if result != expected {
688708
t.Fatalf(`Unexpected CLEANUP_REMOVE_SESSIONS_DAYS value, got %v instead of %v`, result, expected)
689709
}
710+
711+
sorted := opts.SortedOptions(false)
712+
i := slices.IndexFunc(sorted, func(opt *option) bool {
713+
return opt.Key == "CLEANUP_REMOVE_SESSIONS_DAYS"
714+
})
715+
716+
expectedSerialized := 30
717+
if got := sorted[i].Value; got != expectedSerialized {
718+
t.Fatalf(`Unexpected value in option output, got %q instead of %q`, got, expectedSerialized)
719+
}
690720
}
691721

692722
func TestCleanupRemoveSessionsDays(t *testing.T) {
@@ -699,12 +729,22 @@ func TestCleanupRemoveSessionsDays(t *testing.T) {
699729
t.Fatalf(`Parsing failure: %v`, err)
700730
}
701731

702-
expected := 7
703-
result := opts.CleanupRemoveSessionsDays()
732+
expected := 7 * 24 * time.Hour
733+
result := opts.CleanupRemoveSessionsInterval()
704734

705735
if result != expected {
706736
t.Fatalf(`Unexpected CLEANUP_REMOVE_SESSIONS_DAYS value, got %v instead of %v`, result, expected)
707737
}
738+
739+
sorted := opts.SortedOptions(false)
740+
i := slices.IndexFunc(sorted, func(opt *option) bool {
741+
return opt.Key == "CLEANUP_REMOVE_SESSIONS_DAYS"
742+
})
743+
744+
expectedSerialized := 7
745+
if got := sorted[i].Value; got != expectedSerialized {
746+
t.Fatalf(`Unexpected value in option output, got %q instead of %q`, got, expectedSerialized)
747+
}
708748
}
709749

710750
func TestDefaultWorkerPoolSizeValue(t *testing.T) {

internal/config/options.go

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ const (
4848
defaultKeyFile = ""
4949
defaultCertDomain = ""
5050
defaultCleanupFrequency = 24 * time.Hour
51-
defaultCleanupArchiveReadDays = 60
52-
defaultCleanupArchiveUnreadDays = 180
51+
defaultCleanupArchiveReadInterval = 60 * 24 * time.Hour
52+
defaultCleanupArchiveUnreadInterval = 180 * 24 * time.Hour
5353
defaultCleanupArchiveBatchSize = 10000
54-
defaultCleanupRemoveSessionsDays = 30
54+
defaultCleanupRemoveSessionsInterval = 30 * 24 * time.Hour
5555
defaultMediaProxyHTTPClientTimeout = 120 * time.Second
5656
defaultMediaProxyMode = "http-only"
5757
defaultMediaResourceTypes = "image"
@@ -126,10 +126,10 @@ type options struct {
126126
certDomain string
127127
certKeyFile string
128128
cleanupFrequencyInterval time.Duration
129-
cleanupArchiveReadDays int
130-
cleanupArchiveUnreadDays int
129+
cleanupArchiveReadInterval time.Duration
130+
cleanupArchiveUnreadInterval time.Duration
131131
cleanupArchiveBatchSize int
132-
cleanupRemoveSessionsDays int
132+
cleanupRemoveSessionsInterval time.Duration
133133
forceRefreshInterval time.Duration
134134
batchSize int
135135
schedulerEntryFrequencyMinInterval time.Duration
@@ -210,10 +210,10 @@ func NewOptions() *options {
210210
certDomain: defaultCertDomain,
211211
certKeyFile: defaultKeyFile,
212212
cleanupFrequencyInterval: defaultCleanupFrequency,
213-
cleanupArchiveReadDays: defaultCleanupArchiveReadDays,
214-
cleanupArchiveUnreadDays: defaultCleanupArchiveUnreadDays,
213+
cleanupArchiveReadInterval: defaultCleanupArchiveReadInterval,
214+
cleanupArchiveUnreadInterval: defaultCleanupArchiveUnreadInterval,
215215
cleanupArchiveBatchSize: defaultCleanupArchiveBatchSize,
216-
cleanupRemoveSessionsDays: defaultCleanupRemoveSessionsDays,
216+
cleanupRemoveSessionsInterval: defaultCleanupRemoveSessionsInterval,
217217
pollingFrequency: defaultPollingFrequency,
218218
forceRefreshInterval: defaultForceRefreshInterval,
219219
batchSize: defaultBatchSize,
@@ -366,24 +366,24 @@ func (o *options) CleanupFrequency() time.Duration {
366366
return o.cleanupFrequencyInterval
367367
}
368368

369-
// CleanupArchiveReadDays returns the number of days after which marking read items as removed.
370-
func (o *options) CleanupArchiveReadDays() int {
371-
return o.cleanupArchiveReadDays
369+
// CleanupArchiveReadDays returns the interval after which marking read items as removed.
370+
func (o *options) CleanupArchiveReadInterval() time.Duration {
371+
return o.cleanupArchiveReadInterval
372372
}
373373

374-
// CleanupArchiveUnreadDays returns the number of days after which marking unread items as removed.
375-
func (o *options) CleanupArchiveUnreadDays() int {
376-
return o.cleanupArchiveUnreadDays
374+
// CleanupArchiveUnreadDays returns the interval after which marking unread items as removed.
375+
func (o *options) CleanupArchiveUnreadInterval() time.Duration {
376+
return o.cleanupArchiveUnreadInterval
377377
}
378378

379379
// CleanupArchiveBatchSize returns the number of entries to archive for each interval.
380380
func (o *options) CleanupArchiveBatchSize() int {
381381
return o.cleanupArchiveBatchSize
382382
}
383383

384-
// CleanupRemoveSessionsDays returns the number of days after which to remove sessions.
385-
func (o *options) CleanupRemoveSessionsDays() int {
386-
return o.cleanupRemoveSessionsDays
384+
// CleanupRemoveSessionsDays returns the interval after which to remove sessions.
385+
func (o *options) CleanupRemoveSessionsInterval() time.Duration {
386+
return o.cleanupRemoveSessionsInterval
387387
}
388388

389389
// WorkerPoolSize returns the number of background worker.
@@ -723,9 +723,9 @@ func (o *options) SortedOptions(redactSecret bool) []*option {
723723
"CERT_FILE": o.certFile,
724724
"CLEANUP_FREQUENCY_HOURS": int(o.cleanupFrequencyInterval.Hours()),
725725
"CLEANUP_ARCHIVE_BATCH_SIZE": o.cleanupArchiveBatchSize,
726-
"CLEANUP_ARCHIVE_READ_DAYS": o.cleanupArchiveReadDays,
727-
"CLEANUP_ARCHIVE_UNREAD_DAYS": o.cleanupArchiveUnreadDays,
728-
"CLEANUP_REMOVE_SESSIONS_DAYS": o.cleanupRemoveSessionsDays,
726+
"CLEANUP_ARCHIVE_READ_DAYS": int(o.cleanupArchiveReadInterval.Hours() / 24),
727+
"CLEANUP_ARCHIVE_UNREAD_DAYS": int(o.cleanupArchiveUnreadInterval.Hours() / 24),
728+
"CLEANUP_REMOVE_SESSIONS_DAYS": int(o.cleanupRemoveSessionsInterval.Hours() / 24),
729729
"CREATE_ADMIN": o.createAdmin,
730730
"DATABASE_CONNECTION_LIFETIME": o.databaseConnectionLifetime,
731731
"DATABASE_MAX_CONNS": o.databaseMaxConns,

internal/config/parser.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,13 +129,13 @@ func (p *parser) parseLines(lines []string) (err error) {
129129
case "CLEANUP_FREQUENCY_HOURS":
130130
p.opts.cleanupFrequencyInterval = parseInterval(value, time.Hour, defaultCleanupFrequency)
131131
case "CLEANUP_ARCHIVE_READ_DAYS":
132-
p.opts.cleanupArchiveReadDays = parseInt(value, defaultCleanupArchiveReadDays)
132+
p.opts.cleanupArchiveReadInterval = parseInterval(value, 24*time.Hour, defaultCleanupArchiveReadInterval)
133133
case "CLEANUP_ARCHIVE_UNREAD_DAYS":
134-
p.opts.cleanupArchiveUnreadDays = parseInt(value, defaultCleanupArchiveUnreadDays)
134+
p.opts.cleanupArchiveUnreadInterval = parseInterval(value, 24*time.Hour, defaultCleanupArchiveUnreadInterval)
135135
case "CLEANUP_ARCHIVE_BATCH_SIZE":
136136
p.opts.cleanupArchiveBatchSize = parseInt(value, defaultCleanupArchiveBatchSize)
137137
case "CLEANUP_REMOVE_SESSIONS_DAYS":
138-
p.opts.cleanupRemoveSessionsDays = parseInt(value, defaultCleanupRemoveSessionsDays)
138+
p.opts.cleanupRemoveSessionsInterval = parseInterval(value, 24*time.Hour, defaultCleanupRemoveSessionsInterval)
139139
case "WORKER_POOL_SIZE":
140140
p.opts.workerPoolSize = parseInt(value, defaultWorkerPoolSize)
141141
case "FORCE_REFRESH_INTERVAL":

internal/http/cookie/cookie.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func New(name, value string, isHTTPS bool, path string) *http.Cookie {
2424
Path: basePath(path),
2525
Secure: isHTTPS,
2626
HttpOnly: true,
27-
Expires: time.Now().Add(time.Duration(config.Opts.CleanupRemoveSessionsDays()) * 24 * time.Hour),
27+
Expires: time.Now().Add(config.Opts.CleanupRemoveSessionsInterval()),
2828
SameSite: http.SameSiteLaxMode,
2929
}
3030
}

internal/storage/entry.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,9 @@ func (s *Storage) RefreshFeedEntries(userID, feedID int64, entries model.Entries
392392
return newEntries, nil
393393
}
394394

395-
// ArchiveEntries changes the status of entries to "removed" after the given number of days.
396-
func (s *Storage) ArchiveEntries(status string, days, limit int) (int64, error) {
397-
if days < 0 || limit <= 0 {
395+
// ArchiveEntries changes the status of entries to "removed" after the interval (24h minimum).
396+
func (s *Storage) ArchiveEntries(status string, interval time.Duration, limit int) (int64, error) {
397+
if interval < 0 || limit <= 0 {
398398
return 0, nil
399399
}
400400

@@ -419,6 +419,8 @@ func (s *Storage) ArchiveEntries(status string, days, limit int) (int64, error)
419419
)
420420
`
421421

422+
days := max(int(interval/(24*time.Hour)), 1)
423+
422424
result, err := s.db.Exec(query, model.EntryStatusRemoved, status, fmt.Sprintf("%d days", days), limit)
423425
if err != nil {
424426
return 0, fmt.Errorf(`store: unable to archive %s entries: %v`, status, err)

internal/storage/session.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"crypto/rand"
88
"database/sql"
99
"fmt"
10+
"time"
1011

1112
"miniflux.app/v2/internal/model"
1213
)
@@ -122,14 +123,17 @@ func (s *Storage) FlushAllSessions() (err error) {
122123
return nil
123124
}
124125

125-
// CleanOldSessions removes sessions older than specified days.
126-
func (s *Storage) CleanOldSessions(days int) int64 {
126+
// CleanOldSessions removes sessions older than specified interval (24h minimum).
127+
func (s *Storage) CleanOldSessions(interval time.Duration) int64 {
127128
query := `
128129
DELETE FROM
129130
sessions
130131
WHERE
131132
created_at < now() - $1::interval
132133
`
134+
135+
days := max(int(interval/(24*time.Hour)), 1)
136+
133137
result, err := s.db.Exec(query, fmt.Sprintf("%d days", days))
134138
if err != nil {
135139
return 0

internal/storage/user_session.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"crypto/rand"
88
"database/sql"
99
"fmt"
10+
"time"
1011

1112
"miniflux.app/v2/internal/model"
1213
)
@@ -43,7 +44,6 @@ func (s *Storage) UserSessions(userID int64) (model.UserSessions, error) {
4344
&session.UserAgent,
4445
&session.IP,
4546
)
46-
4747
if err != nil {
4848
return nil, fmt.Errorf(`store: unable to fetch user session row: %v`, err)
4949
}
@@ -164,14 +164,17 @@ func (s *Storage) RemoveUserSessionByID(userID, sessionID int64) error {
164164
return nil
165165
}
166166

167-
// CleanOldUserSessions removes user sessions older than specified days.
168-
func (s *Storage) CleanOldUserSessions(days int) int64 {
167+
// CleanOldUserSessions removes user sessions older than specified interval (24h minimum).
168+
func (s *Storage) CleanOldUserSessions(interval time.Duration) int64 {
169169
query := `
170170
DELETE FROM
171171
user_sessions
172172
WHERE
173173
created_at < now() - $1::interval
174174
`
175+
176+
days := max(int(interval/(24*time.Hour)), 1)
177+
175178
result, err := s.db.Exec(query, fmt.Sprintf("%d days", days))
176179
if err != nil {
177180
return 0

0 commit comments

Comments
 (0)