diff --git a/cmd/pasty/main.go b/cmd/pasty/main.go index b1fe949..76b43d2 100644 --- a/cmd/pasty/main.go +++ b/cmd/pasty/main.go @@ -3,6 +3,7 @@ package main import ( "context" "errors" + "github.com/lus/pasty/internal/cleanup" "github.com/lus/pasty/internal/config" "github.com/lus/pasty/internal/meta" "github.com/lus/pasty/internal/reports" @@ -83,6 +84,21 @@ func main() { } }() + // Schedule the cleanup task if configured + if cfg.Cleanup.Enabled { + task := &cleanup.Task{ + Interval: cfg.Cleanup.TaskInterval, + MaxPasteAge: cfg.Cleanup.PasteLifetime, + Repository: driver.Pastes(), + } + log.Info().Msg("Scheduling the cleanup task...") + task.Start() + defer func() { + log.Info().Msg("Shutting down the cleanup task...") + task.Stop() + }() + } + // Start the web server log.Info().Str("address", cfg.Address).Msg("Starting the web server...") webServer := &web.Server{ diff --git a/internal/cleanup/task.go b/internal/cleanup/task.go new file mode 100644 index 0000000..f028e88 --- /dev/null +++ b/internal/cleanup/task.go @@ -0,0 +1,48 @@ +package cleanup + +import ( + "context" + "github.com/lus/pasty/internal/pastes" + "github.com/rs/zerolog/log" + "time" +) + +type Task struct { + Interval time.Duration + MaxPasteAge time.Duration + Repository pastes.Repository + + running bool + stop chan struct{} +} + +func (task *Task) Start() { + if task.running { + return + } + task.stop = make(chan struct{}, 1) + go func() { + for { + select { + case <-time.After(task.Interval): + n, err := task.Repository.DeleteOlderThan(context.Background(), task.MaxPasteAge) + if err != nil { + log.Err(err).Msg("Could not clean up expired pastes.") + continue + } + log.Debug().Int("amount", n).Msg("Cleaned up expired pastes.") + case <-task.stop: + task.running = false + return + } + } + }() + task.running = true +} + +func (task *Task) Stop() { + if !task.running { + return + } + close(task.stop) +} diff --git a/internal/config/compatibility.go b/internal/config/compatibility.go index 3a73709..cfe5b51 100644 --- a/internal/config/compatibility.go +++ b/internal/config/compatibility.go @@ -31,6 +31,9 @@ var keyRedirects = map[string][]string{ "PASTY_REPORTS_ENABLED": {"PASTY_REPORTS_ENABLED"}, "PASTY_REPORTS_WEBHOOK_URL": {"PASTY_REPORT_WEBHOOK"}, "PASTY_REPORTS_WEBHOOK_TOKEN": {"PASTY_REPORT_WEBHOOK_TOKEN"}, + "PASTY_CLEANUP_ENABLED": {"PASTY_AUTODELETE"}, + "PASTY_CLEANUP_PASTE_LIFETIME": {"PASTY_AUTODELETE_LIFETIME"}, + "PASTY_CLEANUP_TASK_INTERVAL": {"PASTY_AUTODELETE_TASK_INTERVAL"}, "PASTY_MODIFICATION_TOKENS_ENABLED": {"PASTY_MODIFICATION_TOKENS", "PASTY_DELETION_TOKENS"}, "PASTY_MODIFICATION_TOKEN_CHARSET": {"PASTY_MODIFICATION_TOKEN_CHARACTERS"}, "PASTY_MODIFICATION_TOKEN_MASTER": {"PASTY_DELETION_TOKEN_MASTER"}, diff --git a/internal/config/config.go b/internal/config/config.go index d32789f..3796860 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -7,27 +7,27 @@ import ( ) type Config struct { - LogLevel string `default:"info" split_words:"true"` - Address string `default:":8080" split_words:"true"` - StorageDriver string `default:"sqlite" split_words:"true"` - PasteIDLength int `default:"6" split_words:"true"` - PasteIDCharset string `default:"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" split_words:"true"` - ModificationTokensEnabled bool `default:"true" split_words:"true"` - ModificationTokenMaster string `split_words:"true"` - ModificationTokenLength int `default:"12" split_words:"true"` - ModificationTokenCharset string `default:"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" split_words:"true"` - RateLimit string `default:"30-M" split_words:"true"` - PasteLengthCap int `default:"50000" split_words:"true"` - AutoDelete *AutoDeleteConfig `split_words:"true"` + LogLevel string `default:"info" split_words:"true"` + Address string `default:":8080" split_words:"true"` + StorageDriver string `default:"sqlite" split_words:"true"` + PasteIDLength int `default:"6" split_words:"true"` + PasteIDCharset string `default:"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" split_words:"true"` + ModificationTokensEnabled bool `default:"true" split_words:"true"` + ModificationTokenMaster string `split_words:"true"` + ModificationTokenLength int `default:"12" split_words:"true"` + ModificationTokenCharset string `default:"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" split_words:"true"` + RateLimit string `default:"30-M" split_words:"true"` + PasteLengthCap int `default:"50000" split_words:"true"` + Cleanup *CleanupConfig Reports *ReportConfig Postgres *PostgresConfig SQLite *SQLiteConfig } -type AutoDeleteConfig struct { - Enabled bool `default:"false"` - Lifetime time.Duration `default:"720h"` - TaskInterval time.Duration `default:"5m" split_words:"true"` +type CleanupConfig struct { + Enabled bool `default:"false"` + PasteLifetime time.Duration `default:"720h" split_words:"true"` + TaskInterval time.Duration `default:"5m" split_words:"true"` } type ReportConfig struct {