OLD | NEW |
1 package search | 1 package search |
2 | 2 |
3 import ( | 3 import ( |
4 "fmt" | 4 "fmt" |
| 5 "sort" |
5 "strconv" | 6 "strconv" |
6 "strings" | 7 "strings" |
7 "sync" | 8 "sync" |
8 | 9 |
9 "go.skia.org/infra/golden/go/storage" | 10 "go.skia.org/infra/golden/go/storage" |
10 "go.skia.org/infra/golden/go/trybot" | 11 "go.skia.org/infra/golden/go/trybot" |
11 ) | 12 ) |
12 | 13 |
13 // TrybotIssue is the output structure for a Rietveld issue that has | 14 // TrybotIssue is the output structure for a Rietveld issue that has |
14 // trybot runs assoicated with it. | 15 // trybot runs assoicated with it. |
15 type TrybotIssue struct { | 16 type TrybotIssue struct { |
16 » ID int64 `json:"id"` | 17 » ID int64 `json:"id"` |
17 » Subject string `json:"subject"` | 18 » Subject string `json:"subject"` |
18 » Owner string `json:"owner"` | 19 » Owner string `json:"owner"` |
19 » Updated int64 `json:"updated"` | 20 » Updated int64 `json:"updated"` |
20 » URL string `json:"url"` | 21 » URL string `json:"url"` |
| 22 » CurrentPatchset int `json:"currentPatchset"` |
21 } | 23 } |
22 | 24 |
23 // ListTrybotIssues returns the most recently updated trybot issues in reverse | 25 // ListTrybotIssues returns the most recently updated trybot issues in reverse |
24 // chronological order. offset and size determine the page and size of the | 26 // chronological order. offset and size determine the page and size of the |
25 // returned list. The second return value is the total number of items | 27 // returned list. The second return value is the total number of items |
26 // available to facilitate pagination. | 28 // available to facilitate pagination. |
27 func ListTrybotIssues(storages *storage.Storage, offset, size int) ([]*TrybotIss
ue, int, error) { | 29 func ListTrybotIssues(storages *storage.Storage, offset, size int) ([]*TrybotIss
ue, int, error) { |
28 issueInfos, total, err := storages.TrybotResults.List(offset, size) | 30 issueInfos, total, err := storages.TrybotResults.List(offset, size) |
29 if err != nil { | 31 if err != nil { |
30 return nil, 0, err | 32 return nil, 0, err |
31 } | 33 } |
32 | 34 |
33 if len(issueInfos) == 0 { | 35 if len(issueInfos) == 0 { |
34 return []*TrybotIssue{}, 0, nil | 36 return []*TrybotIssue{}, 0, nil |
35 } | 37 } |
36 | 38 |
37 ch := make(chan error, len(issueInfos)) | 39 ch := make(chan error, len(issueInfos)) |
38 var wg sync.WaitGroup | 40 var wg sync.WaitGroup |
39 retMap := map[string]*TrybotIssue{} | 41 retMap := map[string]*TrybotIssue{} |
40 var mutex sync.Mutex | 42 var mutex sync.Mutex |
41 | 43 |
42 for _, issueInfo := range issueInfos { | 44 for _, issueInfo := range issueInfos { |
43 wg.Add(1) | 45 wg.Add(1) |
44 go func(issueInfo *trybot.IssueListItem) { | 46 go func(issueInfo *trybot.IssueListItem) { |
45 defer wg.Done() | 47 defer wg.Done() |
46 | 48 |
47 » » » intIssueId, err := strconv.Atoi(issueInfo.Issue) | 49 » » » intIssueId, err := strconv.ParseInt(issueInfo.Issue, 10,
64) |
48 if err != nil { | 50 if err != nil { |
49 ch <- fmt.Errorf("Unable to parse issue id %s. G
ot error: %s", issueInfo.Issue, err) | 51 ch <- fmt.Errorf("Unable to parse issue id %s. G
ot error: %s", issueInfo.Issue, err) |
50 return | 52 return |
51 } | 53 } |
52 result, err := storages.RietveldAPI.GetIssueProperties(i
nt64(intIssueId), false) | 54 result, err := storages.RietveldAPI.GetIssueProperties(i
nt64(intIssueId), false) |
53 if err != nil { | 55 if err != nil { |
54 ch <- fmt.Errorf("Error retrieving rietveld info
rmaton for issue: %s: %s", issueInfo.Issue, err) | 56 ch <- fmt.Errorf("Error retrieving rietveld info
rmaton for issue: %s: %s", issueInfo.Issue, err) |
55 return | 57 return |
56 } | 58 } |
57 | 59 |
| 60 // Retrieve the owner via the patchset via Rietveld. |
| 61 owner := result.Owner |
| 62 if len(result.Patchsets) > 0 { |
| 63 ps, err := storages.RietveldAPI.GetPatchset(intI
ssueId, result.Patchsets[0]) |
| 64 if err != nil { |
| 65 ch <- fmt.Errorf("Error retrieving patch
set %d for issue %s: %s", result.Patchsets[0], issueInfo.Issue, err) |
| 66 return |
| 67 } |
| 68 owner = ps.OwnerEmail |
| 69 } |
| 70 |
58 ret := &TrybotIssue{ | 71 ret := &TrybotIssue{ |
59 » » » » ID: result.Issue, | 72 » » » » ID: result.Issue, |
60 » » » » Owner: result.Owner, | 73 » » » » Owner: owner, |
61 » » » » Subject: result.Subject, | 74 » » » » Subject: result.Subject, |
62 » » » » Updated: result.Modified.Unix(), | 75 » » » » Updated: result.Modified.Unix(), |
63 » » » » URL: strings.TrimSuffix(storages.RietveldAPI
.Url(), "/") + fmt.Sprintf("/%d", result.Issue), | 76 » » » » URL: strings.TrimSuffix(storages.Rie
tveldAPI.Url(), "/") + fmt.Sprintf("/%d", result.Issue), |
| 77 » » » » CurrentPatchset: sort.Search(len(result.Patchset
s), func(i int) bool { return result.Patchsets[i] >= issueInfo.MaxPatchset }) +
1, |
64 } | 78 } |
65 | 79 |
66 mutex.Lock() | 80 mutex.Lock() |
67 retMap[issueInfo.Issue] = ret | 81 retMap[issueInfo.Issue] = ret |
68 mutex.Unlock() | 82 mutex.Unlock() |
69 | 83 |
70 }(issueInfo) | 84 }(issueInfo) |
71 } | 85 } |
72 wg.Wait() | 86 wg.Wait() |
73 close(ch) | 87 close(ch) |
74 | 88 |
75 for err := range ch { | 89 for err := range ch { |
76 return nil, 0, err | 90 return nil, 0, err |
77 } | 91 } |
78 | 92 |
79 ret := make([]*TrybotIssue, 0, len(retMap)) | 93 ret := make([]*TrybotIssue, 0, len(retMap)) |
80 for _, issueInfo := range issueInfos { | 94 for _, issueInfo := range issueInfos { |
81 ret = append(ret, retMap[issueInfo.Issue]) | 95 ret = append(ret, retMap[issueInfo.Issue]) |
82 } | 96 } |
83 | 97 |
84 return ret, total, nil | 98 return ret, total, nil |
85 } | 99 } |
OLD | NEW |