Commit c67655a
fix(server): own the vuls2 db fetch for the process instead of per request
Server mode created a vuls2 db session per request, so every request
decided for itself whether the db was due for a download and fetched it.
A pod that came up with no db on disk therefore had each arriving request
start its own multi-gigabyte fetch into the same directory, several at a
time, each slow enough to trip the registry's stream limits and start
over.
Hoist the db's lifecycle out of the request path:
- SharedDB downloads the db and keeps it current in the background, and
hands each request a session with SkipUpdate forced on. Only the
goroutine that prepares and refreshes fetches, so a fetch is
single-flight and never blocks a request, and a request can never
become another thing that pulls a db. /health reports 503 until there
is a db to serve and /vuls refuses rather than fetching one of its own.
Point a readiness probe at /health: a liveness probe would restart the
process partway through the first fetch and start it over.
- Each request opens its own handle and carries its own read cache.
Sharing one open handle was tried and reverted: opening the db is an
mmap of a file the page cache already holds, ~50us on a full-size
~11 GB db, while a session shared across requests cannot carry vuls2's
read cache, since that cache never evicts and one outliving a request
would grow until the process is OOM-killed. Going without it makes
enrichment re-read and re-unmarshal the same advisory and vulnerability
records once per root that references them: enriching a 4873-CVE result
measured 2.4s with a cache and 150s without.
- Startup adopts whatever usable db is already on disk before it
considers downloading one, so a process that has a db serves right away
rather than after a full fetch. A refresh that fails leaves the working
db in place.
- A refresh resolves the repository manifest and skips the download when
its digest matches the one recorded in the local db. Going by
timestamps alone, a nightly db past the staleness window looks due on
every check for as long as it lives, which re-fetched gigabytes hourly
even when the tag had not moved.
- Record the db digest on the global config from SharedDB alone rather
than from every session open. Concurrent requests wrote it while
detector.DetectPkgCves read the same global to stamp the result, which
was a data race.
- Size detection workers by GOMAXPROCS rather than NumCPU, which reports
the machine's CPU count even when a cgroup quota lets far fewer of
them run.
- Bound concurrent detections with -max-concurrency (default GOMAXPROCS).
One detection holds every CVE it finds plus a read cache that measured
0.4-0.8 GB on heavy servers, so an unbounded number of them
oversubscribes memory badly enough to stall the server. Requests queue
on it rather than being rejected, and a slot is released only after the
session it admitted has been closed.
Refs #2613
Refs #2615
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent 86d476c commit c67655a
9 files changed
Lines changed: 854 additions & 50 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| 12 | + | |
11 | 13 | | |
12 | 14 | | |
13 | 15 | | |
| |||
24 | 26 | | |
25 | 27 | | |
26 | 28 | | |
27 | | - | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
28 | 41 | | |
29 | 42 | | |
30 | 43 | | |
| |||
70 | 83 | | |
71 | 84 | | |
72 | 85 | | |
73 | | - | |
| 86 | + | |
74 | 87 | | |
75 | 88 | | |
76 | 89 | | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
77 | 142 | | |
78 | 143 | | |
79 | 144 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
184 | 185 | | |
185 | 186 | | |
186 | 187 | | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
3 | 13 | | |
4 | 14 | | |
| 15 | + | |
5 | 16 | | |
6 | 17 | | |
7 | 18 | | |
| |||
0 commit comments