diff options
author | Lukasz Wojciechowski <l.wojciechow@partner.samsung.com> | 2018-06-11 15:27:59 +0200 |
---|---|---|
committer | Alexander Mazuruk <a.mazuruk@samsung.com> | 2018-07-26 07:32:48 +0200 |
commit | d58291aa7a8ceb67c78404ab67616b013e333a15 (patch) | |
tree | 1e7f2c10dd2b39e602d23acd28266cfb52804976 | |
parent | 31062956851d43e63d3ee61f102d24313732848c (diff) | |
download | weles-d58291aa7a8ceb67c78404ab67616b013e333a15.tar.gz weles-d58291aa7a8ceb67c78404ab67616b013e333a15.tar.bz2 weles-d58291aa7a8ceb67c78404ab67616b013e333a15.zip |
Implement sorting in ListJobs
Patch includes Aleksander's version of sorting function selector.
Change-Id: I624bba4a07e39b0129c08d5a2513ad1e874c32cc
Signed-off-by: Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
Signed-off-by: Aleksander Mistewicz <a.mistewicz@samsung.com>
-rw-r--r-- | controller/jobscontrollerimpl.go | 96 | ||||
-rw-r--r-- | controller/jobscontrollerimpl_test.go | 125 | ||||
-rw-r--r-- | job_status_extra.go | 43 |
3 files changed, 263 insertions, 1 deletions
diff --git a/controller/jobscontrollerimpl.go b/controller/jobscontrollerimpl.go index c14057c..a922b7f 100644 --- a/controller/jobscontrollerimpl.go +++ b/controller/jobscontrollerimpl.go @@ -21,6 +21,7 @@ package controller import ( "regexp" + "sort" "strings" "sync" "time" @@ -252,12 +253,27 @@ func (js *JobsControllerImpl) List(filter weles.JobFilter, sorter weles.JobSorte return nil, weles.ListInfo{}, err } - // Get all Jobs ignoring sorter and paginator. + // Filter jobs. for _, job := range js.jobs { if job.passesFilter(f) { ret = append(ret, job.JobInfo) } } + // Sort jobs. + ps := &jobSorter{ + jobs: ret, + by: byJobIDAsc, + } + switch sorter.SortBy { + case weles.JobSortByCreatedDate: + ps.setByFunction(sorter.SortOrder, byCreatedAsc, byCreatedDesc) + case weles.JobSortByUpdatedDate: + ps.setByFunction(sorter.SortOrder, byUpdatedAsc, byUpdatedDesc) + case weles.JobSortByJobStatus: + ps.setByFunction(sorter.SortOrder, byStatusAsc, byStatusDesc) + } + sort.Sort(ps) + // TODO Use paginator. info := weles.ListInfo{TotalRecords: uint64(len(ret)), RemainingRecords: 0} return ret, info, nil } @@ -370,3 +386,81 @@ func (job *Job) passesFilter(f *filter) bool { } return true } + +func byCreatedAsc(i1, i2 *weles.JobInfo) bool { + if time.Time(i1.Created).Equal(time.Time(i2.Created)) { + return byJobIDAsc(i1, i2) + } + return time.Time(i1.Created).Before(time.Time(i2.Created)) +} + +func byCreatedDesc(i1, i2 *weles.JobInfo) bool { + if time.Time(i1.Created).Equal(time.Time(i2.Created)) { + return byJobIDAsc(i1, i2) + } + return time.Time(i1.Created).After(time.Time(i2.Created)) +} + +func byUpdatedAsc(i1, i2 *weles.JobInfo) bool { + if time.Time(i1.Updated).Equal(time.Time(i2.Updated)) { + return byJobIDAsc(i1, i2) + } + return time.Time(i1.Updated).Before(time.Time(i2.Updated)) +} + +func byUpdatedDesc(i1, i2 *weles.JobInfo) bool { + if time.Time(i1.Updated).Equal(time.Time(i2.Updated)) { + return byJobIDAsc(i1, i2) + } + return time.Time(i1.Updated).After(time.Time(i2.Updated)) +} + +func byStatusAsc(i1, i2 *weles.JobInfo) bool { + if i1.Status.ToInt() == i2.Status.ToInt() { + return byJobIDAsc(i1, i2) + } + return i1.Status.ToInt() < i2.Status.ToInt() +} + +func byStatusDesc(i1, i2 *weles.JobInfo) bool { + if i1.Status.ToInt() == i2.Status.ToInt() { + return byJobIDAsc(i1, i2) + } + return i1.Status.ToInt() > i2.Status.ToInt() +} + +func byJobIDAsc(i1, i2 *weles.JobInfo) bool { + return i1.JobID < i2.JobID +} + +type jobSorter struct { + jobs []weles.JobInfo + by func(i1, i2 *weles.JobInfo) bool +} + +// Len is part of sort.Interface. +func (s *jobSorter) Len() int { + return len(s.jobs) +} + +// Swap is part of sort.Interface. +func (s *jobSorter) Swap(i, j int) { + s.jobs[i], s.jobs[j] = s.jobs[j], s.jobs[i] +} + +// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter. +func (s *jobSorter) Less(i, j int) bool { + return s.by(&s.jobs[i], &s.jobs[j]) +} + +// by is the type of a "less" function that defines the ordering of its JobInfo arguments. +type by func(p1, p2 *weles.JobInfo) bool + +func (s *jobSorter) setByFunction(order weles.SortOrder, asc, desc by) { + switch order { + case weles.SortOrderAscending: + s.by = asc + case weles.SortOrderDescending: + s.by = desc + } +} diff --git a/controller/jobscontrollerimpl_test.go b/controller/jobscontrollerimpl_test.go index 71b4f00..eee83c8 100644 --- a/controller/jobscontrollerimpl_test.go +++ b/controller/jobscontrollerimpl_test.go @@ -22,6 +22,7 @@ import ( "time" . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" strfmt "github.com/go-openapi/strfmt" @@ -479,6 +480,130 @@ var _ = Describe("JobsControllerImpl", func() { }) }) }) + Describe("Sorter", func() { + jobids := []weles.JobID{} + checkOrder := func(result []weles.JobInfo, info weles.ListInfo, expected []weles.JobID, order []int) { + Expect(len(result)).To(Equal(len(expected))) + for i := range result { + ExpectWithOffset(1, result[i].JobID).To(Equal(expected[order[i]])) + } + ExpectWithOffset(1, info.TotalRecords).To(Equal(uint64(len(expected)))) + ExpectWithOffset(1, info.RemainingRecords).To(BeZero()) + } + BeforeEach(func() { + jobids = []weles.JobID{} + elems = 10 + for i := 1; i <= elems; i++ { + j, err := jc.NewJob(yaml) + Expect(err).NotTo(HaveOccurred()) + jobids = append(jobids, j) + } + // Manipulate data so the sort effect will be visible. + jc.(*JobsControllerImpl).mutex.Lock() + defer jc.(*JobsControllerImpl).mutex.Unlock() + jc.(*JobsControllerImpl).jobs[jobids[0]].JobInfo = weles.JobInfo{ + JobID: jobids[0], + Created: strfmt.DateTime(magicDate.AddDate(5, 0, 0)), + Updated: strfmt.DateTime(magicDate.AddDate(3, 0, 0)), + Status: weles.JobStatusNEW, + } + jc.(*JobsControllerImpl).jobs[jobids[1]].JobInfo = weles.JobInfo{ + JobID: jobids[1], + Created: strfmt.DateTime(magicDate.AddDate(4, 0, 0)), + Updated: strfmt.DateTime(magicDate.AddDate(1, 0, 0)), + Status: weles.JobStatusWAITING, + } + jc.(*JobsControllerImpl).jobs[jobids[2]].JobInfo = weles.JobInfo{ + JobID: jobids[2], + Created: strfmt.DateTime(magicDate.AddDate(2, 0, 0)), + Updated: strfmt.DateTime(magicDate.AddDate(2, 0, 0)), + Status: weles.JobStatusCANCELED, + } + jc.(*JobsControllerImpl).jobs[jobids[3]].JobInfo = weles.JobInfo{ + JobID: jobids[3], + Created: strfmt.DateTime(magicDate.AddDate(3, 0, 0)), + Updated: strfmt.DateTime(magicDate.AddDate(4, 0, 0)), + Status: weles.JobStatusPARSING, + } + jc.(*JobsControllerImpl).jobs[jobids[4]].JobInfo = weles.JobInfo{ + JobID: jobids[4], + Created: strfmt.DateTime(magicDate.AddDate(1, 0, 0)), + Updated: strfmt.DateTime(magicDate.AddDate(5, 0, 0)), + Status: weles.JobStatusDOWNLOADING, + } + + jc.(*JobsControllerImpl).jobs[jobids[5]].JobInfo = weles.JobInfo{ + JobID: jobids[5], + Created: strfmt.DateTime(magicDate.AddDate(6, 0, 0)), + Updated: strfmt.DateTime(magicDate.AddDate(6, 0, 0)), + Status: weles.JobStatusRUNNING, + } + jc.(*JobsControllerImpl).jobs[jobids[6]].JobInfo = weles.JobInfo{ + JobID: jobids[6], + Created: strfmt.DateTime(magicDate.AddDate(6, 1, 0)), + Updated: strfmt.DateTime(magicDate.AddDate(6, 1, 0)), + Status: weles.JobStatusFAILED, + } + jc.(*JobsControllerImpl).jobs[jobids[7]].JobInfo = weles.JobInfo{ + JobID: jobids[7], + Created: strfmt.DateTime(magicDate.AddDate(6, 2, 0)), + Updated: strfmt.DateTime(magicDate.AddDate(6, 2, 0)), + Status: weles.JobStatusCOMPLETED, + } + jc.(*JobsControllerImpl).jobs[jobids[8]].JobInfo = weles.JobInfo{ + JobID: jobids[8], + Created: strfmt.DateTime(magicDate.AddDate(6, 3, 0)), + Updated: strfmt.DateTime(magicDate.AddDate(6, 3, 0)), + Status: weles.JobStatus("InvalidJobStatus"), + } + jc.(*JobsControllerImpl).jobs[jobids[9]].JobInfo = weles.JobInfo{ + JobID: jobids[9], + Created: strfmt.DateTime(magicDate.AddDate(1, 0, 0)), + Updated: strfmt.DateTime(magicDate.AddDate(5, 0, 0)), + Status: weles.JobStatusDOWNLOADING, + } + }) + DescribeTable("sorter", + func(s weles.JobSorter, order []int) { + list, info, err := jc.List(weles.JobFilter{}, s, defaultPagination) + Expect(err).NotTo(HaveOccurred()) + checkOrder(list, info, jobids, order) + }, + Entry("should sort by JobID if Sorter is empty", + weles.JobSorter{}, + []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}), + Entry("should sort by JobID if SortBy is invalid", + weles.JobSorter{SortBy: weles.JobSortBy("InvalidSortBy")}, + []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}), + Entry("should sort by JobID if SortBy is CreatedDate and SortOrder is invalid ", + weles.JobSorter{SortBy: weles.JobSortByCreatedDate, SortOrder: weles.SortOrder("InvalidSortOrder")}, + []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}), + Entry("should sort by JobID if SortBy is UpdatedDate and SortOrder is invalid ", + weles.JobSorter{SortBy: weles.JobSortByUpdatedDate, SortOrder: weles.SortOrder("InvalidSortOrder")}, + []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}), + Entry("should sort by JobID if SortBy is Status and SortOrder is invalid ", + weles.JobSorter{SortBy: weles.JobSortByJobStatus, SortOrder: weles.SortOrder("InvalidSortOrder")}, + []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}), + Entry("should sort by CreatedAsc", + weles.JobSorter{SortBy: weles.JobSortByCreatedDate, SortOrder: weles.SortOrderAscending}, + []int{4, 9, 2, 3, 1, 0, 5, 6, 7, 8}), + Entry("should sort by CreatedDesc", + weles.JobSorter{SortBy: weles.JobSortByCreatedDate, SortOrder: weles.SortOrderDescending}, + []int{8, 7, 6, 5, 0, 1, 3, 2, 4, 9}), + Entry("should sort by UpdatedAsc", + weles.JobSorter{SortBy: weles.JobSortByUpdatedDate, SortOrder: weles.SortOrderAscending}, + []int{1, 2, 0, 3, 4, 9, 5, 6, 7, 8}), + Entry("should sort by UpdatesDesc", + weles.JobSorter{SortBy: weles.JobSortByUpdatedDate, SortOrder: weles.SortOrderDescending}, + []int{8, 7, 6, 5, 4, 9, 3, 0, 2, 1}), + Entry("should sort by StatusAsc", + weles.JobSorter{SortBy: weles.JobSortByJobStatus, SortOrder: weles.SortOrderAscending}, + []int{8, 0, 3, 4, 9, 1, 5, 7, 6, 2}), + Entry("should sort by StatusDesc", + weles.JobSorter{SortBy: weles.JobSortByJobStatus, SortOrder: weles.SortOrderDescending}, + []int{2, 6, 7, 5, 1, 4, 9, 3, 0, 8}), + ) + }) }) }) }) diff --git a/job_status_extra.go b/job_status_extra.go new file mode 100644 index 0000000..ed9968f --- /dev/null +++ b/job_status_extra.go @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +// File job_status_extra.go enhances generated JobStatus type. + +package weles + +// ToInt converts JobStatus to int. +func (status JobStatus) ToInt() int { + switch status { + case JobStatusNEW: + return 1 + case JobStatusPARSING: + return 2 + case JobStatusDOWNLOADING: + return 3 + case JobStatusWAITING: + return 4 + case JobStatusRUNNING: + return 5 + case JobStatusCOMPLETED: + return 6 + case JobStatusFAILED: + return 7 + case JobStatusCANCELED: + return 8 + default: + return -1 + } +} |