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.

Blame · server/lfs_scope.go

Line attribution on main · 65 line(s)

65b88b3b
Keenan Nemetz
16d ago
1 package server
2
3 // Repository-scoped object storage needs a link per (repository, object). An instance
4 // that predates it has the pool and nothing else, so every LFS fetch would 404 until
3abbe749
Keenan Nemetz
16d ago
5 // somebody knew to run `vole admin gc`. Rather than make that an upgrade note people skip, the
65b88b3b
Keenan Nemetz
16d ago
6 // server notices a store with no namespace and links it in the background on first boot.
7 //
8 // It is the safe half of gc: `Link` creates links and deletes nothing, so a pass that is
9 // interrupted leaves the store more reachable than it found it, and the next start simply
10 // finishes the job.
11
12 import (
13 "os"
14 "time"
15
d37d301f
Keenan Nemetz
15h ago
16 "rodent.software/vole/ci/runs"
17 "rodent.software/vole/forge"
65b88b3b
Keenan Nemetz
16d ago
18 )
19
20 // scopeLFSStore links an unscoped store into per-repository namespaces, in the
21 // background. It does nothing once a namespace exists, which is the marker.
22 func (s *Server) scopeLFSStore() {
23 if s.LFS == nil || s.LFS.NamespaceExists() {
24 return
25 }
26 go func() {
27 start := time.Now()
28 repos, err := s.Repos.List()
29 if err != nil {
30 s.Log.Warn("lfs: cannot list repositories for the scoping pass", "err", err)
31 return
32 }
33 if len(repos) == 0 {
34 return
35 }
c5902451
Keenan Nemetz
16d ago
36 scan := make([]forge.GCRepo, 0, len(repos))
65b88b3b
Keenan Nemetz
16d ago
37 for _, m := range repos {
c5902451
Keenan Nemetz
16d ago
38 scan = append(scan, forge.GCRepo{Name: m.Name, Dir: m.Dir})
65b88b3b
Keenan Nemetz
16d ago
39 }
5ece70a5
Keenan Nemetz
10d ago
40 // Run artifacts are roots too, and they belong to the repository whose run
41 // produced them.
65b88b3b
Keenan Nemetz
16d ago
42 runOIDs := map[string][]string{}
43 if _, err := os.Stat(s.Cfg.RunsDB()); err == nil {
44 if rn, err := runs.Open(s.Cfg.RunsDB()); err == nil {
45 if arts, err := rn.ArtifactOIDs(); err == nil {
46 for repo, oids := range arts {
47 runOIDs[repo] = append(runOIDs[repo], oids...)
48 }
49 }
50 rn.Close()
51 }
52 }
c5902451
Keenan Nemetz
16d ago
53 res, err := forge.GCLink(forge.GCOptions{Repos: scan, Store: s.LFS, RunOIDs: runOIDs})
65b88b3b
Keenan Nemetz
16d ago
54 if err != nil {
55 s.Log.Error("lfs: the store could not be linked to repositories; "+
3abbe749
Keenan Nemetz
16d ago
56 "objects stay unfetchable until `vole admin gc` succeeds", "err", err)
65b88b3b
Keenan Nemetz
16d ago
57 return
58 }
59 s.Log.Info("lfs: linked objects into per-repository storage",
60 "repos", len(scan), "objects", res.Linked, "took", time.Since(start).Round(time.Millisecond))
61 for _, p := range res.Problems {
62 s.Log.Warn("lfs: link", "problem", p)
63 }
64 }()
65 }