Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Abstract a request counter's cycle logic from watch() #376

Merged
merged 1 commit into from
Jul 30, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 9 additions & 3 deletions legacy/reqcounter/reqcounter.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,22 @@ func (rc *RequestCounter) reset() {
rc.Since = Clock.Now()
}

// watch continuously logs the request counter at the specified intervals.
// watch indefinitely performs repeated sleep/log cycles.
func (rc *RequestCounter) watch() {
// TODO: @tylerferrara create a way to cleanly terminate this goroutine.
go func() {
for {
Clock.Sleep(rc.Interval)
rc.Flush()
rc.Cycle()
}
}()
}

// Cycle sleeps for the request counter's interval and flushes itself.
func (rc *RequestCounter) Cycle() {
Clock.Sleep(rc.Interval)
rc.Flush()
}

// RequestCounters holds multiple request counters.
type RequestCounters []*RequestCounter

Expand Down
34 changes: 34 additions & 0 deletions legacy/reqcounter/reqcounter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ limitations under the License.
package reqcounter_test

import (
"fmt"
"sync"
"testing"
"time"

"github.com/stretchr/testify/require"
rc "sigs.k8s.io/k8s-container-image-promoter/legacy/reqcounter"
tw "sigs.k8s.io/k8s-container-image-promoter/legacy/timewrapper"
)

// defaultTime should be used as a timestamp for all request counters.
Expand Down Expand Up @@ -124,3 +126,35 @@ func TestRequestCounterIncrement(t *testing.T) {
// Ensure the request counter was incremented.
require.EqualValues(t, &expected, &requestCounter, "The request counter failed to increment its request field.")
}

func TestCycle(t *testing.T) {
// Create a simple request counter expected to log every 10 minutes.
requestCounter := NewRequestCounter(82)
requestCounter.Interval = time.Minute * 10
// Collect logging statements.
logs := []string{}
// Mock logrus.Debug calls.
rc.Debug = func(args ...interface{}) {
logs = append(logs, fmt.Sprint(args[0]))
}
// Mock time.
fakeTime := tw.FakeTime{
Time: defaultTime,
}
rc.Clock = &fakeTime
// Determine the expected logs.
expected := []string{
"From 2006-01-02 15:04:05 to 2006-01-02 15:14:05 [10 min] there have been 82 requests to GCR.",
"From 2006-01-02 15:14:05 to 2006-01-02 15:24:05 [10 min] there have been 0 requests to GCR.",
"From 2006-01-02 15:24:05 to 2006-01-02 15:34:05 [10 min] there have been 0 requests to GCR.",
"From 2006-01-02 15:34:05 to 2006-01-02 15:44:05 [10 min] there have been 0 requests to GCR.",
"From 2006-01-02 15:44:05 to 2006-01-02 15:54:05 [10 min] there have been 0 requests to GCR.",
}
// Repeatedly run sleep/log cycles.
numCycles := len(expected)
for i := 0; i < numCycles; i++ {
requestCounter.Cycle()
}
// Ensure the correct logs were produced.
require.EqualValues(t, expected, logs, "The request counter produced malformed logs.")
}
8 changes: 5 additions & 3 deletions legacy/timewrapper/timewrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ type FakeTime struct {
}

// Now returns the global fake time.
func (ft FakeTime) Now() time.Time { return ft.Time }
func (ft *FakeTime) Now() time.Time { return ft.Time }

// Sleep does not block the current goroutine.
func (ft FakeTime) Sleep(d time.Duration) {}
// Sleep adds the given duration to the global fake time.
func (ft *FakeTime) Sleep(d time.Duration) {
ft.Time = ft.Time.Add(d)
}