Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Stop repeating the index check and the history summaries

73ec800beafe53eea186fbc1cebec3306cc49da0 · Keenan Nemetz · 10d ago · parent 5d440e37

Stop repeating the index check and the history summaries

The request memo covered the repository, the open counts and the change
list, but two more reads were repeated:

- The index refresh (issue rows, filters, `#42` numbers) ran on every
  surface that shows one, and each run started by resolving the metadata
  ref. A page calls it from the header, the number lookup and its own
  view, so it now happens once per request, and the resolved commit is
  shared with the change-request read instead of being resolved twice.
- The overview walked the repository's whole history on every load:
  `shortlog` for contributors, `rev-list --count` for the code page's
  commit count, and the tree grouping for languages. Those are properties
  of a commit, and a commit id is content-addressed, so they cannot go
  stale: they are remembered by commit id in a bounded per-process cache
  that evicts oldest-first.

On the fixture (30 change requests, 30 issues) the overview drops from 19
git calls to 9 on a repeated load, the code page from 12 to 11, and every
page loses one `rev-parse` for the metadata ref.

server/web/request_view.go +5−5

@@ -381,22 +381,22 @@ func (w *Web) requestSidebar(r *http.Request, m *repo.Meta, req *metadata.Reques
381 381 v.BaseOptions = branchOptions(branches, req.Base)
382 382 v.HeadOptions = branchOptions(headBranches(branches, acl, who), req.HeadRef)
383 383 }
384 nums := w.entityNumbers(m)
384 nums := w.entityNumbers(memoOf(r), m)
385 385 v.Number = nums[req.ID]
386 v.LinkedIssues = w.requestLinkedIssues(m, req, nums)
386 v.LinkedIssues = w.requestLinkedIssues(memoOf(r), m, req, nums)
387 387 return v
388 388 }
389 389
390 390 // requestLinkedIssues reads the issues a request promises to close. The index
391 391 // supplies the rows the overview uses, and a row the index cannot name is read
392 392 // from the issue itself rather than dropped: the request still holds the link.
393 func (w *Web) requestLinkedIssues(m *repo.Meta, req *metadata.Request, nums map[string]int) []requestIssue {
393 func (w *Web) requestLinkedIssues(memo *requestMemo, m *repo.Meta, req *metadata.Request, nums map[string]int) []requestIssue {
394 394 if len(req.Closes) == 0 {
395 395 return nil
396 396 }
397 397 rows := make(map[string]index.IssueRow, len(req.Closes))
398 398 if w.Index != nil {
399 if err := w.Index.Ensure(m); err == nil {
399 if err := w.ensureIndex(memo, m); err == nil {
400 400 if list, err := w.Index.Issues(m.ID, index.Filter{State: "all"}); err == nil {
401 401 for _, row := range list {
402 402 rows[row.ID] = row
@@ -474,7 +474,7 @@ func (w *Web) SearchRequestIssues(rw http.ResponseWriter, r *http.Request) {
474 474 w.render(rw, "request_issue_search", view, 0)
475 475 return
476 476 }
477 if err := w.Index.Ensure(m); err != nil {
477 if err := w.ensureIndex(memoOf(r), m); err != nil {
478 478 if w.Logger != nil {
479 479 w.Logger("web: issue search index for %s: %v", m.Name, err)
480 480 }