Skip to content

Commit

Permalink
Merge pull request #20 from gustavosbarreto/master
Browse files Browse the repository at this point in the history
polling refactoring: remove initial state definition logic from PollState
  • Loading branch information
otavio committed Mar 24, 2017
2 parents 8c2ffc6 + 7f42f0b commit e814787
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 79 deletions.
15 changes: 7 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
package main

import (
"math/rand"
"os"
"time"

Expand Down Expand Up @@ -37,17 +36,17 @@ func main() {
}

uh := &UpdateHub{
state: NewPollState(),
api: client.NewApiClient("localhost:8080"),
updater: client.NewUpdateClient(),
timeStep: time.Minute,
settings: settings,
store: afero.NewOsFs(),
pollingIntervalSpan: rand.Intn(settings.PollingInterval),
state: NewPollState(),
api: client.NewApiClient("localhost:8080"),
updater: client.NewUpdateClient(),
timeStep: time.Minute,
settings: settings,
store: afero.NewOsFs(),
}

uh.Controller = uh

uh.StartPolling()
uh.MainLoop()
}

Expand Down
13 changes: 0 additions & 13 deletions states.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,19 +146,6 @@ func (state *PollState) Handle(uh *UpdateHub) (State, bool) {
go func() {
pollingInterval := uh.settings.PollingInterval

now := time.Now()

if uh.settings.FirstPoll == 0 {
uh.settings.FirstPoll = int(now.Unix()) + uh.pollingIntervalSpan
pollingInterval = 1
}

if uh.settings.LastPoll == 0 && uh.settings.FirstPoll <= int(now.Unix()) {
nextState = NewUpdateCheckState()
state.Cancel(true)
return
}

for {
shouldPoll := int(time.Now().Unix()) > uh.settings.FirstPoll

Expand Down
57 changes: 0 additions & 57 deletions states_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,63 +200,6 @@ func TestPollTicks(t *testing.T) {
}
}

func TestFirstPoll(t *testing.T) {
poll := NewPollState()
uh, err := newTestUpdateHub(poll)
assert.NoError(t, err)

now := time.Now()
count := -1
guard := monkey.Patch(time.Now, func() time.Time {
count++
if count == 0 {
return now
}
return now.Add(time.Second * time.Duration(count))
})
defer guard.Unpatch()

c := &testController{
updateAvailable: false,
extraPoll: 0,
}

uh.pollingIntervalSpan = 5
uh.settings.FirstPoll = 0
uh.settings.PollingInterval = 10

uh.Controller = c

nextState, _ := poll.Handle(uh)
assert.IsType(t, &UpdateCheckState{}, nextState)

assert.Equal(t, int(now.Unix())+uh.pollingIntervalSpan, uh.settings.FirstPoll)
assert.Equal(t, uh.pollingIntervalSpan, poll.ticksCount)
}

func TestDelayedPolling(t *testing.T) {
poll := NewPollState()
uh, err := newTestUpdateHub(poll)
assert.NoError(t, err)

now := time.Now()

c := &testController{
updateAvailable: false,
extraPoll: 0,
}

uh.settings.FirstPoll = int(now.Add(-1 * time.Second).Unix())
uh.settings.LastPoll = 0

uh.Controller = c

nextState, _ := poll.Handle(uh)
assert.IsType(t, &UpdateCheckState{}, nextState)

assert.Equal(t, 0, poll.ticksCount)
}

func TestPollingRetries(t *testing.T) {
uh, err := newTestUpdateHub(NewPollState())
assert.NoError(t, err)
Expand Down
20 changes: 19 additions & 1 deletion updatehub.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"bufio"
"errors"
"fmt"
"math/rand"
"path"
"time"

Expand All @@ -33,7 +34,6 @@ type UpdateHub struct {
api *client.ApiClient
updater client.Updater
reporter client.Reporter
pollingIntervalSpan int
lastInstalledPackageUID string
}

Expand Down Expand Up @@ -119,6 +119,24 @@ func (uh *UpdateHub) ReportCurrentState() error {
return nil
}

// StartPolling starts the polling process
func (uh *UpdateHub) StartPolling() {
now := time.Now()

uh.state = NewPollState()

if uh.settings.FirstPoll == 0 {
// Apply an offset in first poll
uh.settings.FirstPoll = int(now.Add(time.Duration(rand.Intn(uh.settings.PollingInterval))).Unix())
} else if uh.settings.LastPoll == 0 && uh.settings.FirstPoll <= int(now.Unix()) {
// it never did a poll before
uh.state = NewUpdateCheckState()
} else if time.Unix(int64(uh.settings.LastPoll), 0).Add(time.Duration(uh.settings.PollingInterval)).Before(now) {
// pending regular interval
uh.state = NewUpdateCheckState()
}
}

func (uh *UpdateHub) MainLoop() {
for {
uh.ReportCurrentState()
Expand Down
59 changes: 59 additions & 0 deletions updatehub_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"testing"
"time"

"github.com/bouk/monkey"
"github.com/spf13/afero"
"github.com/stretchr/testify/assert"

Expand Down Expand Up @@ -127,6 +128,64 @@ func TestUpdateHubReportState(t *testing.T) {
assert.EqualError(t, err, "error")
}

func TestStartPolling(t *testing.T) {
now := time.Now()

// Simulate time passage from now
defer func() *monkey.PatchGuard {
seconds := -1
return monkey.Patch(time.Now, func() time.Time {
seconds++
return now.Add(time.Second * time.Duration(seconds))
})
}()

testCases := []struct {
name string
pollingInterval time.Duration
firstPoll int
lastPoll int
expectedState State
}{
{
"RegularPoll",
time.Second,
0,
0,
&PollState{},
},

{
"NeverDidPollBefore",
time.Second,
int(now.Add(-1 * time.Second).Unix()),
0,
&UpdateCheckState{},
},

{
"PendingRegularPoll",
time.Second,
int(now.Add(-2 * time.Second).Unix()),
int(now.Add(-1 * time.Second).Unix()),
&UpdateCheckState{},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
uh, _ := newTestUpdateHub(nil)

uh.settings.PollingInterval = int(tc.pollingInterval)
uh.settings.FirstPoll = tc.firstPoll
uh.settings.LastPoll = tc.lastPoll

uh.StartPolling()
assert.IsType(t, tc.expectedState, uh.state)
})
}
}

type testObject struct {
metadata.ObjectMetadata
}
Expand Down

0 comments on commit e814787

Please sign in to comment.