Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ spec:
type: object
properties:
backoffDelay:
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^<numberOfRetries>.'
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^(<numberOfRetries>-1).'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kahirokunn iiuc the scope of this PR is mostly fixing the linear retry logic. What is the reason for changing the exponential backoff docs in this PR as well?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Cali0707
Thanks for your review 馃檹
I included this to use one-based retry numbering consistently in both formulas. Exponential already starts at backoffDelay , so this only corrects the docs without changing behavior.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Cali0707 we came to the conclusion docs we not accurate based on a parallel review for backoff delay logic.

type: string
backoffPolicy:
description: BackoffPolicy is the retry backoff policy (linear, exponential).
Expand Down Expand Up @@ -93,7 +93,7 @@ spec:
type: object
properties:
backoffDelay:
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^<numberOfRetries>.'
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^(<numberOfRetries>-1).'
type: string
backoffPolicy:
description: BackoffPolicy is the retry backoff policy (linear, exponential).
Expand Down
2 changes: 1 addition & 1 deletion config/core/resources/broker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ spec:
type: object
properties:
backoffDelay:
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^<numberOfRetries>.'
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^(<numberOfRetries>-1).'
type: string
backoffPolicy:
description: BackoffPolicy is the retry backoff policy (linear, exponential).
Expand Down
4 changes: 2 additions & 2 deletions config/core/resources/channel.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ spec:
type: object
properties:
backoffDelay:
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^<numberOfRetries>.'
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^(<numberOfRetries>-1).'
type: string
backoffPolicy:
description: BackoffPolicy is the retry backoff policy (linear, exponential).
Expand Down Expand Up @@ -121,7 +121,7 @@ spec:
type: object
properties:
backoffDelay:
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^<numberOfRetries>.'
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^(<numberOfRetries>-1).'
type: string
backoffPolicy:
description: BackoffPolicy is the retry backoff policy (linear, exponential).
Expand Down
2 changes: 1 addition & 1 deletion config/core/resources/parallel.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ spec:
- https://en.wikipedia.org/wiki/ISO_8601 For
linear policy, backoff delay is backoffDelay*<numberOfRetries>.
For exponential policy, backoff delay is
backoffDelay*2^<numberOfRetries>.'
backoffDelay*2^(<numberOfRetries>-1).'
type: string
backoffPolicy:
description: BackoffPolicy is the retry backoff
Expand Down
2 changes: 1 addition & 1 deletion config/core/resources/requestreply.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ spec:
type: object
properties:
backoffDelay:
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^<numberOfRetries>.'
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^(<numberOfRetries>-1).'
type: string
backoffPolicy:
description: BackoffPolicy is the retry backoff policy (linear, exponential).
Expand Down
2 changes: 1 addition & 1 deletion config/core/resources/sequence.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ spec:
type: object
properties:
backoffDelay:
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^<numberOfRetries>.'
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^(<numberOfRetries>-1).'
type: string
backoffPolicy:
description: BackoffPolicy is the retry backoff policy (linear, exponential).
Expand Down
2 changes: 1 addition & 1 deletion config/core/resources/subscription.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ spec:
type: object
properties:
backoffDelay:
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^<numberOfRetries>.'
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^(<numberOfRetries>-1).'
type: string
backoffPolicy:
description: BackoffPolicy is the retry backoff policy (linear, exponential).
Expand Down
2 changes: 1 addition & 1 deletion config/core/resources/trigger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ spec:
x-kubernetes-preserve-unknown-fields: true # This is necessary to enable the experimental feature delivery-timeout
properties:
backoffDelay:
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^<numberOfRetries>.'
description: 'BackoffDelay is the delay before retrying. More information on Duration format: - https://www.iso.org/iso-8601-date-and-time-format.html - https://en.wikipedia.org/wiki/ISO_8601 For linear policy, backoff delay is backoffDelay*<numberOfRetries>. For exponential policy, backoff delay is backoffDelay*2^(<numberOfRetries>-1).'
type: string
backoffPolicy:
description: BackoffPolicy is the retry backoff policy (linear, exponential).
Expand Down
2 changes: 1 addition & 1 deletion docs/delivery/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ type DeliverySpec struct {
// - https://en.wikipedia.org/wiki/ISO_8601
//
// For linear policy, backoff delay is backoffDelay*<numberOfRetries>.
// For exponential policy, backoff delay is backoffDelay*2^<numberOfRetries>.
// For exponential policy, backoff delay is backoffDelay*2^(<numberOfRetries>-1).
// +optional
BackoffDelay *string `json:"backoffDelay,omitempty"`
}
Expand Down
4 changes: 2 additions & 2 deletions docs/eventing-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ More information on Duration format:
- <a href="https://www.iso.org/iso-8601-date-and-time-format.html">https://www.iso.org/iso-8601-date-and-time-format.html</a>
- <a href="https://en.wikipedia.org/wiki/ISO_8601">https://en.wikipedia.org/wiki/ISO_8601</a></p>
<p>For linear policy, backoff delay is backoffDelay*<numberOfRetries>.
For exponential policy, backoff delay is backoffDelay*2^<numberOfRetries>.</p>
For exponential policy, backoff delay is backoffDelay*2^(<numberOfRetries>-1).</p>
</td>
</tr>
<tr>
Expand Down Expand Up @@ -1512,7 +1512,7 @@ More information on Duration format:
- <a href="https://www.iso.org/iso-8601-date-and-time-format.html">https://www.iso.org/iso-8601-date-and-time-format.html</a>
- <a href="https://en.wikipedia.org/wiki/ISO_8601">https://en.wikipedia.org/wiki/ISO_8601</a></p>
<p>For linear policy, backoff delay is backoffDelay*<numberOfRetries>.
For exponential policy, backoff delay is backoffDelay*2^<numberOfRetries>.</p>
For exponential policy, backoff delay is backoffDelay*2^(<numberOfRetries>-1).</p>
</td>
</tr>
</tbody>
Expand Down
2 changes: 1 addition & 1 deletion pkg/apis/duck/v1/delivery_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ type DeliverySpec struct {
// - https://en.wikipedia.org/wiki/ISO_8601
//
// For linear policy, backoff delay is backoffDelay*<numberOfRetries>.
// For exponential policy, backoff delay is backoffDelay*2^<numberOfRetries>.
// For exponential policy, backoff delay is backoffDelay*2^(<numberOfRetries>-1).
// +optional
BackoffDelay *string `json:"backoffDelay,omitempty"`

Expand Down
2 changes: 1 addition & 1 deletion pkg/apis/duck/v1beta1/delivery_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ type DeliverySpec struct {
// - https://en.wikipedia.org/wiki/ISO_8601
//
// For linear policy, backoff delay is backoffDelay*<numberOfRetries>.
// For exponential policy, backoff delay is backoffDelay*2^<numberOfRetries>.
// For exponential policy, backoff delay is backoffDelay*2^(<numberOfRetries>-1).
// +optional
BackoffDelay *string `json:"backoffDelay,omitempty"`
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/kncloudevents/retries.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,17 +162,17 @@ func saturatingPeriodDuration(p period.Period) time.Duration {
}

func linearBackoff(delay time.Duration, attemptNum int, configuredMax *time.Duration) time.Duration {
if attemptNum <= 0 || delay <= 0 {
if attemptNum < 0 || delay <= 0 {
return 0
}
limit := maxBackoffDuration
if configuredMax != nil {
limit = *configuredMax
}
if delay >= limit || time.Duration(attemptNum) > limit/delay {
if delay >= limit || time.Duration(attemptNum) >= limit/delay {
return limit
}
return delay * time.Duration(attemptNum)
return delay * (time.Duration(attemptNum) + 1)
}

func exponentialBackoff(delay time.Duration, attemptNum int, configuredMax *time.Duration) time.Duration {
Expand Down
44 changes: 34 additions & 10 deletions pkg/kncloudevents/retries_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func TestRetryConfigBackoffMax(t *testing.T) {
policy: linear,
delay: "PT3S",
backoffMax: ptr.String("PT10S"),
attempts: []int{1, 2, 3, 4, int(^uint(0) >> 1)},
attempts: []int{0, 1, 2, 3, int(^uint(0) >> 1)},
wantBackoffs: []time.Duration{
3 * time.Second,
6 * time.Second,
Expand Down Expand Up @@ -110,7 +110,7 @@ func TestRetryConfigBackoffMax(t *testing.T) {
name: "uncapped linear saturates",
policy: linear,
delay: "PT1S",
attempts: []int{1, int(^uint(0) >> 1)},
attempts: []int{0, int(^uint(0) >> 1)},
wantBackoffs: []time.Duration{time.Second, maxBackoffDuration},
},
{
Expand Down Expand Up @@ -189,6 +189,7 @@ func TestRetryConfigBackoffMax(t *testing.T) {
func TestDoWithRetriesBackoffMax(t *testing.T) {
tests := []struct {
name string
policy v1.BackoffPolicyType
delay string
backoffMax *string
retryAfter string
Expand All @@ -197,38 +198,61 @@ func TestDoWithRetriesBackoffMax(t *testing.T) {
}{
{
name: "exponential backoff is capped",
policy: v1.BackoffPolicyExponential,
delay: "PT1S",
backoffMax: ptr.String("PT2S"),
wantTimes: []time.Duration{0, time.Second, 3 * time.Second, 5 * time.Second, 7 * time.Second},
},
{
name: "exponential backoff without a maximum",
policy: v1.BackoffPolicyExponential,
delay: "PT1S",
wantTimes: []time.Duration{0, time.Second, 3 * time.Second, 7 * time.Second, 15 * time.Second},
},
{
name: "maximum below the initial delay",
policy: v1.BackoffPolicyExponential,
delay: "PT3S",
backoffMax: ptr.String("PT2S"),
wantTimes: []time.Duration{0, 2 * time.Second, 4 * time.Second, 6 * time.Second, 8 * time.Second},
},
{
name: "retry after can exceed the backoff maximum",
policy: v1.BackoffPolicyExponential,
delay: "PT1S",
backoffMax: ptr.String("PT2S"),
retryAfter: "3",
retryAfterMax: ptr.String("PT5S"),
wantTimes: []time.Duration{0, 3 * time.Second, 6 * time.Second, 9 * time.Second, 12 * time.Second},
},
{
name: "linear backoff waits one delay before the first retry",
policy: v1.BackoffPolicyLinear,
delay: "PT1S",
wantTimes: []time.Duration{0, time.Second, 3 * time.Second, 6 * time.Second, 10 * time.Second},
},
{
name: "linear backoff is capped",
policy: v1.BackoffPolicyLinear,
delay: "PT1S",
backoffMax: ptr.String("PT2S"),
wantTimes: []time.Duration{0, time.Second, 3 * time.Second, 5 * time.Second, 7 * time.Second},
},
{
name: "linear maximum below the initial delay",
policy: v1.BackoffPolicyLinear,
delay: "PT3S",
backoffMax: ptr.String("PT2S"),
wantTimes: []time.Duration{0, 2 * time.Second, 4 * time.Second, 6 * time.Second, 8 * time.Second},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
policy := v1.BackoffPolicyExponential
config, err := RetryConfigFromDeliverySpec(v1.DeliverySpec{
Retry: ptr.Int32(4),
BackoffPolicy: &policy,
BackoffPolicy: &tt.policy,
BackoffDelay: &tt.delay,
BackoffMax: tt.backoffMax,
RetryAfterMax: tt.retryAfterMax,
Expand Down Expand Up @@ -328,22 +352,22 @@ func TestRetryConfigFromDeliverySpec(t *testing.T) {
backoffPolicy: v1.BackoffPolicyExponential,
backoffDelay: "PT1.5S",
expectedBackoffDurations: []time.Duration{
1500 * time.Millisecond,
3 * time.Second,
6 * time.Second,
12 * time.Second,
24 * time.Second,
48 * time.Second,
},
}, {
name: "Successful Exponential Backoff 500ms, 5 retries",
backoffPolicy: v1.BackoffPolicyExponential,
backoffDelay: "PT0.5S",
expectedBackoffDurations: []time.Duration{
500 * time.Millisecond,
1 * time.Second,
2 * time.Second,
4 * time.Second,
8 * time.Second,
16 * time.Second,
},
}, {
name: "Invalid Backoff Delay",
Expand All @@ -356,11 +380,11 @@ func TestRetryConfigFromDeliverySpec(t *testing.T) {
backoffDelay: "PT0.5S",
timeout: &validISO8601DurationString,
expectedBackoffDurations: []time.Duration{
500 * time.Millisecond,
1 * time.Second,
2 * time.Second,
4 * time.Second,
8 * time.Second,
16 * time.Second,
},
}, {
name: "Invalid Timeout",
Expand All @@ -374,11 +398,11 @@ func TestRetryConfigFromDeliverySpec(t *testing.T) {
backoffDelay: "PT0.5S",
retryAfterMax: &validISO8601DurationString,
expectedBackoffDurations: []time.Duration{
500 * time.Millisecond,
1 * time.Second,
2 * time.Second,
4 * time.Second,
8 * time.Second,
16 * time.Second,
},
}, {
name: "Invalid RetryAfterMax",
Expand Down Expand Up @@ -422,8 +446,8 @@ func TestRetryConfigFromDeliverySpec(t *testing.T) {
assert.Nil(t, retryConfig.RetryAfterMaxDuration)
}

for i := 1; i < retry; i++ {
expectedBackoffDuration := tc.expectedBackoffDurations[i-1]
for i := 0; i < retry; i++ {
expectedBackoffDuration := tc.expectedBackoffDurations[i]
actualBackoffDuration := retryConfig.Backoff(i, nil)
assert.Equal(t, expectedBackoffDuration, actualBackoffDuration)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,8 @@ func TestReconciler_ReconcileKind(t *testing.T) {
WithInMemoryChannelEventPoliciesReady()),
subs: []fanout.Subscription{*previousSubscription},
wantBackoffs: map[int]time.Duration{
3: 3 * time.Second,
0: 1 * time.Second,
2: 3 * time.Second,
20: 10 * time.Second,
},
wantSubs: []fanout.Subscription{{
Expand Down
Loading