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

Revert "have StateHook periodically PersistState" #15176

Merged
merged 1 commit into from
Jun 7, 2017
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
26 changes: 0 additions & 26 deletions backend/local/hook_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,17 @@ package local

import (
"sync"
"time"

"github.com/hashicorp/terraform/state"
"github.com/hashicorp/terraform/terraform"
)

// interval between forced PersistState calls by StateHook
const persistStateHookInterval = 10 * time.Second

// StateHook is a hook that continuously updates the state by calling
// WriteState on a state.State.
type StateHook struct {
terraform.NilHook
sync.Mutex

// lastPersist is the time of the last call to PersistState, for periodic
// updates to remote state. PostStateUpdate will force a call PersistState
// if it has been more that persistStateHookInterval since the last call to
// PersistState.
lastPersist time.Time

State state.State
}

Expand All @@ -36,24 +26,8 @@ func (h *StateHook) PostStateUpdate(
if err := h.State.WriteState(s); err != nil {
return terraform.HookActionHalt, err
}

// periodically persist the state
if time.Since(h.lastPersist) > persistStateHookInterval {
if err := h.persistState(); err != nil {
return terraform.HookActionHalt, err
}
}
}

// Continue forth
return terraform.HookActionContinue, nil
}

func (h *StateHook) persistState() error {
if h.State != nil {
err := h.State.PersistState()
h.lastPersist = time.Now()
return err
}
return nil
}
97 changes: 0 additions & 97 deletions backend/local/hook_state_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package local

import (
"sync"
"testing"
"time"

"github.com/hashicorp/terraform/state"
"github.com/hashicorp/terraform/terraform"
Expand All @@ -29,98 +27,3 @@ func TestStateHook(t *testing.T) {
t.Fatalf("bad state: %#v", is.State())
}
}

// testPersistState stores the state on WriteState, and
type testPersistState struct {
*state.InmemState

mu sync.Mutex
persisted bool
}

func (s *testPersistState) WriteState(state *terraform.State) error {
s.mu.Lock()
defer s.mu.Unlock()

s.persisted = false
return s.InmemState.WriteState(state)
}

func (s *testPersistState) PersistState() error {
s.mu.Lock()
defer s.mu.Unlock()

s.persisted = true
return nil
}

// verify that StateHook calls PersistState if the last call was more than
// persistStateHookInterval
func TestStateHookPersist(t *testing.T) {
is := &testPersistState{
InmemState: &state.InmemState{},
}
hook := &StateHook{State: is}

s := state.TestStateInitial()
hook.PostStateUpdate(s)

// the first call should persist, since the last time was zero
if !is.persisted {
t.Fatal("PersistState not called")
}

s.Serial++
hook.PostStateUpdate(s)

// this call should not have persisted
if is.persisted {
t.Fatal("PostStateUpdate called PersistState early")
}

if !is.State().Equal(s) {
t.Fatalf("bad state: %#v", is.State())
}

// set the last call back to before our interval
hook.lastPersist = time.Now().Add(-2 * persistStateHookInterval)

s.Serial++
hook.PostStateUpdate(s)

if !is.persisted {
t.Fatal("PersistState not called")
}

if !is.State().Equal(s) {
t.Fatalf("bad state: %#v", is.State())
}
}

// verify that the satet hook is safe for concurrent use
func TestStateHookRace(t *testing.T) {
is := &state.InmemState{}
var hook terraform.Hook = &StateHook{State: is}

s := state.TestStateInitial()

var wg sync.WaitGroup

for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
action, err := hook.PostStateUpdate(s)
if err != nil {
t.Fatalf("err: %s", err)
}
if action != terraform.HookActionContinue {
t.Fatalf("bad: %v", action)
}
if !is.State().Equal(s) {
t.Fatalf("bad state: %#v", is.State())
}
}()
}
wg.Wait()
}