store: fix compose state handling on restart

When restarting composer, we were not handling the compose states
correctly.

This resolves that as follows:
 * any running composes are marked as failed,
 * any waiting composes are put back in the pending jobs queue

As a consequence of needing the ability to reinitialize the job
queue, we must include the depsolved pipeline in the compose object.
This is the correct thing to do, as the semantics we currently
adhere to is that pipelines are depsolved when the compose is
started (and restarting composer should not affect this by for
instance re-depsolve the pipeline).

Resolves rhbz#1784062.

Signed-off-by: Tom Gundersen <teg@jklm.no>
This commit is contained in:
Tom Gundersen 2019-12-17 13:55:45 +01:00 committed by Ondřej Budai
parent 51f1691ab6
commit 0ef89aa864
2 changed files with 31 additions and 5 deletions

View file

@ -48,6 +48,7 @@ type Compose struct {
QueueStatus string `json:"queue_status"`
Blueprint *blueprint.Blueprint `json:"blueprint"`
OutputType string `json:"output-type"`
Pipeline *pipeline.Pipeline `json:"pipeline"`
Targets []*target.Target `json:"targets"`
JobCreated time.Time `json:"job_created"`
JobStarted time.Time `json:"job_started"`
@ -145,6 +146,10 @@ func New(stateDir *string, distro distro.Distro) *Store {
}()
}
s.pendingJobs = make(chan Job, 200)
s.distro = distro
s.stateDir = stateDir
if s.Blueprints == nil {
s.Blueprints = make(map[string]blueprint.Blueprint)
}
@ -152,8 +157,25 @@ func New(stateDir *string, distro distro.Distro) *Store {
s.Workspace = make(map[string]blueprint.Blueprint)
}
if s.Composes == nil {
// TODO: push waiting/running composes to workers again
s.Composes = make(map[uuid.UUID]Compose)
} else {
for composeID, compose := range s.Composes {
switch compose.QueueStatus {
case "RUNNING":
// We do not support resuming an in-flight build
compose.QueueStatus = "FAILED"
s.Composes[composeID] = compose
case "WAITING":
// Push waiting composes back into the pending jobs queue
s.pendingJobs <- Job{
ComposeID: composeID,
Distro: s.distro.Name(),
Pipeline: compose.Pipeline,
Targets: compose.Targets,
OutputType: compose.OutputType,
}
}
}
}
if s.Sources == nil {
s.Sources = make(map[string]SourceConfig)
@ -161,10 +183,6 @@ func New(stateDir *string, distro distro.Distro) *Store {
if s.BlueprintsChanges == nil {
s.BlueprintsChanges = make(map[string]map[string]blueprint.Change)
}
s.pendingJobs = make(chan Job, 200)
s.distro = distro
s.stateDir = stateDir
return &s
}
@ -444,6 +462,7 @@ func (s *Store) PushCompose(composeID uuid.UUID, bp *blueprint.Blueprint, checks
s.Composes[composeID] = Compose{
QueueStatus: "WAITING",
Blueprint: bp,
Pipeline: pipeline,
OutputType: composeType,
Targets: targets,
JobCreated: time.Now(),

View file

@ -345,6 +345,13 @@ func TestCompose(t *testing.T) {
break
}
if compose.Pipeline == nil {
t.Fatalf("%s: the compose in the store did not contain a blueprint", c.Path)
} else {
// TODO: find some (reasonable) way to verify the contents of the pipeline
compose.Pipeline = nil
}
if diff := cmp.Diff(compose, *c.ExpectedCompose, test.IgnoreDates(), test.IgnoreUuids(), test.Ignore("Targets.Options.Location")); diff != "" {
t.Errorf("%s: compose in store isn't the same as expected, diff:\n%s", c.Path, diff)
}