jobqueue: expose dependencies when querying status

The status of a job may depend on the status of its dependenices,
as we do not repeat for instance the failed state in each dependent
job.

Return also the list of dependencies so these can be queried too.
This commit is contained in:
Tom Gundersen 2020-11-09 14:04:58 +00:00 committed by Lars Karlitski
parent 9adae8a3a7
commit c777a18df0
6 changed files with 29 additions and 21 deletions

View file

@ -216,7 +216,7 @@ func (server *Server) ComposeStatus(w http.ResponseWriter, r *http.Request, id s
} }
var result worker.OSBuildJobResult var result worker.OSBuildJobResult
status, err := server.workers.JobStatus(jobId, &result) status, _, err := server.workers.JobStatus(jobId, &result)
if err != nil { if err != nil {
http.Error(w, fmt.Sprintf("Job %s not found: %s", id, err), http.StatusNotFound) http.Error(w, fmt.Sprintf("Job %s not found: %s", id, err), http.StatusNotFound)
return return

View file

@ -263,7 +263,7 @@ func (q *fsJobQueue) CancelJob(id uuid.UUID) error {
return nil return nil
} }
func (q *fsJobQueue) JobStatus(id uuid.UUID) (result json.RawMessage, queued, started, finished time.Time, canceled bool, err error) { func (q *fsJobQueue) JobStatus(id uuid.UUID) (result json.RawMessage, queued, started, finished time.Time, canceled bool, deps []uuid.UUID, err error) {
j, err := q.readJob(id) j, err := q.readJob(id)
if err != nil { if err != nil {
return return
@ -274,6 +274,7 @@ func (q *fsJobQueue) JobStatus(id uuid.UUID) (result json.RawMessage, queued, st
started = j.StartedAt started = j.StartedAt
finished = j.FinishedAt finished = j.FinishedAt
canceled = j.Canceled canceled = j.Canceled
deps = j.Dependencies
return return
} }

View file

@ -147,21 +147,23 @@ func TestDependencies(t *testing.T) {
require.ElementsMatch(t, []uuid.UUID{one, two}, r) require.ElementsMatch(t, []uuid.UUID{one, two}, r)
j := pushTestJob(t, q, "test", nil, []uuid.UUID{one, two}) j := pushTestJob(t, q, "test", nil, []uuid.UUID{one, two})
_, queued, started, finished, canceled, err := q.JobStatus(j) _, queued, started, finished, canceled, deps, err := q.JobStatus(j)
require.NoError(t, err) require.NoError(t, err)
require.True(t, !queued.IsZero()) require.True(t, !queued.IsZero())
require.True(t, started.IsZero()) require.True(t, started.IsZero())
require.True(t, finished.IsZero()) require.True(t, finished.IsZero())
require.False(t, canceled) require.False(t, canceled)
require.ElementsMatch(t, deps, []uuid.UUID{one, two})
require.Equal(t, j, finishNextTestJob(t, q, "test", testResult{}, []uuid.UUID{one, two})) require.Equal(t, j, finishNextTestJob(t, q, "test", testResult{}, []uuid.UUID{one, two}))
result, queued, started, finished, canceled, err := q.JobStatus(j) result, queued, started, finished, canceled, deps, err := q.JobStatus(j)
require.NoError(t, err) require.NoError(t, err)
require.True(t, !queued.IsZero()) require.True(t, !queued.IsZero())
require.True(t, !started.IsZero()) require.True(t, !started.IsZero())
require.True(t, !finished.IsZero()) require.True(t, !finished.IsZero())
require.False(t, canceled) require.False(t, canceled)
require.ElementsMatch(t, deps, []uuid.UUID{one, two})
err = json.Unmarshal(result, &testResult{}) err = json.Unmarshal(result, &testResult{})
require.NoError(t, err) require.NoError(t, err)
@ -172,12 +174,13 @@ func TestDependencies(t *testing.T) {
two := pushTestJob(t, q, "test", nil, nil) two := pushTestJob(t, q, "test", nil, nil)
j := pushTestJob(t, q, "test", nil, []uuid.UUID{one, two}) j := pushTestJob(t, q, "test", nil, []uuid.UUID{one, two})
_, queued, started, finished, canceled, err := q.JobStatus(j) _, queued, started, finished, canceled, deps, err := q.JobStatus(j)
require.NoError(t, err) require.NoError(t, err)
require.True(t, !queued.IsZero()) require.True(t, !queued.IsZero())
require.True(t, started.IsZero()) require.True(t, started.IsZero())
require.True(t, finished.IsZero()) require.True(t, finished.IsZero())
require.False(t, canceled) require.False(t, canceled)
require.ElementsMatch(t, deps, []uuid.UUID{one, two})
r := []uuid.UUID{} r := []uuid.UUID{}
r = append(r, finishNextTestJob(t, q, "test", testResult{}, nil)) r = append(r, finishNextTestJob(t, q, "test", testResult{}, nil))
@ -186,12 +189,13 @@ func TestDependencies(t *testing.T) {
require.Equal(t, j, finishNextTestJob(t, q, "test", testResult{}, []uuid.UUID{one, two})) require.Equal(t, j, finishNextTestJob(t, q, "test", testResult{}, []uuid.UUID{one, two}))
result, queued, started, finished, canceled, err := q.JobStatus(j) result, queued, started, finished, canceled, deps, err := q.JobStatus(j)
require.NoError(t, err) require.NoError(t, err)
require.True(t, !queued.IsZero()) require.True(t, !queued.IsZero())
require.True(t, !started.IsZero()) require.True(t, !started.IsZero())
require.True(t, !finished.IsZero()) require.True(t, !finished.IsZero())
require.False(t, canceled) require.False(t, canceled)
require.ElementsMatch(t, deps, []uuid.UUID{one, two})
err = json.Unmarshal(result, &testResult{}) err = json.Unmarshal(result, &testResult{})
require.NoError(t, err) require.NoError(t, err)
@ -248,7 +252,7 @@ func TestCancel(t *testing.T) {
require.NotEmpty(t, id) require.NotEmpty(t, id)
err = q.CancelJob(id) err = q.CancelJob(id)
require.NoError(t, err) require.NoError(t, err)
result, _, _, _, canceled, err := q.JobStatus(id) result, _, _, _, canceled, _, err := q.JobStatus(id)
require.NoError(t, err) require.NoError(t, err)
require.True(t, canceled) require.True(t, canceled)
require.Nil(t, result) require.Nil(t, result)
@ -266,7 +270,7 @@ func TestCancel(t *testing.T) {
require.Equal(t, json.RawMessage("null"), args) require.Equal(t, json.RawMessage("null"), args)
err = q.CancelJob(id) err = q.CancelJob(id)
require.NoError(t, err) require.NoError(t, err)
result, _, _, _, canceled, err = q.JobStatus(id) result, _, _, _, canceled, _, err = q.JobStatus(id)
require.NoError(t, err) require.NoError(t, err)
require.True(t, canceled) require.True(t, canceled)
require.Nil(t, result) require.Nil(t, result)
@ -286,7 +290,7 @@ func TestCancel(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
err = q.CancelJob(id) err = q.CancelJob(id)
require.NoError(t, err) require.NoError(t, err)
result, _, _, _, canceled, err = q.JobStatus(id) result, _, _, _, canceled, _, err = q.JobStatus(id)
require.NoError(t, err) require.NoError(t, err)
require.False(t, canceled) require.False(t, canceled)
err = json.Unmarshal(result, &testResult{}) err = json.Unmarshal(result, &testResult{})

View file

@ -50,13 +50,15 @@ type JobQueue interface {
// Cancel a job. Does nothing if the job has already finished. // Cancel a job. Does nothing if the job has already finished.
CancelJob(id uuid.UUID) error CancelJob(id uuid.UUID) error
// If the job has finished, returns the result as raw JSON.
//
// Returns the current status of the job, in the form of three times: // Returns the current status of the job, in the form of three times:
// queued, started, and finished. `started` and `finished` might be the // queued, started, and finished. `started` and `finished` might be the
// zero time (check with t.IsZero()), when the job is not running or // zero time (check with t.IsZero()), when the job is not running or
// finished, respectively. // finished, respectively.
// //
// If the job is finished, its result will be returned in `result`. // Lastly, the IDs of the jobs dependencies are returned.
JobStatus(id uuid.UUID) (result json.RawMessage, queued, started, finished time.Time, canceled bool, err error) JobStatus(id uuid.UUID) (result json.RawMessage, queued, started, finished time.Time, canceled bool, deps []uuid.UUID, err error)
} }
var ( var (

View file

@ -141,7 +141,7 @@ func (q *testJobQueue) CancelJob(id uuid.UUID) error {
return nil return nil
} }
func (q *testJobQueue) JobStatus(id uuid.UUID) (result json.RawMessage, queued, started, finished time.Time, canceled bool, err error) { func (q *testJobQueue) JobStatus(id uuid.UUID) (result json.RawMessage, queued, started, finished time.Time, canceled bool, deps []uuid.UUID, err error) {
j, exists := q.jobs[id] j, exists := q.jobs[id]
if !exists { if !exists {
err = jobqueue.ErrNotExist err = jobqueue.ErrNotExist
@ -153,6 +153,7 @@ func (q *testJobQueue) JobStatus(id uuid.UUID) (result json.RawMessage, queued,
started = j.StartedAt started = j.StartedAt
finished = j.FinishedAt finished = j.FinishedAt
canceled = j.Canceled canceled = j.Canceled
deps = j.Dependencies
return return
} }

View file

@ -99,16 +99,16 @@ func (s *Server) EnqueueKojiFinalize(job *KojiFinalizeJob, initID uuid.UUID, bui
return s.jobs.Enqueue("koji-finalize", job, append([]uuid.UUID{initID}, buildIDs...)) return s.jobs.Enqueue("koji-finalize", job, append([]uuid.UUID{initID}, buildIDs...))
} }
func (s *Server) JobStatus(id uuid.UUID, result interface{}) (*JobStatus, error) { func (s *Server) JobStatus(id uuid.UUID, result interface{}) (*JobStatus, []uuid.UUID, error) {
rawResult, queued, started, finished, canceled, err := s.jobs.JobStatus(id) rawResult, queued, started, finished, canceled, deps, err := s.jobs.JobStatus(id)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
if !finished.IsZero() && !canceled { if !finished.IsZero() && !canceled {
err = json.Unmarshal(rawResult, result) err = json.Unmarshal(rawResult, result)
if err != nil { if err != nil {
return nil, fmt.Errorf("error unmarshaling result for job '%s': %v", id, err) return nil, nil, fmt.Errorf("error unmarshaling result for job '%s': %v", id, err)
} }
} }
@ -125,7 +125,7 @@ func (s *Server) JobStatus(id uuid.UUID, result interface{}) (*JobStatus, error)
Started: started, Started: started,
Finished: finished, Finished: finished,
Canceled: canceled, Canceled: canceled,
}, nil }, deps, nil
} }
func (s *Server) Cancel(id uuid.UUID) error { func (s *Server) Cancel(id uuid.UUID) error {
@ -139,7 +139,7 @@ func (s *Server) JobArtifact(id uuid.UUID, name string) (io.Reader, int64, error
return nil, 0, errors.New("Artifacts not enabled") return nil, 0, errors.New("Artifacts not enabled")
} }
status, err := s.JobStatus(id, &json.RawMessage{}) status, _, err := s.JobStatus(id, &json.RawMessage{})
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }
@ -168,7 +168,7 @@ func (s *Server) DeleteArtifacts(id uuid.UUID) error {
return errors.New("Artifacts not enabled") return errors.New("Artifacts not enabled")
} }
status, err := s.JobStatus(id, &json.RawMessage{}) status, _, err := s.JobStatus(id, &json.RawMessage{})
if err != nil { if err != nil {
return err return err
} }
@ -201,7 +201,7 @@ func (s *Server) RequestJob(ctx context.Context, arch string, jobTypes []string)
var dynamicArgs []json.RawMessage var dynamicArgs []json.RawMessage
for _, depID := range depIDs { for _, depID := range depIDs {
result, _, _, _, _, _ := s.jobs.JobStatus(depID) result, _, _, _, _, _, _ := s.jobs.JobStatus(depID)
dynamicArgs = append(dynamicArgs, result) dynamicArgs = append(dynamicArgs, result)
} }
@ -323,7 +323,7 @@ func (h *apiHandlers) GetJob(ctx echo.Context, tokenstr string) error {
return ctx.JSON(http.StatusOK, getJobResponse{}) return ctx.JSON(http.StatusOK, getJobResponse{})
} }
status, err := h.server.JobStatus(jobId, &json.RawMessage{}) status, _, err := h.server.JobStatus(jobId, &json.RawMessage{})
if err != nil { if err != nil {
return err return err
} }