| 36 | } |
| 37 | |
| 38 | func (w HTTPClient) GetRuns( |
| 39 | _ context.Context, |
| 40 | from time.Time, |
| 41 | pageSize int, |
| 42 | browserName string, |
| 43 | channelName string, |
| 44 | ) (shared.TestRuns, error) { |
| 45 | //nolint:exhaustruct |
| 46 | // External struct does not need comply with exhaustruct. |
| 47 | apiOptions := shared.TestRunFilter{ |
| 48 | From: &from, |
| 49 | // TODO: Modify the upstream code so that we can use uint instead of int. |
| 50 | MaxCount: &pageSize, |
| 51 | Products: shared.ProductSpecs{ |
| 52 | { |
| 53 | ProductAtRevision: shared.ProductAtRevision{ |
| 54 | Product: shared.Product{ |
| 55 | BrowserName: browserName, |
| 56 | }, |
| 57 | }, |
| 58 | Labels: mapset.NewSetWith(channelName), |
| 59 | }, |
| 60 | }, |
| 61 | } |
| 62 | |
| 63 | allRuns := shared.TestRuns{} |
| 64 | var to *time.Time |
| 65 | var finalIDOfLastPage *int64 |
| 66 | for { |
| 67 | if to != nil { |
| 68 | apiOptions.To = to |
| 69 | } |
| 70 | runs, err := shared.FetchRuns(w.hostname, apiOptions) |
| 71 | if err != nil { |
| 72 | if is404Error(err) { |
| 73 | // No more results |
| 74 | break |
| 75 | } |
| 76 | |
| 77 | return nil, err |
| 78 | } |
| 79 | |
| 80 | lastRunOfPage := runs[len(runs)-1] |
| 81 | // Edge case: |
| 82 | // We are unable to get a page token back to start the next page. So |
| 83 | // there is a possibility that as we manually shift the "to" variable, |
| 84 | // we get the previous page. This can happen if the number of items per |
| 85 | // page equals "pageSize" exactly on every call. To mitigate, we track |
| 86 | // the last ID of the last page. If we see it again, we can stop. |
| 87 | if finalIDOfLastPage != nil && *finalIDOfLastPage == lastRunOfPage.ID { |
| 88 | break |
| 89 | } |
| 90 | |
| 91 | allRuns = append(allRuns, runs...) |
| 92 | |
| 93 | if len(runs) < pageSize { |
| 94 | break |
| 95 | } |