labelEvent.go

 1package iterator
 2
 3import (
 4	"context"
 5	"sort"
 6
 7	"github.com/xanzy/go-gitlab"
 8)
 9
10// Since Gitlab does not return the label events items in the correct order
11// we need to sort the list ourselves and stop relying on the pagination model
12// #BecauseGitlab
13type labelEventIterator struct {
14	issue int
15	index int
16	cache []*gitlab.LabelEvent
17}
18
19func newLabelEventIterator() *labelEventIterator {
20	lei := &labelEventIterator{}
21	lei.Reset(-1)
22	return lei
23}
24
25func (lei *labelEventIterator) Next(ctx context.Context, conf config) (bool, error) {
26	// first query
27	if lei.cache == nil {
28		return lei.getNext(ctx, conf)
29	}
30
31	// move cursor index
32	if lei.index < len(lei.cache)-1 {
33		lei.index++
34		return true, nil
35	}
36
37	return false, nil
38}
39
40func (lei *labelEventIterator) Value() *gitlab.LabelEvent {
41	return lei.cache[lei.index]
42}
43
44func (lei *labelEventIterator) getNext(ctx context.Context, conf config) (bool, error) {
45	ctx, cancel := context.WithTimeout(ctx, conf.timeout)
46	defer cancel()
47
48	// since order is not guaranteed we should query all label events
49	// and sort them by ID
50	page := 1
51	for {
52		labelEvents, _, err := conf.gc.ResourceLabelEvents.ListIssueLabelEvents(
53			conf.project,
54			lei.issue,
55			&gitlab.ListLabelEventsOptions{
56				ListOptions: gitlab.ListOptions{
57					Page:    page,
58					PerPage: conf.capacity,
59				},
60			},
61			gitlab.WithContext(ctx),
62		)
63		if err != nil {
64			lei.Reset(-1)
65			return false, err
66		}
67
68		if len(labelEvents) == 0 {
69			break
70		}
71		lei.cache = append(lei.cache, labelEvents...)
72		page++
73	}
74
75	sort.Sort(lei)
76	lei.index = 0
77
78	return len(lei.cache) > 0, nil
79}
80
81func (lei *labelEventIterator) Reset(issue int) {
82	lei.issue = issue
83	lei.index = -1
84	lei.cache = nil
85}
86
87// ORDERING
88
89func (lei *labelEventIterator) Len() int {
90	return len(lei.cache)
91}
92
93func (lei *labelEventIterator) Swap(i, j int) {
94	lei.cache[i], lei.cache[j] = lei.cache[j], lei.cache[i]
95}
96
97func (lei *labelEventIterator) Less(i, j int) bool {
98	return lei.cache[i].ID < lei.cache[j].ID
99}