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/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

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

Render issues, changes and the activity feed from the index

14b5c648a04090d0e718f5920f6abfc2d14c7274 · Keenan Nemetz · 10d ago · parent 9d8dd1bc

Render issues, changes and the activity feed from the index

Stage 3: the pages that still read the metadata branch now read the rows
the request already refreshed.

- The issue page reads its issue, comments, labels, assignees and number
  from the index. Its one remaining git read is the backlink search
  (`log --grep`), which is a content search, not a record lookup.
- A change page reads its one request from the index for a GET. A write
  request still reads git: it has no memo because it may have just
  changed the record, and it must not be answered by the version it
  replaced.
- The activity feed builds its issue, change, comment and approval events
  from the index. It keeps the metadata log for state changes (a reopened
  issue is two events and the file only knows the last), the latest
  commit, and tags: the remaining git calls are content, not duplicates.

Git calls per page on the fixture (40 files, 30 issues, 30 changes):

  issue view     7 -> 3
  change view   12 -> 9
  activity      whole-tree reads -> one log, one commit, one tag listing

The change page's remaining calls are the diff and the merge check; the
issue page's are the backlink search.

server/web/memo.go +23−3

@@ -20,6 +20,7 @@ import (
20 20 "net/http"
21 21 "sync"
22 22
23 "github.com/rodent-software/vole/forge/index"
23 24 "github.com/rodent-software/vole/forge/repo"
24 25 "github.com/rodent-software/vole/metadata"
25 26 )
@@ -174,10 +175,17 @@ func (w *Web) requestsAt(memo *requestMemo, m *repo.Meta) ([]*metadata.Request,
174 175 return list, err
175 176 }
176 177
177 // requestAt returns one change request, reading that request's files rather
178 // than every request on the branch. It uses the request's resolved metadata
179 // commit, so a page that also refreshes the index resolves the ref once.
178 // requestAt returns one change request for rendering. A read request uses the
179 // index, which ensureIndex refreshes to the branch's current commit. A write
180 // request reads git instead: it has no memo because it may have just changed the
181 // record, and it must not be answered by the version it replaced.
180 182 func (w *Web) requestAt(memo *requestMemo, m *repo.Meta, id string) (*metadata.Request, error) {
183 if w.Index != nil && memo != nil {
184 if err := w.ensureIndex(memo, m); err != nil {
185 return nil, err
186 }
187 return w.Index.Request(m.ID, id)
188 }
181 189 head, err := w.metadataHead(memo, m)
182 190 if err != nil {
183 191 return nil, err
@@ -191,3 +199,15 @@ func (w *Web) requestAt(memo *requestMemo, m *repo.Meta, id string) (*metadata.R
191 199 }
192 200 return req, nil
193 201 }
202
203 // issueAt returns one issue for rendering, on the same rule: the index for a
204 // read request, git for a write or a Web without an index.
205 func (w *Web) issueAt(memo *requestMemo, m *repo.Meta, id string) (*metadata.Issue, error) {
206 if w.Index != nil && memo != nil {
207 if err := w.ensureIndex(memo, m); err != nil {
208 return nil, err
209 }
210 return w.Index.Issue(m.ID, id)
211 }
212 return index.LoadIssue(m, id)
213 }