diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 7734a4fc..f32302ac 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -934,6 +934,41 @@ func TestDefautSchedulerEntryFrequencyFactor(t *testing.T) { } } +func TestSchedulerRoundRobinValue(t *testing.T) { + os.Clearenv() + + parser := NewParser() + opts, err := parser.ParseEnvironmentVariables() + if err != nil { + t.Fatalf(`Parsing failure: %v`, err) + } + + expected := defaultSchedulerRoundRobinMinInterval + result := opts.SchedulerRoundRobinMinInterval() + + if result != expected { + t.Fatalf(`Unexpected SCHEDULER_ROUND_ROBIN_MIN_INTERVAL value, got %v instead of %v`, result, expected) + } +} + +func TestSchedulerRoundRobinDefault(t *testing.T) { + os.Clearenv() + os.Setenv("SCHEDULER_ROUND_ROBIN_MIN_INTERVAL", "15") + + parser := NewParser() + opts, err := parser.ParseEnvironmentVariables() + if err != nil { + t.Fatalf(`Parsing failure: %v`, err) + } + + expected := 15 + result := opts.SchedulerRoundRobinMinInterval() + + if result != expected { + t.Fatalf(`Unexpected SCHEDULER_ROUND_ROBIN_MIN_INTERVAL value, got %v instead of %v`, result, expected) + } +} + func TestPollingParsingErrorLimit(t *testing.T) { os.Clearenv() os.Setenv("POLLING_PARSING_ERROR_LIMIT", "100") diff --git a/internal/config/options.go b/internal/config/options.go index 626d01b5..abbaf849 100644 --- a/internal/config/options.go +++ b/internal/config/options.go @@ -34,6 +34,7 @@ const ( defaultSchedulerEntryFrequencyMinInterval = 5 defaultSchedulerEntryFrequencyMaxInterval = 24 * 60 defaultSchedulerEntryFrequencyFactor = 1 + defaultSchedulerRoundRobinMinInterval = 60 defaultPollingParsingErrorLimit = 3 defaultRunMigrations = false defaultDatabaseURL = "user=postgres password=postgres dbname=miniflux2 sslmode=disable" @@ -126,6 +127,7 @@ type Options struct { schedulerEntryFrequencyMinInterval int schedulerEntryFrequencyMaxInterval int schedulerEntryFrequencyFactor int + schedulerRoundRobinMinInterval int pollingParsingErrorLimit int workerPoolSize int createAdmin bool @@ -203,6 +205,7 @@ func NewOptions() *Options { schedulerEntryFrequencyMinInterval: defaultSchedulerEntryFrequencyMinInterval, schedulerEntryFrequencyMaxInterval: defaultSchedulerEntryFrequencyMaxInterval, schedulerEntryFrequencyFactor: defaultSchedulerEntryFrequencyFactor, + schedulerRoundRobinMinInterval: defaultSchedulerRoundRobinMinInterval, pollingParsingErrorLimit: defaultPollingParsingErrorLimit, workerPoolSize: defaultWorkerPoolSize, createAdmin: defaultCreateAdmin, @@ -400,6 +403,10 @@ func (o *Options) SchedulerEntryFrequencyFactor() int { return o.schedulerEntryFrequencyFactor } +func (o *Options) SchedulerRoundRobinMinInterval() int { + return o.schedulerRoundRobinMinInterval +} + // PollingParsingErrorLimit returns the limit of errors when to stop polling. func (o *Options) PollingParsingErrorLimit() int { return o.pollingParsingErrorLimit @@ -668,6 +675,7 @@ func (o *Options) SortedOptions(redactSecret bool) []*Option { "SCHEDULER_ENTRY_FREQUENCY_MAX_INTERVAL": o.schedulerEntryFrequencyMaxInterval, "SCHEDULER_ENTRY_FREQUENCY_MIN_INTERVAL": o.schedulerEntryFrequencyMinInterval, "SCHEDULER_ENTRY_FREQUENCY_FACTOR": o.schedulerEntryFrequencyFactor, + "SCHEDULER_ROUND_ROBIN_MIN_INTERVAL": o.schedulerRoundRobinMinInterval, "SCHEDULER_SERVICE": o.schedulerService, "SERVER_TIMING_HEADER": o.serverTimingHeader, "WATCHDOG": o.watchdog, diff --git a/internal/config/parser.go b/internal/config/parser.go index 454d2c99..d64d67c7 100644 --- a/internal/config/parser.go +++ b/internal/config/parser.go @@ -152,6 +152,8 @@ func (p *Parser) parseLines(lines []string) (err error) { p.opts.schedulerEntryFrequencyMinInterval = parseInt(value, defaultSchedulerEntryFrequencyMinInterval) case "SCHEDULER_ENTRY_FREQUENCY_FACTOR": p.opts.schedulerEntryFrequencyFactor = parseInt(value, defaultSchedulerEntryFrequencyFactor) + case "SCHEDULER_ROUND_ROBIN_MIN_INTERVAL": + p.opts.schedulerRoundRobinMinInterval = parseInt(value, defaultSchedulerRoundRobinMinInterval) case "POLLING_PARSING_ERROR_LIMIT": p.opts.pollingParsingErrorLimit = parseInt(value, defaultPollingParsingErrorLimit) // kept for compatibility purpose diff --git a/internal/model/feed.go b/internal/model/feed.go index c1a0384f..987de9df 100644 --- a/internal/model/feed.go +++ b/internal/model/feed.go @@ -120,7 +120,7 @@ func (f *Feed) ScheduleNextCheck(weeklyCount int) { } f.NextCheckAt = time.Now().Add(time.Minute * time.Duration(intervalMinutes)) default: - f.NextCheckAt = time.Now().Add(time.Minute * time.Duration(config.Opts.PollingFrequency())) + f.NextCheckAt = time.Now().Add(time.Minute * time.Duration(config.Opts.SchedulerRoundRobinMinInterval())) } } diff --git a/internal/model/feed_test.go b/internal/model/feed_test.go index 394279dd..6541520a 100644 --- a/internal/model/feed_test.go +++ b/internal/model/feed_test.go @@ -83,6 +83,31 @@ func TestFeedScheduleNextCheckDefault(t *testing.T) { } } +func TestFeedScheduleNextCheckRoundRobinMinInterval(t *testing.T) { + minInterval := 1 + os.Clearenv() + os.Setenv("POLLING_SCHEDULER", "round_robin") + os.Setenv("SCHEDULER_ROUND_ROBIN_MIN_INTERVAL", fmt.Sprintf("%d", minInterval)) + + var err error + parser := config.NewParser() + config.Opts, err = parser.ParseEnvironmentVariables() + if err != nil { + t.Fatalf(`Parsing failure: %v`, err) + } + feed := &Feed{} + weeklyCount := 100 + feed.ScheduleNextCheck(weeklyCount) + + if feed.NextCheckAt.IsZero() { + t.Error(`The next_check_at must be set`) + } + + if feed.NextCheckAt.After(time.Now().Add(time.Minute * time.Duration(minInterval))) { + t.Error(`The next_check_at should not be after the now + min interval`) + } +} + func TestFeedScheduleNextCheckEntryCountBasedMaxInterval(t *testing.T) { maxInterval := 5 minInterval := 1 diff --git a/miniflux.1 b/miniflux.1 index c93bab39..7bf9ebd1 100644 --- a/miniflux.1 +++ b/miniflux.1 @@ -203,6 +203,11 @@ Factor to increase refresh frequency for the entry frequency scheduler\&. .br Default is 1\&. .TP +.B SCHEDULER_ROUND_ROBIN_MIN_INTERVAL +Minimum interval in minutes for the round robin scheduler\&. +.br +Default is 60 minutes\&. +.TP .B POLLING_PARSING_ERROR_LIMIT The maximum number of parsing errors that the program will try before stopping polling a feed. Once the limit is reached, the user must refresh the feed manually. Set to 0 for unlimited. .br