These are split up by endpoint since it is along that boundary we parallelize work Populate .Mentions
()
| 262 | |
| 263 | // Populate .Mentions |
| 264 | func (s *StatusGetter) LoadNotifications() error { |
| 265 | perPage := 100 |
| 266 | c := api.NewClientFromHTTP(s.Client) |
| 267 | query := url.Values{} |
| 268 | query.Add("per_page", fmt.Sprintf("%d", perPage)) |
| 269 | query.Add("participating", "true") |
| 270 | query.Add("all", "true") |
| 271 | |
| 272 | fetchWorkers := 10 |
| 273 | ctx, abortFetching := context.WithCancel(context.Background()) |
| 274 | defer abortFetching() |
| 275 | toFetch := make(chan Notification) |
| 276 | fetched := make(chan StatusItem) |
| 277 | |
| 278 | wg := new(errgroup.Group) |
| 279 | for i := 0; i < fetchWorkers; i++ { |
| 280 | wg.Go(func() error { |
| 281 | for { |
| 282 | select { |
| 283 | case <-ctx.Done(): |
| 284 | return nil |
| 285 | case n, ok := <-toFetch: |
| 286 | if !ok { |
| 287 | return nil |
| 288 | } |
| 289 | actual, err := s.ActualMention(n.Subject.LatestCommentURL) |
| 290 | |
| 291 | if err != nil { |
| 292 | var httpErr api.HTTPError |
| 293 | httpStatusCode := -1 |
| 294 | |
| 295 | if errors.As(err, &httpErr) { |
| 296 | httpStatusCode = httpErr.StatusCode |
| 297 | } |
| 298 | |
| 299 | switch httpStatusCode { |
| 300 | case 403: |
| 301 | s.addAuthError(httpErr.Message, factory.SSOURL()) |
| 302 | case 404: |
| 303 | return nil |
| 304 | default: |
| 305 | abortFetching() |
| 306 | return fmt.Errorf("could not fetch comment: %w", err) |
| 307 | } |
| 308 | } |
| 309 | |
| 310 | if actual != "" { |
| 311 | // I'm so sorry |
| 312 | split := strings.Split(n.Subject.URL, "/") |
| 313 | fetched <- StatusItem{ |
| 314 | Repository: n.Repository.FullName, |
| 315 | Identifier: fmt.Sprintf("%s#%s", n.Repository.FullName, split[len(split)-1]), |
| 316 | preview: actual, |
| 317 | index: n.index, |
| 318 | } |
| 319 | } |
| 320 | } |
| 321 | } |
no test coverage detected