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.

Read what a page needs once per request

5d440e37f16d06790ce87e2f8b7dcc7d9bf0532c · Keenan Nemetz · 10d ago · parent 34cbc99f

Read what a page needs once per request

A page and its header are built from the same facts, and each of them was
read separately: the repository (twice, each resolving HEAD's branch with
a git call), the open change requests (once for the header's count, once
for the page), and a change request looked up by reading every request.
On a repository with 30 change requests the overview paid 21 git
invocations after the metadata batching, and the requests list still paid
8.

Give each read request one memo, installed by the middleware, and have the
handlers and the header read through it. It lasts one request and covers
reads only: a request that writes metadata gets no memo, so there is no
TTL, no cross-request cache, and no invalidation protocol, and a push is
still visible on the next page load.

The header now takes the page it is rendering (`nav .Page "issues"`)
instead of six fields the view already carries, which is also why the memo
can reach it at all. Templates are unchanged in what they output.

server/web/overview.go +3−4

@@ -19,7 +19,6 @@ import (
19 19 "github.com/rodent-software/vole/forge/index"
20 20 "github.com/rodent-software/vole/forge/repo"
21 21 "github.com/rodent-software/vole/internal/format"
22 "github.com/rodent-software/vole/metadata"
23 22 )
24 23
25 24 // maxReadmeBytes is the largest README rendered on the overview. A file past it
@@ -101,7 +100,7 @@ func (w *Web) Overview(rw http.ResponseWriter, r *http.Request) {
101 100 recentRuns, _ = w.Runs.Recent(m.Name, 5)
102 101 }
103 102
104 recentIssues, recentRequests := w.overviewRecent(m)
103 recentIssues, recentRequests := w.overviewRecent(memoOf(r), m)
105 104
106 105 readme, readmeName := w.readmeAt(m, ref, commit)
107 106
@@ -140,7 +139,7 @@ func (w *Web) Overview(rw http.ResponseWriter, r *http.Request) {
140 139 // overview sidebar. Closed and merged records are history and already have a
141 140 // home in their own lists; the overview is a map of what is still being worked
142 141 // on. A failed read leaves an empty section rather than failing the README page.
143 func (w *Web) overviewRecent(m *repo.Meta) (issues, requests []overviewEntity) {
142 func (w *Web) overviewRecent(memo *requestMemo, m *repo.Meta) (issues, requests []overviewEntity) {
144 143 var numbers map[string]int
145 144 if w.Index != nil {
146 145 if err := w.Index.Ensure(m); err == nil {
@@ -157,7 +156,7 @@ func (w *Web) overviewRecent(m *repo.Meta) (issues, requests []overviewEntity) {
157 156 }
158 157 }
159 158 }
160 if list, err := metadata.LoadRequests(m.Git(), metadata.Ref); err == nil {
159 if list, err := w.requestsAt(memo, m); err == nil {
161 160 for _, req := range list {
162 161 if req.Open() {
163 162 requests = append(requests, overviewEntity{