示例#1
0
func pollMonth(env task.Env, month string, cc bool) (pt []*task.PolledTask, err error) {
	c := env.HTTPClient()
	cursor := ""
	n := 0
	var (
		metawg  sync.WaitGroup // for meta or metaerr to be loaded
		meta    monthMeta
		metaerr error
	)

	metawg.Add(1)
	go func() {
		defer metawg.Done()
		meta, metaerr = getMonthMeta(env, month)
	}()

	// Opens issue to rietveld, even if they're logically closed
	// (R=closed) to us.
	var rietOpen []*Review

	for {
		query := monthQuery
		if cc {
			query = monthQueryCC
		}
		url := urlWithParams(query, map[string]string{
			"DATE_AFTER":  month + "-01 00:00:00",
			"DATE_BEFORE": monthAfter(month) + "-01 00:00:00",
			"CURSOR":      cursor,
			"LIMIT":       fmt.Sprint(itemsPerPage),
		})
		n++
		env.Logf("Fetching codereview page %d: %s", n, url)
		res, err := c.Get(url)
		if err != nil {
			env.Logf("Error fetching %s: %v", url, err)
			return nil, err
		}
		var reviews []*Review
		reviews, cursor, err = ParseReviews(res.Body)
		res.Body.Close()
		if err != nil {
			env.Logf("ParseReviews error: %v", err)
			return nil, err
		}
		env.Logf("got %d reviews, cursor is %q", len(reviews), cursor)
		for _, r := range reviews {
			if r.Issue == 0 {
				env.Logf("bogus issue %+v", r)
				continue
			}
			rietOpen = append(rietOpen, r)
		}
		if cursor == "" || len(reviews) < itemsPerPage {
			break
		}
	}

	metawg.Wait()
	if metaerr != nil {
		env.Logf("Error loading month meta for %q: %v", month, metaerr)
		return nil, metaerr
	}

	// For each issue that Rietveld believes to be open, see if we
	// have the latest comments for it and then see if it's
	// actually logically still open, based on its comments.
	var updates []chan issueMeta
	for _, r := range rietOpen {
		im := meta[r.Issue]
		if im.policyVersion != policyVersion || im.lastModified != r.Modified {
			env.Logf("Need to summarize issue %d", r.Issue)
			ch := make(chan issueMeta, 1)
			updates = append(updates, ch)
			go func(issueId int) {
				ch <- summarizeIssue(env, issueId)
			}(r.Issue)
		} else {
			env.Logf("Issue %d is unmodified.", r.Issue)
		}
	}
	var updateErr error
	var errCount int
	for _, ch := range updates {
		im := <-ch
		if im.err != nil {
			errCount++
			if updateErr == nil {
				updateErr = im.err
			}
		} else {
			meta[im.issue] = im
		}
	}
	if updateErr != nil {
		// Save what we've got so far.
		env.Logf("Errors re-fetching month %q: %d/%d fetches failed. Saving %d good issue summaries.", month, errCount, len(updates), len(meta))
		env.SetMeta(monthMetaPrefix+month, meta.serialize())
		return nil, updateErr
	}
	if len(updates) > 0 {
		if err := env.SetMeta(monthMetaPrefix+month, meta.serialize()); err != nil {
			env.Logf("Error writing month meta for %q: %v", month, err)
			return nil, err
		}
	}
	for _, r := range rietOpen {
		im := meta[r.Issue]
		if im.reviewer == "close" {
			continue
		}
		ownerHint := im.reviewer
		if ownerHint == "" {
			ownerHint = r.Reviewer()
		}
		t := &task.PolledTask{
			ID:        fmt.Sprint(r.Issue),
			Title:     r.Desc,
			OwnerHint: ownerHint,
		}
		pt = append(pt, t)
	}

	env.Logf("codereview: for month %q, returning %d open tasks", month, len(pt))
	return pt, nil
}