Skip to content

Commit 8e986d3

Browse files
refactor: code
1 parent f44b445 commit 8e986d3

File tree

4 files changed

+109
-94
lines changed

4 files changed

+109
-94
lines changed

pkg/smartrequeue/entry.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package smartrequeue
2+
3+
import (
4+
"time"
5+
6+
ctrl "sigs.k8s.io/controller-runtime"
7+
)
8+
9+
// Entry is used to manage the requeue logic for a specific object.
10+
// It holds the next duration to requeue and the store it belongs to.
11+
type Entry struct {
12+
store *Store
13+
nextDuration time.Duration
14+
}
15+
16+
func newEntry(s *Store) *Entry {
17+
return &Entry{
18+
store: s,
19+
nextDuration: s.minInterval,
20+
}
21+
}
22+
23+
// Error resets the duration to the minInterval and returns an empty Result and the error
24+
// so that the controller-runtime can handle the exponential backoff for errors.
25+
func (e *Entry) Error(err error) (ctrl.Result, error) {
26+
e.nextDuration = e.store.minInterval
27+
e.setNext()
28+
return ctrl.Result{}, err
29+
}
30+
31+
// Stable returns a Result and increments the interval for the next iteration.
32+
// Used when the external resource is stable (healthy or unhealthy).
33+
func (e *Entry) Stable() (ctrl.Result, error) {
34+
defer e.setNext()
35+
return ctrl.Result{RequeueAfter: e.nextDuration}, nil
36+
}
37+
38+
// Progressing resets the duration to the minInterval and returns a Result with that interval.
39+
// Used when the external resource is still doing something (creating, deleting, updating, etc.)
40+
func (e *Entry) Progressing() (ctrl.Result, error) {
41+
e.nextDuration = e.store.minInterval
42+
defer e.setNext()
43+
return ctrl.Result{RequeueAfter: e.nextDuration}, nil
44+
}
45+
46+
// Never deletes the entry from the store and returns an empty Result.
47+
func (e *Entry) Never() (ctrl.Result, error) {
48+
e.store.deleteEntry(e)
49+
return ctrl.Result{}, nil
50+
}
51+
52+
// setNext updates the next requeue duration using exponential backoff.
53+
// It multiplies the current duration by the store's multiplier and ensures
54+
// the result doesn't exceed the configured maximum interval.
55+
func (e *Entry) setNext() {
56+
newDuration := time.Duration(float32(e.nextDuration) * e.store.multiplier)
57+
58+
if newDuration > e.store.maxInterval {
59+
newDuration = e.store.maxInterval
60+
}
61+
62+
e.nextDuration = newDuration
63+
}

pkg/smartrequeue/entry_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package smartrequeue
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
"github.com/stretchr/testify/assert"
8+
ctrl "sigs.k8s.io/controller-runtime"
9+
)
10+
11+
func Test_Entry(t *testing.T) {
12+
entry := newEntry(NewStore(time.Second, time.Minute, 2))
13+
14+
assert.Equal(t, 1*time.Second, getRequeueAfter(entry.Stable()))
15+
assert.Equal(t, 2*time.Second, getRequeueAfter(entry.Stable()))
16+
assert.Equal(t, 4*time.Second, getRequeueAfter(entry.Stable()))
17+
assert.Equal(t, 8*time.Second, getRequeueAfter(entry.Stable()))
18+
assert.Equal(t, 16*time.Second, getRequeueAfter(entry.Stable()))
19+
assert.Equal(t, 32*time.Second, getRequeueAfter(entry.Stable()))
20+
assert.Equal(t, 60*time.Second, getRequeueAfter(entry.Stable()))
21+
assert.Equal(t, 60*time.Second, getRequeueAfter(entry.Stable()))
22+
23+
assert.Equal(t, 1*time.Second, getRequeueAfter(entry.Progressing()))
24+
assert.Equal(t, 1*time.Second, getRequeueAfter(entry.Progressing()))
25+
26+
assert.Equal(t, 2*time.Second, getRequeueAfter(entry.Stable()))
27+
assert.Equal(t, 4*time.Second, getRequeueAfter(entry.Stable()))
28+
29+
assert.Equal(t, 0*time.Second, getRequeueAfter(entry.Error(assert.AnError)))
30+
assert.Equal(t, 2*time.Second, getRequeueAfter(entry.Stable()))
31+
assert.Equal(t, 4*time.Second, getRequeueAfter(entry.Stable()))
32+
}
33+
34+
func getRequeueAfter(res ctrl.Result, _ error) time.Duration {
35+
return res.RequeueAfter.Round(time.Second)
36+
}

pkg/smartrequeue/store.go

Lines changed: 10 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,19 @@ import (
55
"sync"
66
"time"
77

8-
ctrl "sigs.k8s.io/controller-runtime"
98
"sigs.k8s.io/controller-runtime/pkg/client"
109
)
1110

11+
// Store is used to manage requeue entries for different objects.
12+
// It holds a map of entries indexed by a key that uniquely identifies the object.
13+
type Store struct {
14+
minInterval time.Duration
15+
maxInterval time.Duration
16+
multiplier float32
17+
objects map[key]*Entry
18+
objectsLock sync.Mutex
19+
}
20+
1221
// NewStore creates a new Store with the specified minimum and maximum intervals
1322
// and a multiplier for the exponential backoff logic.
1423
func NewStore(minInterval, maxInterval time.Duration, multiplier float32) *Store {
@@ -20,16 +29,6 @@ func NewStore(minInterval, maxInterval time.Duration, multiplier float32) *Store
2029
}
2130
}
2231

23-
// Store is used to manage requeue entries for different objects.
24-
// It holds a map of entries indexed by a key that uniquely identifies the object.
25-
type Store struct {
26-
minInterval time.Duration
27-
maxInterval time.Duration
28-
multiplier float32
29-
objects map[key]*Entry
30-
objectsLock sync.Mutex
31-
}
32-
3332
func (s *Store) For(obj client.Object) *Entry {
3433
s.objectsLock.Lock()
3534
defer s.objectsLock.Unlock()
@@ -70,59 +69,3 @@ type key struct {
7069
Name string
7170
Namespace string
7271
}
73-
74-
func newEntry(s *Store) *Entry {
75-
return &Entry{
76-
store: s,
77-
nextDuration: s.minInterval,
78-
}
79-
}
80-
81-
// Entry is used to manage the requeue logic for a specific object.
82-
// It holds the next duration to requeue and the store it belongs to.
83-
type Entry struct {
84-
store *Store
85-
nextDuration time.Duration
86-
}
87-
88-
// Error resets the duration to the minInterval and returns an empty Result and the error
89-
// so that the controller-runtime can handle the exponential backoff for errors.
90-
func (e *Entry) Error(err error) (ctrl.Result, error) {
91-
e.nextDuration = e.store.minInterval
92-
e.setNext()
93-
return ctrl.Result{}, err
94-
}
95-
96-
// Stable returns a Result and increments the interval for the next iteration.
97-
// Used when the external resource is stable (healthy or unhealthy).
98-
func (e *Entry) Stable() (ctrl.Result, error) {
99-
defer e.setNext()
100-
return ctrl.Result{RequeueAfter: e.nextDuration}, nil
101-
}
102-
103-
// Progressing resets the duration to the minInterval and returns a Result with that interval.
104-
// Used when the external resource is still doing something (creating, deleting, updating, etc.)
105-
func (e *Entry) Progressing() (ctrl.Result, error) {
106-
e.nextDuration = e.store.minInterval
107-
defer e.setNext()
108-
return ctrl.Result{RequeueAfter: e.nextDuration}, nil
109-
}
110-
111-
// Never deletes the entry from the store and returns an empty Result.
112-
func (e *Entry) Never() (ctrl.Result, error) {
113-
e.store.deleteEntry(e)
114-
return ctrl.Result{}, nil
115-
}
116-
117-
// setNext updates the next requeue duration using exponential backoff.
118-
// It multiplies the current duration by the store's multiplier and ensures
119-
// the result doesn't exceed the configured maximum interval.
120-
func (e *Entry) setNext() {
121-
newDuration := time.Duration(float32(e.nextDuration) * e.store.multiplier)
122-
123-
if newDuration > e.store.maxInterval {
124-
newDuration = e.store.maxInterval
125-
}
126-
127-
e.nextDuration = newDuration
128-
}

pkg/smartrequeue/store_test.go

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,33 +10,6 @@ import (
1010
"sigs.k8s.io/controller-runtime/pkg/client"
1111
)
1212

13-
func Test_Entry(t *testing.T) {
14-
entry := newEntry(NewStore(time.Second, time.Minute, 2))
15-
16-
assert.Equal(t, 1*time.Second, getRequeueAfter(entry.Stable()))
17-
assert.Equal(t, 2*time.Second, getRequeueAfter(entry.Stable()))
18-
assert.Equal(t, 4*time.Second, getRequeueAfter(entry.Stable()))
19-
assert.Equal(t, 8*time.Second, getRequeueAfter(entry.Stable()))
20-
assert.Equal(t, 16*time.Second, getRequeueAfter(entry.Stable()))
21-
assert.Equal(t, 32*time.Second, getRequeueAfter(entry.Stable()))
22-
assert.Equal(t, 60*time.Second, getRequeueAfter(entry.Stable()))
23-
assert.Equal(t, 60*time.Second, getRequeueAfter(entry.Stable()))
24-
25-
assert.Equal(t, 1*time.Second, getRequeueAfter(entry.Progressing()))
26-
assert.Equal(t, 1*time.Second, getRequeueAfter(entry.Progressing()))
27-
28-
assert.Equal(t, 2*time.Second, getRequeueAfter(entry.Stable()))
29-
assert.Equal(t, 4*time.Second, getRequeueAfter(entry.Stable()))
30-
31-
assert.Equal(t, 0*time.Second, getRequeueAfter(entry.Error(assert.AnError)))
32-
assert.Equal(t, 2*time.Second, getRequeueAfter(entry.Stable()))
33-
assert.Equal(t, 4*time.Second, getRequeueAfter(entry.Stable()))
34-
}
35-
36-
func getRequeueAfter(res ctrl.Result, _ error) time.Duration {
37-
return res.RequeueAfter.Round(time.Second)
38-
}
39-
4013
func TestFor(t *testing.T) {
4114
tests := []struct {
4215
name string

0 commit comments

Comments
 (0)