docs: move presign memoization to the done list

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WTdBxLFU5TpwmqVdVsN1wq
This commit is contained in:
Evan Jarrett
2026-09-11 17:19:10 -05:00
co-authored by Claude Opus 4.8
parent 2a94f924af
commit 7ecb09465d
+1 -26
View File
@@ -19,6 +19,7 @@ appview database.
| `034ea59` | Hold reports blob size on read presigns; appview Stat no longer HEADs S3 for it. |
| `f4343d7` | Blobs under 16MB go up as one presigned PUT; every upload is hashed and verified against its digest. |
| `47a1070` | Process-wide budget on upload buffer memory; sweep for abandoned uploads; flush boundary pinned at exactly 16MB. |
| `2a94f92` | Per-request memo of blob presigns; a blob GET is one hold call, not three (Stat, ServeBlob and the notification listener's Stat shared it). |
In flight as of 2026-09-09: the registry reads the sailor profile from the
local users row instead of the owner's PDS on every request, and part uploads
@@ -26,32 +27,6 @@ are pipelined so one part is in flight while the next fills.
## Remaining
### Presign memoization within a request
**Problem.** Every blob GET costs three hold calls, each doing full token
validation, a captain record read and a presign. Distribution's blob handler
calls `Stat` then `ServeBlob`, and distribution's notifications listener
(`notifications.Listen` wraps every repository unconditionally, whether or not
any endpoint is configured) calls `Stat` a third time after `ServeBlob` to
build the pull event. Measured 2026-09-11 with `TestBenchRealImages`: a p90
pull of 22 layers is 22 registry GETs and 66 hold calls, 44 of them HEAD
presigns whose URL is never used.
**Where.** `ProxyBlobStore.Stat` and `ServeBlob` in
`pkg/appview/storage/proxy_blob_store.go`.
**Fix.** The store is built per request, so a small memo keyed by digest and
method inside it is safe. Stat reads the request method from the context
(`storage.HTTPRequestMethod`, already set by the auth middleware), presigns
for that method when it is GET or HEAD, and remembers the URL and size.
ServeBlob reuses the URL when the digest and method match; the listener's
second Stat is answered from the memo. S3 signs the HTTP method, so a HEAD
URL cannot serve a GET; anything other than GET or HEAD must still presign
HEAD, since the hold refuses `method=PUT` on the read path.
**Impact.** One hold call per blob fetch instead of three. On the p90 pull
that is 66 hold calls down to 22.
### Stat from the appview's own layers table
**Problem.** For a layer of an already indexed manifest, the appview's `layers`