Summary
On the Maven proxy download path, merge_and_cache_proxy_metadata re-writes maven-metadata.xml and its four checksum sidecars on every cache-miss/stale revalidation, even when the merged document is byte-identical to what is already stored. It reads the cached document but the subsequent storage.put + compute_and_store_checksums are unconditional — there is no data != cached guard.
Impact
- With
metadata_ttl = 0 (revalidate-every-pull) or after TTL expiry, each metadata GET does 5 storage writes (1 doc + 4 checksums). A Maven client resolving a dependency fetches maven-metadata.xml then its checksum(s), so one resolution can trigger two full merges = up to 10 writes.
- On object-store backends (S3/GCS) that is real PUT cost + latency on a hot path, mostly for no-op rewrites (the merged bytes usually don't change between revalidations).
- Bounded by
metadata_ttl (a positive TTL serves from cache without writes), so this is a cost/latency regression under low/zero TTL, not a correctness issue.
Evidence (main @ 0644178)
nora-registry/src/registry/maven.rs, merge_and_cache_proxy_metadata:
- L1053
let cached = state.storage.get(&key).await.ok(); — cached already available
- L1075
state.storage.put(&key, &data).await — unconditional
- L1078
compute_and_store_checksums(&state.storage, &key, &data).await — unconditional (4 more puts)
Suggested fix
Skip the writes when the merged document equals the cached bytes:
if cached.as_deref() != Some(data.as_ref()) { put + compute_and_store_checksums }
(the cached value is already read, so the guard is nearly free). Optionally move checksum computation off the synchronous serve path.
Introduced by #885 (reland #887). Minor — not a blocker.
Summary
On the Maven proxy download path,
merge_and_cache_proxy_metadatare-writesmaven-metadata.xmland its four checksum sidecars on every cache-miss/stale revalidation, even when the merged document is byte-identical to what is already stored. It reads the cached document but the subsequentstorage.put+compute_and_store_checksumsare unconditional — there is nodata != cachedguard.Impact
metadata_ttl = 0(revalidate-every-pull) or after TTL expiry, each metadata GET does 5 storage writes (1 doc + 4 checksums). A Maven client resolving a dependency fetchesmaven-metadata.xmlthen its checksum(s), so one resolution can trigger two full merges = up to 10 writes.metadata_ttl(a positive TTL serves from cache without writes), so this is a cost/latency regression under low/zero TTL, not a correctness issue.Evidence (main @ 0644178)
nora-registry/src/registry/maven.rs,merge_and_cache_proxy_metadata:let cached = state.storage.get(&key).await.ok();— cached already availablestate.storage.put(&key, &data).await— unconditionalcompute_and_store_checksums(&state.storage, &key, &data).await— unconditional (4 more puts)Suggested fix
Skip the writes when the merged document equals the cached bytes:
if cached.as_deref() != Some(data.as_ref()) { put + compute_and_store_checksums }(the
cachedvalue is already read, so the guard is nearly free). Optionally move checksum computation off the synchronous serve path.Introduced by #885 (reland #887). Minor — not a blocker.