Ver Fonte

refactor(cli): use time.Duration for scheduler frequency

Polling frequency is undocumented so it's not exacly clear what units were.
gudvinr há 8 meses atrás
pai
commit
7060ecc163

+ 5 - 5
internal/cli/scheduler.go

@@ -26,12 +26,12 @@ func runScheduler(store *storage.Storage, pool *worker.Pool) {
 
 	go cleanupScheduler(
 		store,
-		config.Opts.CleanupFrequencyHours(),
+		config.Opts.CleanupFrequency(),
 	)
 }
 
-func feedScheduler(store *storage.Storage, pool *worker.Pool, frequency, batchSize, errorLimit, limitPerHost int) {
-	for range time.Tick(time.Duration(frequency) * time.Minute) {
+func feedScheduler(store *storage.Storage, pool *worker.Pool, frequency time.Duration, batchSize, errorLimit, limitPerHost int) {
+	for range time.Tick(frequency) {
 		// Generate a batch of feeds for any user that has feeds to refresh.
 		batchBuilder := store.NewBatchBuilder()
 		batchBuilder.WithBatchSize(batchSize)
@@ -49,8 +49,8 @@ func feedScheduler(store *storage.Storage, pool *worker.Pool, frequency, batchSi
 	}
 }
 
-func cleanupScheduler(store *storage.Storage, frequency int) {
-	for range time.Tick(time.Duration(frequency) * time.Hour) {
+func cleanupScheduler(store *storage.Storage, frequency time.Duration) {
+	for range time.Tick(frequency) {
 		runCleanupTasks(store)
 	}
 }

+ 45 - 5
internal/config/config_test.go

@@ -589,12 +589,22 @@ func TestDefaultCleanupFrequencyHoursValue(t *testing.T) {
 		t.Fatalf(`Parsing failure: %v`, err)
 	}
 
-	expected := defaultCleanupFrequencyHours
-	result := opts.CleanupFrequencyHours()
+	expected := defaultCleanupFrequency
+	result := opts.CleanupFrequency()
 
 	if result != expected {
 		t.Fatalf(`Unexpected CLEANUP_FREQUENCY_HOURS value, got %v instead of %v`, result, expected)
 	}
+
+	sorted := opts.SortedOptions(false)
+	i := slices.IndexFunc(sorted, func(opt *option) bool {
+		return opt.Key == "CLEANUP_FREQUENCY_HOURS"
+	})
+
+	expectedSerialized := int(defaultCleanupFrequency / time.Hour)
+	if got := sorted[i].Value; got != expectedSerialized {
+		t.Fatalf(`Unexpected value in option output, got %q instead of %q`, got, expectedSerialized)
+	}
 }
 
 func TestCleanupFrequencyHours(t *testing.T) {
@@ -608,12 +618,22 @@ func TestCleanupFrequencyHours(t *testing.T) {
 		t.Fatalf(`Parsing failure: %v`, err)
 	}
 
-	expected := 42
-	result := opts.CleanupFrequencyHours()
+	expected := 42 * time.Hour
+	result := opts.CleanupFrequency()
 
 	if result != expected {
 		t.Fatalf(`Unexpected CLEANUP_FREQUENCY_HOURS value, got %v instead of %v`, result, expected)
 	}
+
+	sorted := opts.SortedOptions(false)
+	i := slices.IndexFunc(sorted, func(opt *option) bool {
+		return opt.Key == "CLEANUP_FREQUENCY_HOURS"
+	})
+
+	expectedSerialized := 42
+	if got := sorted[i].Value; got != expectedSerialized {
+		t.Fatalf(`Unexpected value in option output, got %q instead of %q`, got, expectedSerialized)
+	}
 }
 
 func TestDefaultCleanupArchiveReadDaysValue(t *testing.T) {
@@ -737,6 +757,16 @@ func TestDefaultPollingFrequencyValue(t *testing.T) {
 	if result != expected {
 		t.Fatalf(`Unexpected POLLING_FREQUENCY value, got %v instead of %v`, result, expected)
 	}
+
+	sorted := opts.SortedOptions(false)
+	i := slices.IndexFunc(sorted, func(opt *option) bool {
+		return opt.Key == "POLLING_FREQUENCY"
+	})
+
+	expectedSerialized := int(defaultPollingFrequency / time.Minute)
+	if got := sorted[i].Value; got != expectedSerialized {
+		t.Fatalf(`Unexpected value in option output, got %q instead of %q`, got, expectedSerialized)
+	}
 }
 
 func TestPollingFrequency(t *testing.T) {
@@ -749,12 +779,22 @@ func TestPollingFrequency(t *testing.T) {
 		t.Fatalf(`Parsing failure: %v`, err)
 	}
 
-	expected := 42
+	expected := 42 * time.Minute
 	result := opts.PollingFrequency()
 
 	if result != expected {
 		t.Fatalf(`Unexpected POLLING_FREQUENCY value, got %v instead of %v`, result, expected)
 	}
+
+	sorted := opts.SortedOptions(false)
+	i := slices.IndexFunc(sorted, func(opt *option) bool {
+		return opt.Key == "POLLING_FREQUENCY"
+	})
+
+	expectedSerialized := 42
+	if got := sorted[i].Value; got != expectedSerialized {
+		t.Fatalf(`Unexpected value in option output, got %q instead of %q`, got, expectedSerialized)
+	}
 }
 
 func TestDefaultForceRefreshInterval(t *testing.T) {

+ 11 - 11
internal/config/options.go

@@ -28,7 +28,7 @@ const (
 	defaultRootURL                            = "http://localhost"
 	defaultBasePath                           = ""
 	defaultWorkerPoolSize                     = 16
-	defaultPollingFrequency                   = 60
+	defaultPollingFrequency                   = 60 * time.Minute
 	defaultForceRefreshInterval               = 30 * time.Second
 	defaultBatchSize                          = 100
 	defaultPollingScheduler                   = "round_robin"
@@ -47,7 +47,7 @@ const (
 	defaultCertFile                           = ""
 	defaultKeyFile                            = ""
 	defaultCertDomain                         = ""
-	defaultCleanupFrequencyHours              = 24
+	defaultCleanupFrequency                   = 24 * time.Hour
 	defaultCleanupArchiveReadDays             = 60
 	defaultCleanupArchiveUnreadDays           = 180
 	defaultCleanupArchiveBatchSize            = 10000
@@ -125,7 +125,7 @@ type options struct {
 	certFile                           string
 	certDomain                         string
 	certKeyFile                        string
-	cleanupFrequencyHours              int
+	cleanupFrequencyInterval           time.Duration
 	cleanupArchiveReadDays             int
 	cleanupArchiveUnreadDays           int
 	cleanupArchiveBatchSize            int
@@ -137,7 +137,7 @@ type options struct {
 	schedulerEntryFrequencyFactor      int
 	schedulerRoundRobinMinInterval     time.Duration
 	schedulerRoundRobinMaxInterval     time.Duration
-	pollingFrequency                   int
+	pollingFrequency                   time.Duration
 	pollingLimitPerHost                int
 	pollingParsingErrorLimit           int
 	pollingScheduler                   string
@@ -209,7 +209,7 @@ func NewOptions() *options {
 		certFile:                           defaultCertFile,
 		certDomain:                         defaultCertDomain,
 		certKeyFile:                        defaultKeyFile,
-		cleanupFrequencyHours:              defaultCleanupFrequencyHours,
+		cleanupFrequencyInterval:           defaultCleanupFrequency,
 		cleanupArchiveReadDays:             defaultCleanupArchiveReadDays,
 		cleanupArchiveUnreadDays:           defaultCleanupArchiveUnreadDays,
 		cleanupArchiveBatchSize:            defaultCleanupArchiveBatchSize,
@@ -361,9 +361,9 @@ func (o *options) CertDomain() string {
 	return o.certDomain
 }
 
-// CleanupFrequencyHours returns the interval in hours for cleanup jobs.
-func (o *options) CleanupFrequencyHours() int {
-	return o.cleanupFrequencyHours
+// CleanupFrequencyHours returns the interval for cleanup jobs.
+func (o *options) CleanupFrequency() time.Duration {
+	return o.cleanupFrequencyInterval
 }
 
 // CleanupArchiveReadDays returns the number of days after which marking read items as removed.
@@ -402,7 +402,7 @@ func (o *options) BatchSize() int {
 }
 
 // PollingFrequency returns the interval to refresh feeds in the background.
-func (o *options) PollingFrequency() int {
+func (o *options) PollingFrequency() time.Duration {
 	return o.pollingFrequency
 }
 
@@ -721,10 +721,10 @@ func (o *options) SortedOptions(redactSecret bool) []*option {
 		"BATCH_SIZE":                             o.batchSize,
 		"CERT_DOMAIN":                            o.certDomain,
 		"CERT_FILE":                              o.certFile,
+		"CLEANUP_FREQUENCY_HOURS":                int(o.cleanupFrequencyInterval.Hours()),
 		"CLEANUP_ARCHIVE_BATCH_SIZE":             o.cleanupArchiveBatchSize,
 		"CLEANUP_ARCHIVE_READ_DAYS":              o.cleanupArchiveReadDays,
 		"CLEANUP_ARCHIVE_UNREAD_DAYS":            o.cleanupArchiveUnreadDays,
-		"CLEANUP_FREQUENCY_HOURS":                o.cleanupFrequencyHours,
 		"CLEANUP_REMOVE_SESSIONS_DAYS":           o.cleanupRemoveSessionsDays,
 		"CREATE_ADMIN":                           o.createAdmin,
 		"DATABASE_CONNECTION_LIFETIME":           o.databaseConnectionLifetime,
@@ -770,7 +770,7 @@ func (o *options) SortedOptions(redactSecret bool) []*option {
 		"OAUTH2_USER_CREATION":                   o.oauth2UserCreationAllowed,
 		"DISABLE_LOCAL_AUTH":                     o.disableLocalAuth,
 		"FORCE_REFRESH_INTERVAL":                 int(o.forceRefreshInterval.Seconds()),
-		"POLLING_FREQUENCY":                      o.pollingFrequency,
+		"POLLING_FREQUENCY":                      int(o.pollingFrequency.Minutes()),
 		"POLLING_LIMIT_PER_HOST":                 o.pollingLimitPerHost,
 		"POLLING_PARSING_ERROR_LIMIT":            o.pollingParsingErrorLimit,
 		"POLLING_SCHEDULER":                      o.pollingScheduler,

+ 2 - 2
internal/config/parser.go

@@ -127,7 +127,7 @@ func (p *parser) parseLines(lines []string) (err error) {
 		case "CERT_DOMAIN":
 			p.opts.certDomain = parseString(value, defaultCertDomain)
 		case "CLEANUP_FREQUENCY_HOURS":
-			p.opts.cleanupFrequencyHours = parseInt(value, defaultCleanupFrequencyHours)
+			p.opts.cleanupFrequencyInterval = parseInterval(value, time.Hour, defaultCleanupFrequency)
 		case "CLEANUP_ARCHIVE_READ_DAYS":
 			p.opts.cleanupArchiveReadDays = parseInt(value, defaultCleanupArchiveReadDays)
 		case "CLEANUP_ARCHIVE_UNREAD_DAYS":
@@ -143,7 +143,7 @@ func (p *parser) parseLines(lines []string) (err error) {
 		case "BATCH_SIZE":
 			p.opts.batchSize = parseInt(value, defaultBatchSize)
 		case "POLLING_FREQUENCY":
-			p.opts.pollingFrequency = parseInt(value, defaultPollingFrequency)
+			p.opts.pollingFrequency = parseInterval(value, time.Minute, defaultPollingFrequency)
 		case "POLLING_LIMIT_PER_HOST":
 			p.opts.pollingLimitPerHost = parseInt(value, 0)
 		case "POLLING_PARSING_ERROR_LIMIT":