engine: graph: Prevent converged timeout of dirty res

Somewhere after the engine re-write we seem to have regressed and
converge early even if some resource is dirty. This adds an additional
timer so that we don't start the individual resource converged countdown
until our state is okay.
This commit is contained in:
James Shubin
2019-01-17 18:46:00 -05:00
parent 34550246f4
commit 354a1c23b0
2 changed files with 11 additions and 0 deletions

View File

@@ -119,6 +119,7 @@ func (obj *Engine) Process(vertex pgraph.Vertex) error {
for _, changed := range updated { for _, changed := range updated {
if changed { // at least one was updated if changed { // at least one was updated
// invalidate cache, mark as dirty // invalidate cache, mark as dirty
obj.state[vertex].tuid.StopTimer()
obj.state[vertex].isStateOK = false obj.state[vertex].isStateOK = false
break break
} }
@@ -174,6 +175,7 @@ func (obj *Engine) Process(vertex pgraph.Vertex) error {
// if CheckApply ran without noop and without error, state should be good // if CheckApply ran without noop and without error, state should be good
if !noop && err == nil { // aka !noop || checkOK if !noop && err == nil { // aka !noop || checkOK
obj.state[vertex].tuid.StartTimer()
obj.state[vertex].isStateOK = true // reset obj.state[vertex].isStateOK = true // reset
if refresh { if refresh {
obj.SetUpstreamRefresh(vertex, false) // refresh happened, clear the request obj.SetUpstreamRefresh(vertex, false) // refresh happened, clear the request
@@ -252,9 +254,11 @@ func (obj *Engine) Worker(vertex pgraph.Vertex) error {
defer close(obj.state[vertex].stopped) // done signal defer close(obj.state[vertex].stopped) // done signal
obj.state[vertex].cuid = obj.Converger.Register() obj.state[vertex].cuid = obj.Converger.Register()
obj.state[vertex].tuid = obj.Converger.Register()
// must wait for all users of the cuid to finish *before* we unregister! // must wait for all users of the cuid to finish *before* we unregister!
// as a result, this defer happens *before* the below wait group Wait... // as a result, this defer happens *before* the below wait group Wait...
defer obj.state[vertex].cuid.Unregister() defer obj.state[vertex].cuid.Unregister()
defer obj.state[vertex].tuid.Unregister()
defer obj.state[vertex].wg.Wait() // this Worker is the last to exit! defer obj.state[vertex].wg.Wait() // this Worker is the last to exit!

View File

@@ -86,6 +86,7 @@ type State struct {
working bool // is the Main() loop running ? working bool // is the Main() loop running ?
cuid converger.UID // primary converger cuid converger.UID // primary converger
tuid converger.UID // secondary converger
init *engine.Init // a copy of the init struct passed to res Init init *engine.Init // a copy of the init struct passed to res Init
} }
@@ -121,6 +122,7 @@ func (obj *State) Init() error {
} }
//obj.cuid = obj.Converger.Register() // gets registered in Worker() //obj.cuid = obj.Converger.Register() // gets registered in Worker()
//obj.tuid = obj.Converger.Register() // gets registered in Worker()
obj.init = &engine.Init{ obj.init = &engine.Init{
Program: obj.Program, Program: obj.Program,
@@ -128,6 +130,7 @@ func (obj *State) Init() error {
// Watch: // Watch:
Running: func() error { Running: func() error {
obj.tuid.StopTimer()
close(obj.started) // this is reset in the reset func close(obj.started) // this is reset in the reset func
obj.isStateOK = false // assume we're initially dirty obj.isStateOK = false // assume we're initially dirty
// optimization: skip the initial send if not a starter // optimization: skip the initial send if not a starter
@@ -141,6 +144,7 @@ func (obj *State) Init() error {
Events: obj.eventsChan, Events: obj.eventsChan,
Read: obj.read, Read: obj.read,
Dirty: func() { // TODO: should we rename this SetDirty? Dirty: func() { // TODO: should we rename this SetDirty?
obj.tuid.StopTimer()
obj.isStateOK = false obj.isStateOK = false
}, },
@@ -208,6 +212,9 @@ func (obj *State) Close() error {
//if obj.cuid != nil { //if obj.cuid != nil {
// obj.cuid.Unregister() // gets unregistered in Worker() // obj.cuid.Unregister() // gets unregistered in Worker()
//} //}
//if obj.tuid != nil {
// obj.tuid.Unregister() // gets unregistered in Worker()
//}
// redundant safety // redundant safety
obj.wg.Wait() // wait until all poke's and events on me have exited obj.wg.Wait() // wait until all poke's and events on me have exited