Skip to content

Commit 63b1279

Browse files
committed
feat(feed): use exponential backoff for broken feeds
Instead of having a hard limit of 3 (regular) tries for feeds with errors, use an exponential backoff by default, with an upper-limit of one week. See #3334 for context/discussions.
1 parent 8adcaed commit 63b1279

File tree

4 files changed

+16
-5
lines changed

4 files changed

+16
-5
lines changed

internal/config/options.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,8 +489,8 @@ func NewConfigOptions() *configOptions {
489489
},
490490
},
491491
"POLLING_PARSING_ERROR_LIMIT": {
492-
ParsedIntValue: 3,
493-
RawValue: "3",
492+
ParsedIntValue: 0,
493+
RawValue: "0",
494494
ValueType: intType,
495495
Validator: func(rawValue string) error {
496496
return validateGreaterOrEqualThan(rawValue, 0)

internal/config/options_parsing_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,8 +1058,8 @@ func TestPollingLimitPerHostOptionParsing(t *testing.T) {
10581058
func TestPollingParsingErrorLimitOptionParsing(t *testing.T) {
10591059
configParser := NewConfigParser()
10601060

1061-
if configParser.options.PollingParsingErrorLimit() != 3 {
1062-
t.Fatalf("Expected POLLING_PARSING_ERROR_LIMIT to be 3 by default")
1061+
if configParser.options.PollingParsingErrorLimit() != 0 {
1062+
t.Fatalf("Expected POLLING_PARSING_ERROR_LIMIT to be 0 by default")
10631063
}
10641064

10651065
if err := configParser.parseLines([]string{"POLLING_PARSING_ERROR_LIMIT=5"}); err != nil {

internal/model/feed.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package model // import "miniflux.app/v2/internal/model"
66
import (
77
"fmt"
88
"io"
9+
"math"
910
"time"
1011

1112
"miniflux.app/v2/internal/config"
@@ -135,6 +136,16 @@ func (f *Feed) ScheduleNextCheck(weeklyCount int, refreshDelay time.Duration) ti
135136
// Use the RSS TTL field, Retry-After, Cache-Control or Expires HTTP headers if defined.
136137
interval = max(interval, refreshDelay)
137138

139+
// Use a binary exponential backoff for feeds with parsing errors.
140+
// https://en.wikipedia.org/wiki/Exponential_backoff
141+
if f.ParsingErrorCount > 0 {
142+
backoff := time.Duration(math.Pow(2, float64(f.ParsingErrorCount))) * time.Hour
143+
// Set a hard limit at one week
144+
if backoff.Hours() < time.Hour.Hours()*24*7 {
145+
interval += backoff
146+
}
147+
}
148+
138149
// Limit the max interval value for misconfigured feeds.
139150
switch config.Opts.PollingScheduler() {
140151
case SchedulerRoundRobin:

miniflux.1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ The maximum number of parsing errors that the program will try before stopping p
504504
.br
505505
Once the limit is reached, the user must refresh the feed manually. Set to 0 for unlimited.
506506
.br
507-
Default is 3\&.
507+
Default is 0\&.
508508
.TP
509509
.B POLLING_SCHEDULER
510510
Determines the strategy used to schedule feed polling.

0 commit comments

Comments
 (0)