summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukasz Wojciechowski <l.wojciechow@partner.samsung.com>2018-06-11 15:27:59 +0200
committerAlexander Mazuruk <a.mazuruk@samsung.com>2018-07-26 07:32:48 +0200
commitd58291aa7a8ceb67c78404ab67616b013e333a15 (patch)
tree1e7f2c10dd2b39e602d23acd28266cfb52804976
parent31062956851d43e63d3ee61f102d24313732848c (diff)
downloadweles-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.go96
-rw-r--r--controller/jobscontrollerimpl_test.go125
-rw-r--r--job_status_extra.go43
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
+ }
+}